File Coverage

lib/App/gh/Command/All.pm
Criterion Covered Total %
statement 24 85 28.2
branch 0 28 0.0
condition 0 5 0.0
subroutine 8 11 72.7
pod 0 2 0.0
total 32 131 24.4


line stmt bran cond sub pod time code
1             package App::gh::Command::All;
2 1     1   1788 use utf8;
  1         10  
  1         5  
3 1     1   64 use warnings;
  1         2  
  1         24  
4 1     1   4 use strict;
  1         1  
  1         29  
5 1     1   4 use base qw(App::gh::Command);
  1         1  
  1         80  
6 1     1   6 use File::Path qw(mkpath rmtree);
  1         2  
  1         68  
7 1         90 use App::gh::Utils qw(
8             info
9             error
10             notice
11             generate_repo_uri
12             run_git_fetch
13             build_git_clone_command
14             dialog_yes_default
15 1     1   5 );
  1         1  
16 1     1   788 use Scope::Guard qw(guard);
  1         385  
  1         46  
17 1     1   5 use Cwd ();
  1         95  
  1         914  
18              
19             sub options { (
20 0     0 0   "verbose" => "verbose",
21             "prompt" => "prompt",
22             "into=s" => "into",
23             "exclude=s@" => "exclude",
24             "s|skip-exists" => "skip_exists",
25              
26             "ssh" => "protocol_ssh", # git@github.com:c9s/repo.git
27             "http" => "protocol_http", # http://github.com/c9s/repo.git
28             "https" => "protocol_https", # https://github.com/c9s/repo.git
29             "git|ro" => "protocol_git", # git://github.com/c9s/repo.git
30              
31              
32             "tags" => "tags",
33             "q|quiet" => "quiet",
34             "bare" => "bare",
35             "mirror" => "mirror",
36             "b|branch=s" => "branch",
37             "recursive" => "recursive",
38             "origin" => "origin",
39              
40              
41             "p|prefix=s" => "prefix",
42             "f|force" => "force",
43             ) }
44              
45              
46             #
47             # @param string $user github user id
48             # @param string $type github repository type (all,owner,member,all)
49             # @see http://developer.github.com/v3/repos/
50              
51             sub run {
52 0     0 0   my $self = shift;
53 0           my $user = shift;
54 0   0       my $type = shift || 'owner';
55              
56             # turn off buffering
57 0           $|++;
58              
59 0           my $cwd = Cwd::getcwd();
60 0   0       $self->{into} ||= $user;
61              
62 0 0         die 'Need account id.' unless $user;
63              
64 0 0         if( $self->{into} ) {
65 0           info "Cloning all repositories into @{[ $self->{into} ]}";
  0            
66 0           mkpath [ $self->{into} ];
67 0           chdir $self->{into};
68             }
69              
70 0           info "Getting repositories from $user...";
71 0           my @repos = App::gh->github->repos->list_user($user,$type);
72              
73 0 0         unless(@repos) {
74 0           info "Found no repository to clone, exiting";
75 0           return;
76             }
77              
78 0           my $into = Cwd::getcwd();
79 0           my $cloned = 0;
80 0           my $total = scalar(@repos);
81              
82 0           info "Found " . $total . " repositories to clone:";
83 0           print " " x 8 . join " " , map { $_->{name} } @repos;
  0            
84 0           print "\n";
85              
86 0 0         return unless dialog_yes_default "Are you sure to continue ?";
87              
88             my $progress = sub {
89 0     0     return sprintf "[%d/%d]",
90             ++$cloned,
91             $total;
92 0           };
93              
94 0           my $exclude = do {
95 0 0         my $arr = ref $self->{exclude} eq 'ARRAY' ? $self->{exclude} : [];
96 0           +{map { $_ => 1 } @$arr};
  0            
97             };
98              
99 0           for my $repo ( @repos ) {
100 0           my $local_repo = $repo->{name};
101              
102 0 0         next if exists $exclude->{ $local_repo };
103              
104 0           my $uri = generate_repo_uri($user,$repo->{name},$self);
105 0           my @command = build_git_clone_command($uri,$self);
106 0 0         $local_repo = $self->{prefix} . $local_repo if $self->{prefix};
107 0           push @command , $local_repo;
108              
109 0 0         if( -e $local_repo) {
110 0 0         if( $self->{skip_exists} ) {
    0          
111 0           info "Found $local_repo, skip.";
112 0           next;
113             }
114             elsif( $self->{force} ) {
115 0           notice "Force mode, Deleting original $local_repo";
116 0 0         rmtree $local_repo or do {
117 0           error "Could not remove '$local_repo', skip.\n";
118 0           next;
119             };
120             }
121             else {
122             # fetch and jump to next
123 0           info $progress->() . " $local_repo exists, fetching...";
124 0           chdir($local_repo);
125 0           run_git_fetch {
126             all => 1,
127             quiet => $self->{quiet},
128             tags => $self->{tags},
129             };
130 0           chdir($into);
131 0           next;
132             }
133             }
134              
135 0 0         if( $self->{prompt} ) {
136 0 0         next unless dialog_yes_default "Clong " . $repo->{name} . ' ?';
137             }
138              
139 0           info sprintf "%s Cloning %s (%d/%d) ...",
140             $progress->(),
141             $repo->{full_name},
142             $repo->{watchers},
143             $repo->{forks};
144 0           my $cmd = join " ",@command;
145 0           qx($cmd);
146              
147 0 0         if( $self->{tags} ) {
148 0           chdir $local_repo;
149 0           run_git_fetch {
150             all => 1,
151             quiet => $self->{quiet},
152             tags => $self->{tags},
153             };
154 0           chdir $into;
155             }
156              
157             }
158              
159             # for my $repo ( @{ $repolist } ) {
160             # # =================
161             # # End of conditions for skipping clone
162             #
163             #
164             # if( -e $local_repo_dir ) {
165             # my $cwd = Cwd::getcwd();
166             # chdir $local_repo_dir;
167             # my $guard = guard { chdir $cwd }; # switch back
168             # print "Updating $local_repo_dir from remotes ..." . $print_progress->() . "\n";
169             #
170             # if( qx{ git config --get core.bare } =~ /\Atrue\n?\Z/ ) {
171             # # Here I assume remote..mirror is automatically set.
172             # # bacause --bare and --mirror do the set-up.
173             # qx{ git fetch --all };
174             # }
175             # else {
176             # my $flags = qq();
177             # $flags .= qq{ -q } unless $self->{verbose};
178             #
179             # # prune deleted remote branches
180             # qx{git remote update --prune};
181             #
182             # # fetch all remotes
183             # qx{ git fetch --all };
184             #
185             # # update current working repo
186             # qx{ git pull $flags --rebase --all };
187             # }
188             # }
189             # else {
190             # # Support old git (which does not support `git clone --mirror`)
191             # if ($self->{mirror}) {
192             # my $cwd = Cwd::getcwd();
193             # chdir $local_repo_dir;
194             # my $guard = guard { chdir $cwd }; # switch back
195             # qx{ git config remote.origin.fetch '+refs/*:refs/*' };
196             # qx{ git config remote.origin.url $uri };
197             # qx{ git config remote.origin.mirror true };
198             # }
199             # }
200             # }
201             # print "Done\n";
202              
203             }
204              
205              
206             1;
207             __END__