File Coverage

blib/lib/App/ghmulti.pm
Criterion Covered Total %
statement 40 83 48.1
branch 7 38 18.4
condition 1 10 10.0
subroutine 13 21 61.9
pod 0 11 0.0
total 61 163 37.4


line stmt bran cond sub pod time code
1             package App::ghmulti;
2              
3 5     5   463215 use 5.010;
  5         20  
4 5     5   37 use strict;
  5         11  
  5         180  
5 5     5   26 use warnings;
  5         11  
  5         384  
6              
7 5     5   33 use Carp;
  5         14  
  5         478  
8              
9 5     5   2997 use GitHub::Config::SSH::UserData qw(get_user_data_from_ssh_cfg);
  5         172116  
  5         513  
10 5     5   3025 use Git::RemoteURL::Parse qw(parse_git_remote_url);
  5         9821  
  5         423  
11              
12              
13 5     5   2748 use Getopt::Std;
  5         12154  
  5         2603  
14             # If set to true, exit script after processing --help or --version flags
15             $Getopt::Std::STANDARD_HELP_VERSION = 1;
16              
17 5     5   3398 use Pod::Usage;
  5         447603  
  5         7135  
18              
19             our $VERSION = '0.06';
20              
21              
22             sub run {
23 3     3 0 237907 my %opts;
24 3 50       27 getopts('cu', \%opts ) or pod2usage(2);
25              
26 1 50       69 usr_error("Too many options") if keys(%opts) > 1;
27              
28 1 50       4 if ($opts{u}) {
    0          
29 1 50       6 my $url = @ARGV ? shift(@ARGV) : get_remote_url();
30 1 50       3 usr_error("Too many arguments @ARGV") if @ARGV;
31 1         7 print (get_ssh_url($url), "\n");
32             } elsif ($opts{c}) {
33 0 0       0 usr_error("Missing URL") if !@ARGV;
34 0 0       0 usr_error("Too many arguments") if @ARGV > 2;
35 0         0 clone_repo(@ARGV);
36             } else {
37 0 0       0 usr_error("Too many arguments") if @ARGV;
38 0         0 config_existing_repo();
39             }
40             }
41              
42              
43             #
44             # clone_repo GITHUB_REPO, DIR
45             # clone_repo GITHUB_REPO
46             #
47             # Clones GITHUB_REPO and configures the local clone with the data from ‘~/.ssh/config’.
48             #
49             sub clone_repo {
50 0     0 0 0 my ($url, $dir) = @_;
51 0 0       0 exit_with_msg("You are in a git repo", 1) if in_git_repo();
52 0         0 my ($uname, $repo) = get_data_from_gh_url($url);
53 0   0     0 $dir //= $repo;
54 0         0 my $user_data = get_user_data_from_ssh_cfg($uname);
55 0         0 run_cmd("git clone " . get_ssh_url($url) . " $dir");
56 0         0 chdir($dir);
57 0         0 config_user_data($user_data);
58 0         0 chdir("..");
59             }
60              
61              
62             #
63             # config_existing_repo
64             #
65             # Configures the current git repo with the data from ‘~/.ssh/config’. If the
66             # remote url is already in 'git@github-...' the function prints a message and
67             # does nothing.
68             #
69             sub config_existing_repo {
70 0     0 0 0 my $url = get_remote_url();
71 0 0       0 exit_with_msg("Remote URL is already 'git\@github-' format") if ($url =~ /^git\@github-/);
72 0         0 my ($uname, undef) = get_data_from_gh_url($url);
73 0         0 my $user_data = get_user_data_from_ssh_cfg($uname);
74 0         0 run_cmd("git remote set-url origin " . get_ssh_url($url));
75 0         0 config_user_data($user_data);
76             }
77              
78              
79              
80             #
81             # get_ssh_url GITHUB_URL
82             #
83             # Changes GITHUB_URL in our 'git\@github-...' format and returns the result.
84             #
85             sub get_ssh_url {
86 1     1 0 2 my $url = shift;
87 1 50       5 return $url if ($url =~ /^git\@github-/);
88 1         5 my ($uname, $repo) = get_data_from_gh_url($url);
89 1         104 return "git\@github-$uname:$uname/$repo.git";
90             }
91              
92              
93             #
94             # get_data_from_gh_url GITHUB_URL
95             #
96             # Returns a two-element list containing user name and repo taken from GITHUB_URL.
97             #
98             sub get_data_from_gh_url {
99 1     1 0 2 my $url = shift;
100 1   33     9 my $data = parse_git_remote_url($url) // croak("$url: unrecognized URL");
101 1 50       30 croak("$data->{service}: non-github service. Not supported.") if $data->{service} ne 'github';
102 1         7 return ($data->{user}, $data->{repo});
103             }
104              
105              
106             #
107             # in_git_repo
108             #
109             # Returns a boolean that flags if you are in a git repo.
110             #
111             sub in_git_repo {
112 0     0 0 0 `git status 2>&1`;
113 0         0 return $? == 0;
114             }
115              
116              
117             #
118             # get_remote_url
119             #
120             # Returns the remote url. If you are not in a git repo, the sub terminates
121             # with an error message.
122             #
123             sub get_remote_url {
124 0 0   0 0 0 exit_with_msg("Not in a git repo", 1) unless in_git_repo();
125 0         0 my $url = `git remote get-url origin`;
126 0 0       0 if ($?) {
127 0         0 die("Failed to execute get-url");
128             }
129 0         0 chomp($url);
130 0         0 return $url;
131             }
132              
133              
134             #
135             # config_user_data UDATA
136             #
137             # Locally configures user.email and user.name.
138             # UDATA is a reference to a hash containing 'email' and 'full_name'.
139             #
140             sub config_user_data {
141 0     0 0 0 my ($udata) = @_;
142 0         0 run_cmd("git config user.email \"$udata->{email}\"");
143 0         0 run_cmd("git config user.name \"$udata->{full_name}\"");
144             }
145              
146             # ---
147              
148             #
149             # exit_with_msg MSG, EXIT_VALUE
150             # exit_with_msg MSG
151             #
152             # Prints MSG and exits with value EXIT_VALUE (default: 0).
153             # For EXIT_VALUE != 0 the message is printed to STDERR.
154             #
155             sub exit_with_msg {
156 0     0 0 0 my ($msg, $exit_value) = @_;
157 0   0     0 $exit_value //= 0;
158 0 0       0 my $hndl = $exit_value ? *STDERR : *STDOUT;
159 0 0       0 $msg .= "\n" if substr($msg, -1) ne "\n";
160 0         0 print $hndl ($msg);
161 0         0 exit $exit_value;
162             }
163              
164              
165             #
166             # run_cmd CMD ECHO
167             # run_cmd CMD
168             #
169             # Executes CMD.
170             #
171             # If ECHO is a true value, then CMD is also printed to STDOUT. Default is true (1).
172             #
173             sub run_cmd {
174 0     0 0 0 my ($cmd, $echo) = @_;
175 0   0     0 $echo //= 1;
176 0         0 chomp($cmd);
177 0 0       0 print("Running: $cmd\n") if $echo;
178 0 0       0 system($cmd) == 0 or croak("Failed running $cmd");
179             }
180              
181              
182             sub usr_error {
183 0     0 0 0 pod2usage(-verbose => 1, -message => "$0: $_[0]\n", -output => \*STDERR, -exitval => 1);
184             }
185              
186              
187              
188             # ----------- functions for Getopt::Std, must be in main namespace ---------------------
189              
190             #
191             # Print help text, see docu of Getopt::Std.
192             #
193             #sub HELP_MESSAGE {
194             sub main::HELP_MESSAGE {
195 1     1   22 pod2usage(-exitval => 0, -verbose => 2);
196             }
197              
198             #
199             # Print version info, see docu of Getopt::Std.
200             #
201             sub main::VERSION_MESSAGE {
202 2     2   174 print("$0: $VERSION\n");
203             }
204              
205              
206             1;
207              
208              
209             __END__