line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::GitHub::FindRepository; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
44665
|
use warnings; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
71
|
|
4
|
2
|
|
|
2
|
|
11
|
use strict; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
183
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 NAME |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
App::GitHub::FindRepository - Determine the right case for a GitHub repository |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 VERSION |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Version 0.06 |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=cut |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = '0.06'; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 SYNOPSIS |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
github-find-repository git://github.com/robertkrimen/Doc-Simply.git |
21
|
|
|
|
|
|
|
# git://github.com/robertkrimen/doc-simply.git |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
github-find-repository robertkrimen,Doc-Simply |
24
|
|
|
|
|
|
|
# git://github.com/robertkrimen/doc-simply.git |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
github-find-repository --pinger=./bin/git-ls-remote ... |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# ... or ... |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
use App::GitHub::FindRepository |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my $url = App::GitHub::FindRepository->find( robertkrimen/Doc-Simply ) |
33
|
|
|
|
|
|
|
# git://github.com/robertkrimen/doc-simply.git |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 DESCRIPTION |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
GitHub recently made a change that now allows mixed-case repository names. Unfortunately, their git daemon |
38
|
|
|
|
|
|
|
will not find the right repository given the wrong case. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
L (C) will interrogate the repository home page (HTML), |
41
|
|
|
|
|
|
|
looking for the "right" repository name in a case insensitive manner |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
If LWP is not installed and curl is not available, then the finder will fallback to using the git protocol (via git-ls-remote or git-peek-remote). |
44
|
|
|
|
|
|
|
It will first attempt to ping the mixed-case version, and, failing that, will attempt to ping the lowercase version. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
In either case, it will return/print the valid repository url, if any |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 CAVEAT |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
When finding via the git protocol, the following applies: |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Given a mixed-case repository, the find routine will try the mixed-case once, then the lowercase. It will not find anything |
53
|
|
|
|
|
|
|
else |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
github-find-repository --git-protocol robertkrimen/Doc-Simply |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
...will work, as long as the real repository is C or C |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
If the real repository is C then the finder will NOT see it |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head1 INSTALL |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
You can install L by using L: |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
cpan -i App::GitHub::FindRepository |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
If that doesn't work properly, you can find help at: |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
http://sial.org/howto/perl/life-with-cpan/ |
70
|
|
|
|
|
|
|
http://sial.org/howto/perl/life-with-cpan/macosx/ # Help on Mac OS X |
71
|
|
|
|
|
|
|
http://sial.org/howto/perl/life-with-cpan/non-root/ # Help with a non-root account |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head1 CONTRIBUTE |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
You can contribute or fork this project via GitHub: |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
L |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
git clone git://github.com/robertkrimen/App-GitHub-FindRepository.git |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=cut |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head1 USAGE |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head2 github-find-repository |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
A commandline application that will print out the the repository with the right casing |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
Usage: github-find-repository [...] |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
--pinger The pinger to use (default is either git-ls-remote or git-peek-remote) |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
--getter The getter to use (default is LWP then curl) |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
--git-protocol Don't try to determine the repository by sniffing HTML, just use git:// |
96
|
|
|
|
|
|
|
NOTE: This mode will only check the given casing then lowercase |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
--output |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
Given "http://github.com/robertkrimen/aPp-giTHub-findRepoSitory.git" |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
URL http://github.com/robertkrimen/App-GitHub-FindRepository.git |
103
|
|
|
|
|
|
|
public git://github.com/robertkrimen/App-GitHub-FindRepository.git |
104
|
|
|
|
|
|
|
private git@github.com:robertkrimen/App-GitHub-FindRepository.git |
105
|
|
|
|
|
|
|
base robertkrimen/App-GitHub-FindRepository |
106
|
|
|
|
|
|
|
name App-GitHub-FindRepository |
107
|
|
|
|
|
|
|
home http://github.com/robertkrimen/App-GitHub-FindRepository |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
--help, -h, -? This help |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
The repository to test, can be like: |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
git://github.com/robertkrimen/App-GitHub-FindRepository.git |
114
|
|
|
|
|
|
|
robertkrimen/App-GitHub-FindRepository.git |
115
|
|
|
|
|
|
|
robertkrimen,App-GitHub-FindRepository |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
For example: |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
github-find-repository --getter curl robertkrimen,aPp-giTHuB-findRepOsitory |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=head2 $repository = AppGitHub::FindRepository->find( [, ...] ) |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
Given a mixed-case repository URI, it will return the version with the right case |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
getter The method to use to access the repository home page (HTML) |
126
|
|
|
|
|
|
|
pinger The pinger to use to access the repository via the git protocol |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=head2 $repository = AppGitHub::FindRepository->find_by_git( [, ...] ) |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
pinger The pinger to use to access the repository via the git protocol |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
Given a mixed-case repository URI, it will return the version with the right case, but only using the git protocol |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
NOTE: This method will only check the given casing then lowercase. See CAVEAT |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head1 ::Repository |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
The repository object that C<< ->find >> and C<< ->find_by_git >> return |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
The object will stringify via the C<< ->url >> method |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 $repository->url |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
The URL (URI) of the repository (depends on what the object was instantiated with) |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 $repository->public |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
The public github clone URL: |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
git://github.com/.git |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=head2 $repository->private |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
The private github clone URL: |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
git@github.com:.git |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head2 $repository->base |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
The user/project part of the repository path (WITHOUT the .git suffix): |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
robertkrimen/App-GitHub-FindRepository |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=head2 $repository->name |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
The name of the project: |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
App-GitHub-FindRepository |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=head2 $repository->home |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
The home page of the project on GitHub: |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
http://github.com/ # Will redirect to .../tree/master |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=head1 A bash function as an alternative |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
If you do not want to install App::GitHub::FindRepository, here is a bash equivalent (using the git protocol, see CAVEAT): |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
#!/bin/bash |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
function github-find-repository() { |
183
|
|
|
|
|
|
|
local pinger=`which git-ls-remote` |
184
|
|
|
|
|
|
|
if [ "$pinger" == "" ]; then pinger=`which git-peek-remote`; fi |
185
|
|
|
|
|
|
|
if [ "$pinger" == "" ]; then echo "Couldn't find pinger (git-ls-remote or git-peek-remote)"; return -1; fi |
186
|
|
|
|
|
|
|
local repository=$1 |
187
|
|
|
|
|
|
|
if [ "`$pinger $repository 2>/dev/null`" ]; then echo $repository; return 0; fi |
188
|
|
|
|
|
|
|
repository=`echo $repository | tr "[:upper:]" "[:lower:]" ` |
189
|
|
|
|
|
|
|
if [ "`$pinger $repository 2>/dev/null`" ]; then echo $repository; return 0; fi |
190
|
|
|
|
|
|
|
return -1 |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
github-find-repository $* |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head1 SEE ALSO |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
L |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=cut |
200
|
|
|
|
|
|
|
|
201
|
2
|
|
|
2
|
|
1138
|
use App::GitHub::FindRepository::Repository; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
61
|
|
202
|
|
|
|
|
|
|
|
203
|
2
|
|
|
2
|
|
2608
|
use Getopt::Long; |
|
2
|
|
|
|
|
27526
|
|
|
2
|
|
|
|
|
11
|
|
204
|
2
|
|
|
2
|
|
2357
|
use Env::Path qw/PATH/; |
|
2
|
|
|
|
|
5271
|
|
|
2
|
|
|
|
|
29
|
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
if (Env::Path->MSWIN) { |
207
|
|
|
|
|
|
|
require Cwd; |
208
|
|
|
|
|
|
|
(my $cwd = Cwd::getcwd()) =~ s{/}{\\}g; |
209
|
|
|
|
|
|
|
PATH->Remove($cwd); |
210
|
|
|
|
|
|
|
PATH->Prepend($cwd); |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub _find_in_path ($) { |
214
|
|
|
|
|
|
|
|
215
|
0
|
|
|
0
|
|
|
for ( PATH->Whence( shift ) ) { |
216
|
0
|
0
|
0
|
|
|
|
return $_ if -f && -r _ && -x _; |
|
|
|
0
|
|
|
|
|
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
return undef; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub do_usage (;$) { |
223
|
0
|
|
|
0
|
0
|
|
my $error = shift; |
224
|
0
|
0
|
|
|
|
|
warn $error if $error; |
225
|
0
|
|
|
|
|
|
warn <<_END_; |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
Usage: github-find-repository [...] |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
--pinger The pinger to use (default is either git-ls-remote or git-peek-remote) |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
--getter The getter to use (default is LWP then curl) |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
--git-protocol Don't try to determine the repository by sniffing HTML, just use git:// |
234
|
|
|
|
|
|
|
NOTE: This mode will only check the given casing then lowercase |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
--output |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Given "http://github.com/robertkrimen/aPp-giTHub-findRepoSitory.git" |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
URL http://github.com/robertkrimen/App-GitHub-FindRepository.git |
241
|
|
|
|
|
|
|
public git://github.com/robertkrimen/App-GitHub-FindRepository.git |
242
|
|
|
|
|
|
|
private git\@github.com:robertkrimen/App-GitHub-FindRepository.git |
243
|
|
|
|
|
|
|
base robertkrimen/App-GitHub-FindRepository |
244
|
|
|
|
|
|
|
name App-GitHub-FindRepository |
245
|
|
|
|
|
|
|
home http://github.com/robertkrimen/App-GitHub-FindRepository |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
--help, -h, -? This help |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
The repository to test, can be like: |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
git://github.com/robertkrimen/App-GitHub-FindRepository.git |
252
|
|
|
|
|
|
|
robertkrimen/App-GitHub-FindRepository.git |
253
|
|
|
|
|
|
|
robertkrimen,App-GitHub-FindRepository |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
For example: |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
github-find-repository --getter curl robertkrimen,aPp-giTHuB-findRepOsitory |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
_END_ |
260
|
|
|
|
|
|
|
|
261
|
0
|
0
|
|
|
|
|
exit -1 if $error; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub do_found ($$) { |
265
|
0
|
|
|
0
|
0
|
|
my $output = shift; |
266
|
0
|
|
|
|
|
|
my $repository = shift; |
267
|
0
|
0
|
|
|
|
|
if ($output) { |
268
|
0
|
|
|
|
|
|
print $repository->$output, "\n"; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
else { |
271
|
0
|
|
|
|
|
|
print "$repository\n"; |
272
|
|
|
|
|
|
|
} |
273
|
0
|
|
|
|
|
|
exit 0; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub do_not_found ($) { |
277
|
0
|
|
|
0
|
0
|
|
my $repository = shift; |
278
|
0
|
|
|
|
|
|
warn <<_END_; |
279
|
|
|
|
|
|
|
$0: Repository \"$repository\" not found |
280
|
|
|
|
|
|
|
_END_ |
281
|
0
|
|
|
|
|
|
exit -1; |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub pinger { |
285
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
286
|
0
|
|
0
|
|
|
|
return $ENV{GH_FR_PINGER} || _find_in_path 'git-ls-remote' || _find_in_path 'git-peek-remote'; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub _get_by_LWP { |
290
|
0
|
|
|
0
|
|
|
my $self = shift; |
291
|
|
|
|
|
|
|
return sub { |
292
|
0
|
|
|
0
|
|
|
my $url = shift; |
293
|
0
|
|
|
|
|
|
my $agent = LWP::UserAgent->new; |
294
|
0
|
|
|
|
|
|
my $response = $agent->get( $url ); |
295
|
0
|
0
|
|
|
|
|
die $response->status_line, "\n" unless $response->is_success; |
296
|
0
|
|
|
|
|
|
return $response->decoded_content; |
297
|
0
|
|
|
|
|
|
}; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
sub _get_by_curl { |
301
|
0
|
|
|
0
|
|
|
my $self = shift; |
302
|
0
|
|
|
|
|
|
my $curl = shift; |
303
|
|
|
|
|
|
|
return sub { |
304
|
0
|
|
|
0
|
|
|
my $url = shift; |
305
|
0
|
|
|
|
|
|
return `$curl -s -L $url`; |
306
|
0
|
|
|
|
|
|
}; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
sub getter { |
309
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
310
|
0
|
|
|
|
|
|
my $getter = shift; |
311
|
|
|
|
|
|
|
|
312
|
0
|
0
|
|
|
|
|
return $getter if ref $getter eq 'CODE'; |
313
|
|
|
|
|
|
|
|
314
|
0
|
0
|
|
|
|
|
$getter = 'LWP' unless $getter; |
315
|
|
|
|
|
|
|
|
316
|
0
|
0
|
|
|
|
|
die "Oh my god no!\n" if $getter eq '^'; |
317
|
|
|
|
|
|
|
|
318
|
0
|
|
|
|
|
|
my $command; |
319
|
0
|
0
|
0
|
|
|
|
if ($getter =~ m/^LWP$/i && eval "require LWP::UserAgent") { |
|
|
0
|
|
|
|
|
|
320
|
0
|
|
|
|
|
|
return $self->_get_by_LWP; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
elsif ($command = _find_in_path 'curl') { |
323
|
0
|
|
|
|
|
|
return $self->_get_by_curl( $command ); |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
0
|
|
|
|
|
|
return undef; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
sub parse_repository { |
330
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
331
|
0
|
|
|
|
|
|
return App::GitHub::FindRepository::Repository->parse( @_ ); |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub find { |
335
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
336
|
0
|
|
|
|
|
|
my $repository = $self->parse_repository( shift ); |
337
|
0
|
|
|
|
|
|
my %given = @_; |
338
|
0
|
|
|
|
|
|
my $getter = $self->getter( $given{getter} ); |
339
|
0
|
|
|
|
|
|
my $pinger = $given{pinger}; |
340
|
|
|
|
|
|
|
|
341
|
0
|
0
|
|
|
|
|
die "No repository given\n" unless $repository; |
342
|
0
|
0
|
|
|
|
|
if (! $getter ) { |
343
|
0
|
|
|
|
|
|
warn "Unable to use/find LWP or curl\n"; |
344
|
0
|
|
|
|
|
|
warn "Falling back to git protocol\n"; |
345
|
0
|
|
|
|
|
|
return $self->find_by_git( $repository, pinger => $pinger ); |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
0
|
|
|
|
|
|
my $url = $repository->home; |
349
|
0
|
|
|
|
|
|
my $base = $repository->base; |
350
|
|
|
|
|
|
|
|
351
|
0
|
|
|
|
|
|
my $content; |
352
|
0
|
|
|
|
|
|
eval { |
353
|
0
|
|
|
|
|
|
$content = $getter->( $url ); |
354
|
|
|
|
|
|
|
}; |
355
|
0
|
0
|
|
|
|
|
unless ($content) { |
356
|
0
|
|
0
|
|
|
|
my $error = $@ || "Unknown error"; |
357
|
0
|
|
|
|
|
|
chomp $error; |
358
|
0
|
|
|
|
|
|
warn "Failed GET $url since: $error\n"; |
359
|
0
|
|
|
|
|
|
warn "Falling back to git protocol\n"; |
360
|
0
|
|
|
|
|
|
return $self->find_by_git( $repository, pinger => $pinger ); |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
0
|
|
|
|
|
|
my ($canonical) = $content =~ m/\/($base)\//i; |
364
|
|
|
|
|
|
|
|
365
|
0
|
0
|
|
|
|
|
unless ($canonical) { |
366
|
0
|
|
|
|
|
|
warn "Failed to find \"/$base/\" in content of size ", length $content, "\n"; |
367
|
0
|
|
|
|
|
|
warn "Falling back to git protocol\n"; |
368
|
0
|
|
|
|
|
|
return $self->find_by_git( $repository, pinger => $pinger ); |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
$repository->base( $canonical ); |
372
|
|
|
|
|
|
|
|
373
|
0
|
|
|
|
|
|
return $repository; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub find_by_git { |
377
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
378
|
0
|
|
|
|
|
|
my $repository = $self->parse_repository( shift ); |
379
|
0
|
|
|
|
|
|
my %given = @_; |
380
|
0
|
|
0
|
|
|
|
my $pinger = $given{pinger} || $self->pinger; |
381
|
|
|
|
|
|
|
|
382
|
0
|
0
|
|
|
|
|
die "No or invalid repository given\n" unless $repository; |
383
|
0
|
0
|
|
|
|
|
die "No pinger!\n" unless $pinger; |
384
|
|
|
|
|
|
|
|
385
|
0
|
|
|
|
|
|
my $test_repository = $repository->test; |
386
|
|
|
|
|
|
|
|
387
|
0
|
0
|
|
|
|
|
return $repository if !system( "$pinger $test_repository 1>/dev/null 2>/dev/null" ); |
388
|
|
|
|
|
|
|
|
389
|
0
|
0
|
|
|
|
|
if ($repository->base =~ m/[A-Z]/) { |
390
|
0
|
|
|
|
|
|
$repository->base( lc $repository->base ); |
391
|
0
|
|
|
|
|
|
my $test_repository = $repository->test; |
392
|
0
|
0
|
|
|
|
|
return $repository if !system( "$pinger $test_repository 1>/dev/null 2>/dev/null" ); |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
0
|
|
|
|
|
|
return undef; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub run { |
399
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
400
|
|
|
|
|
|
|
|
401
|
0
|
|
|
|
|
|
my ($getter, $pinger, $git_protocol, $output, $help); |
402
|
0
|
|
|
|
|
|
GetOptions( |
403
|
|
|
|
|
|
|
'help|h|?' => \$help, |
404
|
|
|
|
|
|
|
'getter=s' => \$getter, |
405
|
|
|
|
|
|
|
'pinger=s' => \$pinger, |
406
|
|
|
|
|
|
|
'output=s' => \$output, |
407
|
|
|
|
|
|
|
'git-protocol' => \$git_protocol, |
408
|
|
|
|
|
|
|
); |
409
|
|
|
|
|
|
|
|
410
|
0
|
0
|
|
|
|
|
if ($help) { |
411
|
0
|
|
|
|
|
|
do_usage; |
412
|
0
|
|
|
|
|
|
exit 0; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
0
|
0
|
|
|
|
|
$pinger = $self->pinger unless $pinger; |
416
|
|
|
|
|
|
|
|
417
|
0
|
|
|
|
|
|
my $repository = join '', @ARGV; |
418
|
|
|
|
|
|
|
|
419
|
0
|
0
|
|
|
|
|
do_usage <<_END_ unless $repository; |
420
|
|
|
|
|
|
|
$0: You need to specify a repository |
421
|
|
|
|
|
|
|
_END_ |
422
|
|
|
|
|
|
|
|
423
|
0
|
0
|
|
|
|
|
if ($output) { |
424
|
0
|
|
|
|
|
|
$output = lc $output; |
425
|
0
|
0
|
|
|
|
|
$output =~ m/^(base|public|private|url|name|home)$/ or do_usage <<_END_; |
426
|
|
|
|
|
|
|
$0: Unrecogonized output option "$output" |
427
|
|
|
|
|
|
|
_END_ |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
0
|
|
|
|
|
|
eval { |
431
|
0
|
|
|
|
|
|
my $repository = $repository; |
432
|
0
|
0
|
|
|
|
|
if ($git_protocol) { |
433
|
0
|
|
|
|
|
|
$repository = $self->find_by_git( $repository, pinger => $pinger ); |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
else { |
436
|
0
|
|
|
|
|
|
$repository = $self->find( $repository, getter => $getter, pinger => $pinger ); |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
0
|
0
|
|
|
|
|
do_found $output, $repository if $repository; |
440
|
|
|
|
|
|
|
}; |
441
|
0
|
0
|
|
|
|
|
if ($@ =~ m/No pinger!/) { |
|
|
0
|
|
|
|
|
|
442
|
0
|
|
|
|
|
|
do_usage <<_END_; |
443
|
|
|
|
|
|
|
$0: No pinger given and couldn't find git-ls-remote or git-peek-remote in \$PATH |
444
|
|
|
|
|
|
|
_END_ |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
elsif ($@) { |
447
|
0
|
|
|
|
|
|
my $error = $@; |
448
|
0
|
|
|
|
|
|
chomp $error; |
449
|
0
|
|
|
|
|
|
do_usage <<_END_; |
450
|
|
|
|
|
|
|
$0: There was an error: $error |
451
|
|
|
|
|
|
|
_END_ |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
0
|
|
|
|
|
|
do_not_found $repository; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=head1 AUTHOR |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
Robert Krimen, C<< >> |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
=head1 BUGS |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
464
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
465
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=head1 SUPPORT |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
perldoc App::GitHub::FindRepository |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
You can also look for information at: |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=over 4 |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
L |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
L |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
=item * CPAN Ratings |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
L |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=item * Search CPAN |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
L |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
=back |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
Copyright 2009 Robert Krimen, all rights reserved. |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
508
|
|
|
|
|
|
|
under the same terms as Perl itself. |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=cut |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
__PACKAGE__; # End of App::GitHub::FindRepository |