| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Copyrights 1998,2005-2022 by [Mark Overmeer]. |
|
2
|
|
|
|
|
|
|
# For other contributors see ChangeLog. |
|
3
|
|
|
|
|
|
|
# See the manual pages for details on the licensing terms. |
|
4
|
|
|
|
|
|
|
# Pod stripped from pm file by OODoc 2.03. |
|
5
|
|
|
|
|
|
|
# This code is part of distribution CPAN::Site. |
|
6
|
|
|
|
|
|
|
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package CPAN::Site::Index; |
|
9
|
2
|
|
|
2
|
|
2043
|
use vars '$VERSION'; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
101
|
|
|
10
|
|
|
|
|
|
|
$VERSION = '1.17'; |
|
11
|
|
|
|
|
|
|
|
|
12
|
2
|
|
|
2
|
|
11
|
use base 'Exporter'; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
181
|
|
|
13
|
|
|
|
|
|
|
|
|
14
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
43
|
|
|
15
|
2
|
|
|
2
|
|
8
|
use strict; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
115
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our @EXPORT_OK = qw/cpan_index cpan_mirror/; |
|
18
|
|
|
|
|
|
|
our $VERSION; # required in test-env |
|
19
|
|
|
|
|
|
|
|
|
20
|
2
|
|
|
2
|
|
856
|
use Log::Report 'cpan-site', syntax => 'SHORT'; |
|
|
2
|
|
|
|
|
184031
|
|
|
|
2
|
|
|
|
|
9
|
|
|
21
|
|
|
|
|
|
|
|
|
22
|
2
|
|
|
2
|
|
1163
|
use version; |
|
|
2
|
|
|
|
|
3102
|
|
|
|
2
|
|
|
|
|
9
|
|
|
23
|
2
|
|
|
2
|
|
130
|
use File::Find qw/find/; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
100
|
|
|
24
|
2
|
|
|
2
|
|
444
|
use File::Copy qw/copy/; |
|
|
2
|
|
|
|
|
2057
|
|
|
|
2
|
|
|
|
|
100
|
|
|
25
|
2
|
|
|
2
|
|
13
|
use File::Basename qw/basename dirname/; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
107
|
|
|
26
|
2
|
|
|
2
|
|
864
|
use HTTP::Date qw/time2str/; |
|
|
2
|
|
|
|
|
3199
|
|
|
|
2
|
|
|
|
|
115
|
|
|
27
|
2
|
|
|
2
|
|
390
|
use File::Spec::Functions qw/catfile catdir splitdir/; |
|
|
2
|
|
|
|
|
641
|
|
|
|
2
|
|
|
|
|
100
|
|
|
28
|
2
|
|
|
2
|
|
1112
|
use LWP::UserAgent (); |
|
|
2
|
|
|
|
|
70602
|
|
|
|
2
|
|
|
|
|
48
|
|
|
29
|
2
|
|
|
2
|
|
1357
|
use Archive::Tar (); |
|
|
2
|
|
|
|
|
92987
|
|
|
|
2
|
|
|
|
|
65
|
|
|
30
|
2
|
|
|
2
|
|
1249
|
use Archive::Zip qw(:ERROR_CODES :CONSTANTS); |
|
|
2
|
|
|
|
|
80446
|
|
|
|
2
|
|
|
|
|
286
|
|
|
31
|
2
|
|
|
2
|
|
818
|
use CPAN::Checksums qw(updatedir); # horrible function name |
|
|
2
|
|
|
|
|
58704
|
|
|
|
2
|
|
|
|
|
131
|
|
|
32
|
2
|
|
|
2
|
|
15
|
use IO::Zlib (); |
|
|
2
|
|
|
|
|
14
|
|
|
|
2
|
|
|
|
|
7219
|
|
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my $tar_gz = qr/ \.tar\.gz$ | \.tar\.Z$ | \.tgz$/xi; |
|
35
|
|
|
|
|
|
|
my $zip = qr/ \.zip$ /xi; |
|
36
|
|
|
|
|
|
|
my $cpan_update = 0.04; # days between reload of full CPAN index |
|
37
|
|
|
|
|
|
|
my $ua; |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub safe_copy($$); |
|
40
|
|
|
|
|
|
|
sub cpan_index($@); |
|
41
|
|
|
|
|
|
|
sub register($$$); |
|
42
|
|
|
|
|
|
|
sub package_inventory($$;$); |
|
43
|
|
|
|
|
|
|
sub package_on_usual_location($); |
|
44
|
|
|
|
|
|
|
sub inspect_archive; |
|
45
|
|
|
|
|
|
|
sub inspect_tar_archive($$); |
|
46
|
|
|
|
|
|
|
sub inspect_zip_archive($$); |
|
47
|
|
|
|
|
|
|
sub collect_package_details($$$); |
|
48
|
|
|
|
|
|
|
sub update_global_cpan($$); |
|
49
|
|
|
|
|
|
|
sub load_file($$); |
|
50
|
|
|
|
|
|
|
sub merge_global_cpan($$$); |
|
51
|
|
|
|
|
|
|
sub create_details($$$$$); |
|
52
|
|
|
|
|
|
|
sub calculate_checksums($$); |
|
53
|
|
|
|
|
|
|
sub read_details($); |
|
54
|
|
|
|
|
|
|
sub remove_expired_details($$$); |
|
55
|
|
|
|
|
|
|
sub mkdirhier(@); |
|
56
|
|
|
|
|
|
|
sub cpan_mirror($$$@); |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub safe_copy($$) |
|
59
|
2
|
|
|
2
|
0
|
8
|
{ my ($from, $to) = @_; |
|
60
|
2
|
|
|
|
|
25
|
trace "copy $from to $to"; |
|
61
|
2
|
50
|
|
|
|
86
|
copy $from, $to |
|
62
|
|
|
|
|
|
|
or fault __x"cannot copy {from} to {to}", from => $from, to => $to; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub cpan_index($@) |
|
66
|
1
|
|
|
1
|
0
|
2035
|
{ my ($mycpan, $globalcpan, %opts) = @_; |
|
67
|
1
|
|
|
|
|
3
|
my $lazy = $opts{lazy}; |
|
68
|
1
|
|
|
|
|
1
|
my $fallback = $opts{fallback}; |
|
69
|
1
|
50
|
|
|
|
4
|
my $undefs = exists $opts{undefs} ? $opts{undefs} : 1; |
|
70
|
|
|
|
|
|
|
|
|
71
|
1
|
50
|
|
|
|
3
|
unless($ua) |
|
72
|
1
|
|
|
|
|
10
|
{ $ua = LWP::UserAgent->new; |
|
73
|
1
|
50
|
|
|
|
2464
|
$ua->env_proxy if $opts{env_proxy}; |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
|
|
76
|
1
|
50
|
|
|
|
17
|
-d $mycpan |
|
77
|
|
|
|
|
|
|
or error __x"archive top '{dir}' is not a directory" |
|
78
|
|
|
|
|
|
|
, dir => $mycpan; |
|
79
|
|
|
|
|
|
|
|
|
80
|
1
|
|
|
|
|
28
|
my $program = basename $0; |
|
81
|
1
|
|
50
|
|
|
4
|
$VERSION ||= 'undef'; # test env at home |
|
82
|
1
|
|
|
|
|
6
|
trace "$program version $VERSION"; |
|
83
|
|
|
|
|
|
|
|
|
84
|
1
|
|
|
|
|
44
|
my $global = catdir $mycpan, 'global'; |
|
85
|
1
|
|
|
|
|
4
|
my $mods = catdir $mycpan, 'modules'; |
|
86
|
1
|
|
|
|
|
3
|
my $authors = catdir $mycpan, 'authors'; |
|
87
|
1
|
|
|
|
|
4
|
mkdirhier $global, $mods, $authors; |
|
88
|
|
|
|
|
|
|
|
|
89
|
1
|
|
|
|
|
3
|
my $globdetails = update_global_cpan $mycpan, $globalcpan; |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# Create mailrc and modlist |
|
92
|
|
|
|
|
|
|
|
|
93
|
1
|
|
|
|
|
20
|
safe_copy catfile($global, '01mailrc.txt.gz') |
|
94
|
|
|
|
|
|
|
, catfile($authors, '01mailrc.txt.gz'); |
|
95
|
|
|
|
|
|
|
|
|
96
|
1
|
|
|
|
|
1574
|
safe_copy catfile($global, '03modlist.data.gz') |
|
97
|
|
|
|
|
|
|
, catfile($mods, '03modlist.data.gz'); |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# Create packages details |
|
100
|
|
|
|
|
|
|
|
|
101
|
1
|
|
|
|
|
377
|
my $details = catfile $mods, '02packages.details.txt.gz'; |
|
102
|
1
|
|
|
|
|
6
|
my $newlist = catfile $mods, '02packages.details.tmp.gz'; |
|
103
|
1
|
|
|
|
|
4
|
my $newer; |
|
104
|
|
|
|
|
|
|
|
|
105
|
1
|
|
|
|
|
3
|
my $reuse_dists = {}; |
|
106
|
1
|
50
|
33
|
|
|
7
|
if($lazy && -f $details) |
|
107
|
0
|
|
|
|
|
0
|
{ $reuse_dists = read_details $details; |
|
108
|
0
|
|
|
|
|
0
|
$newer = -M $details; |
|
109
|
0
|
|
|
|
|
0
|
remove_expired_details $mycpan, $reuse_dists, $newer; |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
|
|
112
|
1
|
|
|
|
|
7
|
my ($mypkgs, $distdirs) |
|
113
|
|
|
|
|
|
|
= package_inventory $mycpan, $reuse_dists, $newer; |
|
114
|
|
|
|
|
|
|
|
|
115
|
1
|
50
|
|
|
|
3
|
merge_global_cpan $mycpan, $mypkgs, $globdetails |
|
116
|
|
|
|
|
|
|
if $fallback; |
|
117
|
|
|
|
|
|
|
|
|
118
|
1
|
|
|
|
|
7
|
create_details $details, $newlist, $mypkgs, $lazy, $undefs; |
|
119
|
|
|
|
|
|
|
|
|
120
|
1
|
50
|
|
|
|
621
|
if(-f $details) |
|
121
|
0
|
|
|
|
|
0
|
{ trace "backup old details file to $details.bak"; |
|
122
|
0
|
|
|
|
|
0
|
safe_copy $details, "$details.bak"; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
|
|
125
|
1
|
50
|
|
|
|
44
|
if(-f $newlist) |
|
126
|
1
|
|
|
|
|
10
|
{ trace "promoting $newlist to current"; |
|
127
|
1
|
50
|
|
|
|
94
|
rename $newlist, $details |
|
128
|
|
|
|
|
|
|
or error __x"cannot rename '{from}' in '{to}'" |
|
129
|
|
|
|
|
|
|
, from => $newlist, to => $details; |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
1
|
|
|
|
|
15
|
calculate_checksums $distdirs, catdir($mycpan, 'authors', 'id'); |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# |
|
136
|
|
|
|
|
|
|
# Package Inventory |
|
137
|
|
|
|
|
|
|
# |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# global variables for testing purposes (sorry) |
|
140
|
|
|
|
|
|
|
our ($topdir, $findpkgs, %finddirs, $olddists, $index_age); |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub register($$$) |
|
143
|
31
|
|
|
31
|
0
|
73
|
{ my ($package, $this_version, $dist) = @_; |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# warn "register $package, " . (defined $this_version ? $this_version : 'undef'); |
|
146
|
|
|
|
|
|
|
|
|
147
|
31
|
50
|
|
|
|
58
|
if(ref $this_version) |
|
148
|
0
|
|
|
|
|
0
|
{ eval { $this_version = version->parse($this_version) }; |
|
|
0
|
|
|
|
|
0
|
|
|
149
|
0
|
0
|
|
|
|
0
|
if($@) |
|
150
|
0
|
|
|
|
|
0
|
{ alert __x"error when creating version object for {pkg}: {err}" |
|
151
|
|
|
|
|
|
|
, pkg => $package, err => $@; |
|
152
|
0
|
|
|
|
|
0
|
return; |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
|
|
156
|
31
|
50
|
|
|
|
89
|
my $registered_version = exists $findpkgs->{$package} ? $findpkgs->{$package}[0] : undef; |
|
157
|
31
|
100
|
|
|
|
57
|
$this_version =~ s/^v// if $this_version; |
|
158
|
|
|
|
|
|
|
|
|
159
|
31
|
50
|
33
|
|
|
83
|
return if defined $registered_version |
|
160
|
|
|
|
|
|
|
&& $registered_version > $this_version; |
|
161
|
|
|
|
|
|
|
|
|
162
|
31
|
|
|
|
|
234
|
$findpkgs->{$package} = [ $this_version, $dist ]; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub package_inventory($$;$) |
|
166
|
1
|
|
|
1
|
0
|
4
|
{ (my $mycpan, $olddists, $index_age) = @_; #!!! see "my" |
|
167
|
1
|
|
|
|
|
8
|
$topdir = catdir $mycpan, 'authors', 'id'; |
|
168
|
1
|
|
|
|
|
6
|
mkdirhier $topdir; |
|
169
|
|
|
|
|
|
|
|
|
170
|
1
|
|
|
|
|
3
|
$findpkgs = {}; |
|
171
|
1
|
|
|
|
|
8
|
trace "creating inventory from $topdir"; |
|
172
|
|
|
|
|
|
|
|
|
173
|
1
|
|
|
|
|
174
|
find {wanted => \&inspect_archive, no_chdir => 1}, $topdir; |
|
174
|
1
|
|
|
|
|
8
|
($findpkgs, \%finddirs); |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub package_on_usual_location($) |
|
178
|
23
|
|
|
23
|
0
|
408
|
{ my $file = shift; |
|
179
|
23
|
|
|
|
|
84
|
my ($top, $subdir, @rest) = splitdir $file; |
|
180
|
23
|
50
|
|
|
|
214
|
defined $subdir or return 0; |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
!@rest # path is at top-level of distro |
|
183
|
23
|
100
|
|
|
|
125
|
|| $subdir eq 'lib'; # inside lib |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub inspect_archive |
|
187
|
8
|
|
|
8
|
0
|
16275
|
{ my $fn = $File::Find::name; |
|
188
|
8
|
100
|
33
|
|
|
672
|
return unless -f $fn && ($fn =~ $tar_gz || $fn =~ $zip); |
|
|
|
|
66
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
|
190
|
4
|
|
|
|
|
95
|
(my $dist = $fn) =~ s!^\Q$topdir\E[\\/]!!; |
|
191
|
|
|
|
|
|
|
|
|
192
|
4
|
50
|
33
|
|
|
20
|
if(defined $index_age && -M $fn > $index_age) |
|
193
|
|
|
|
|
|
|
{ |
|
194
|
0
|
0
|
|
|
|
0
|
unless(exists $olddists->{$dist}) |
|
195
|
0
|
|
|
|
|
0
|
{ trace "not the latest: $dist"; |
|
196
|
0
|
|
|
|
|
0
|
return; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
0
|
|
|
|
|
0
|
trace "latest older than index: $dist"; |
|
200
|
0
|
|
|
|
|
0
|
foreach (@{$olddists->{$dist}}) |
|
|
0
|
|
|
|
|
0
|
|
|
201
|
0
|
|
|
|
|
0
|
{ my ($pkg, $version) = @$_; |
|
202
|
0
|
|
|
|
|
0
|
register $pkg, $version, $dist; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
0
|
|
|
|
|
0
|
return; |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
|
|
207
|
4
|
|
|
|
|
30
|
trace "inspecting archive $fn"; |
|
208
|
4
|
|
|
|
|
137
|
$finddirs{$File::Find::dir}++; |
|
209
|
|
|
|
|
|
|
|
|
210
|
4
|
50
|
|
|
|
47
|
return inspect_tar_archive $dist, $fn |
|
211
|
|
|
|
|
|
|
if $fn =~ $tar_gz; |
|
212
|
|
|
|
|
|
|
|
|
213
|
0
|
0
|
|
|
|
0
|
return inspect_zip_archive $dist, $fn |
|
214
|
|
|
|
|
|
|
if $fn =~ $zip; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub inspect_tar_archive($$) |
|
218
|
4
|
|
|
4
|
0
|
13
|
{ my ($dist, $fn) = @_; |
|
219
|
|
|
|
|
|
|
|
|
220
|
4
|
|
|
|
|
66
|
my $arch = Archive::Tar->new; |
|
221
|
4
|
50
|
|
|
|
60
|
$arch->read($fn, 1) |
|
222
|
|
|
|
|
|
|
or error __x"no files in tar archive '{fn}': {err}" |
|
223
|
|
|
|
|
|
|
, fn => $fn, err => $arch->error; |
|
224
|
|
|
|
|
|
|
|
|
225
|
4
|
|
|
|
|
60840
|
foreach my $file ($arch->get_files) |
|
226
|
64
|
|
|
|
|
655
|
{ my $fn = $file->full_path; |
|
227
|
64
|
100
|
100
|
|
|
1499
|
$file->is_file && $fn =~ m/\.pm$/i && package_on_usual_location $fn |
|
|
|
|
100
|
|
|
|
|
|
228
|
|
|
|
|
|
|
or next; |
|
229
|
21
|
|
|
|
|
72
|
collect_package_details $fn, $dist, $file->get_content_by_ref; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub inspect_zip_archive($$) |
|
234
|
0
|
|
|
0
|
0
|
0
|
{ my ($dist, $fn) = @_; |
|
235
|
|
|
|
|
|
|
|
|
236
|
0
|
|
|
|
|
0
|
my $arch = Archive::Zip->new; |
|
237
|
0
|
0
|
|
|
|
0
|
$arch->read($fn)==AZ_OK |
|
238
|
|
|
|
|
|
|
or error __x"no files in zip archive '{fn}': {err}" |
|
239
|
|
|
|
|
|
|
, fn => $fn, err => $arch->error; |
|
240
|
|
|
|
|
|
|
|
|
241
|
0
|
|
|
|
|
0
|
foreach my $member ($arch->membersMatching( qr/\.pm$/i )) |
|
242
|
0
|
|
|
|
|
0
|
{ my $fn = $member->fileName; |
|
243
|
0
|
0
|
0
|
|
|
0
|
$member->isTextFile && package_on_usual_location $fn |
|
244
|
|
|
|
|
|
|
or next; |
|
245
|
0
|
|
|
|
|
0
|
my ($contents, $status) = $member->contents; |
|
246
|
0
|
0
|
|
|
|
0
|
$status==AZ_OK |
|
247
|
|
|
|
|
|
|
or error "error in zip file {fn}: {err}" |
|
248
|
|
|
|
|
|
|
, fn => $fn, err => $status; |
|
249
|
0
|
|
|
|
|
0
|
collect_package_details $fn, $dist, \$contents; |
|
250
|
|
|
|
|
|
|
} |
|
251
|
|
|
|
|
|
|
} |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub collect_package_details($$$) |
|
254
|
21
|
|
|
21
|
0
|
119
|
{ my ($fn, $dist) = (shift, shift); |
|
255
|
21
|
|
|
|
|
31
|
my @lines = split /\r?\n/, ${shift()}; |
|
|
21
|
|
|
|
|
2527
|
|
|
256
|
21
|
|
|
|
|
61
|
my $in_pod = 0; |
|
257
|
21
|
|
|
|
|
25
|
my $package; |
|
258
|
21
|
|
|
|
|
40
|
local $VERSION = undef; # may get destroyed by eval |
|
259
|
|
|
|
|
|
|
|
|
260
|
21
|
|
|
|
|
43
|
while(@lines) |
|
261
|
4650
|
|
|
|
|
5537
|
{ local $_ = shift @lines; |
|
262
|
4650
|
50
|
|
|
|
6219
|
last if m/^__(?:END|DATA)__$/; |
|
263
|
|
|
|
|
|
|
|
|
264
|
4650
|
100
|
|
|
|
6307
|
$in_pod = ($1 ne 'cut') if m/^=(\w+)/; |
|
265
|
4650
|
100
|
100
|
|
|
9619
|
next if $in_pod || m/^\s*#/; |
|
266
|
|
|
|
|
|
|
|
|
267
|
3409
|
|
100
|
|
|
9155
|
$_ .= shift @lines |
|
|
|
|
100
|
|
|
|
|
|
268
|
|
|
|
|
|
|
while @lines && m/package|use|VERSION/ && !m/[;{]/; |
|
269
|
|
|
|
|
|
|
|
|
270
|
3409
|
100
|
|
|
|
5268
|
if( m/^\s* package \s* ((?:\w+\:\:)*\w+) (?:\s+ (\S*))? \s* [;{]/x ) |
|
271
|
31
|
|
|
|
|
111
|
{ my ($thispkg, $v) = ($1, $2); |
|
272
|
31
|
|
|
|
|
43
|
my $thisversion; |
|
273
|
31
|
50
|
|
|
|
57
|
if($v) |
|
274
|
0
|
|
|
|
|
0
|
{ $thisversion = eval {qv($v)}; |
|
|
0
|
|
|
|
|
0
|
|
|
275
|
0
|
0
|
|
|
|
0
|
alert __x"illegal version for {pkg}, found '{version}': {err}" |
|
276
|
|
|
|
|
|
|
, pkg => $thispkg, version => $v, err => $@ if $@; |
|
277
|
|
|
|
|
|
|
} |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# second package in file? |
|
280
|
31
|
100
|
|
|
|
79
|
register $package, $VERSION, $dist |
|
281
|
|
|
|
|
|
|
if defined $package; |
|
282
|
|
|
|
|
|
|
|
|
283
|
31
|
|
|
|
|
53
|
($package, $VERSION) = ($thispkg, $thisversion); |
|
284
|
31
|
|
|
|
|
141
|
trace "pkg $package from $fn"; |
|
285
|
|
|
|
|
|
|
} |
|
286
|
|
|
|
|
|
|
|
|
287
|
3409
|
50
|
|
|
|
8999
|
if( m/^\s* \$ ${package}::VERSION \s* = \s* ["']?(\w+?)["']? \s* ;/x ) |
|
288
|
0
|
|
|
|
|
0
|
{ $VERSION = $1; |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
3409
|
100
|
100
|
|
|
8839
|
if( !$VERSION && m/^ (?:use\s+version\s*;\s*)? |
|
292
|
|
|
|
|
|
|
(?:our)? \s* \$ ((?: \w+\:\:)*) VERSION \s* \= (.*)/x ) |
|
293
|
10
|
50
|
|
|
|
31
|
{ defined $2 or next; |
|
294
|
10
|
|
|
|
|
26
|
my ($ns, $vers) = ($1, $2); |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# some versions of CPAN.pm do contain lines like "$VERSION =~ ..." |
|
297
|
|
|
|
|
|
|
# which also need to be processed. |
|
298
|
10
|
|
|
|
|
776
|
eval "\$VERSION =$vers"; |
|
299
|
10
|
50
|
|
|
|
47
|
if(defined $VERSION) |
|
300
|
10
|
100
|
|
|
|
43
|
{ ($package = $ns) =~ s/\:\:$// |
|
301
|
|
|
|
|
|
|
if length $ns; |
|
302
|
10
|
|
|
|
|
41
|
trace "pkg $package version $VERSION"; |
|
303
|
|
|
|
|
|
|
} |
|
304
|
|
|
|
|
|
|
} |
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
|
|
307
|
21
|
50
|
|
|
|
43
|
$VERSION = $VERSION->numify if ref $VERSION; |
|
308
|
21
|
50
|
|
|
|
114
|
register $package, $VERSION, $dist |
|
309
|
|
|
|
|
|
|
if defined $package; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub update_global_cpan($$) |
|
313
|
1
|
|
|
1
|
0
|
3
|
{ my ($mycpan, $globalcpan) = @_; |
|
314
|
|
|
|
|
|
|
|
|
315
|
1
|
|
|
|
|
4
|
my $global = catdir $mycpan, 'global'; |
|
316
|
|
|
|
|
|
|
my ($mailrc, $globdetails, $modlist) = |
|
317
|
1
|
|
|
|
|
3
|
map { catfile $global, $_ } |
|
|
3
|
|
|
|
|
12
|
|
|
318
|
|
|
|
|
|
|
qw/01mailrc.txt.gz 02packages.details.txt.gz 03modlist.data.gz/; |
|
319
|
|
|
|
|
|
|
|
|
320
|
1
|
0
|
33
|
|
|
21
|
return $globdetails |
|
|
|
|
33
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
321
|
|
|
|
|
|
|
if -f $globdetails && -f $globdetails && -f $modlist |
|
322
|
|
|
|
|
|
|
&& -M $globdetails < $cpan_update; |
|
323
|
|
|
|
|
|
|
|
|
324
|
1
|
|
|
|
|
8
|
info "(re)loading global CPAN files"; |
|
325
|
|
|
|
|
|
|
|
|
326
|
1
|
|
|
|
|
23
|
mkdirhier $global; |
|
327
|
1
|
|
|
|
|
5
|
load_file "$globalcpan/authors/01mailrc.txt.gz", $mailrc; |
|
328
|
1
|
|
|
|
|
54
|
load_file "$globalcpan/modules/02packages.details.txt.gz", $globdetails; |
|
329
|
1
|
|
|
|
|
73
|
load_file "$globalcpan/modules/03modlist.data.gz", $modlist; |
|
330
|
1
|
|
|
|
|
44
|
$globdetails; |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
sub load_file($$) |
|
334
|
3
|
|
|
3
|
0
|
10
|
{ my ($from, $to) = @_; |
|
335
|
3
|
|
|
|
|
15
|
my $response = $ua->get($from, ':content_file' => $to); |
|
336
|
3
|
50
|
|
|
|
1352531
|
return if $response->is_success; |
|
337
|
|
|
|
|
|
|
|
|
338
|
0
|
|
|
|
|
0
|
unlink $to; |
|
339
|
0
|
|
|
|
|
0
|
error __x"failed to get {uri} for {to}: {err}" |
|
340
|
|
|
|
|
|
|
, uri => $from, to => $to, err => $response->status_line; |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
sub merge_global_cpan($$$) |
|
344
|
0
|
|
|
0
|
0
|
0
|
{ my ($mycpan, $pkgs, $globdetails) = @_; |
|
345
|
|
|
|
|
|
|
|
|
346
|
0
|
|
|
|
|
0
|
trace "merge packages with CPAN core list in $globdetails"; |
|
347
|
0
|
|
|
|
|
0
|
my $cpan_pkgs = read_details $globdetails; |
|
348
|
|
|
|
|
|
|
|
|
349
|
0
|
|
|
|
|
0
|
while(my ($cpandist, $cpanpkgs) = each %$cpan_pkgs) |
|
350
|
0
|
|
|
|
|
0
|
{ foreach (@$cpanpkgs) |
|
351
|
0
|
|
|
|
|
0
|
{ my ($pkg, $version) = @$_; |
|
352
|
0
|
0
|
|
|
|
0
|
next if exists $pkgs->{$pkg}; |
|
353
|
0
|
|
|
|
|
0
|
$pkgs->{$pkg} = [$version, $cpandist]; |
|
354
|
|
|
|
|
|
|
} |
|
355
|
|
|
|
|
|
|
} |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub create_details($$$$$) |
|
359
|
2
|
|
|
2
|
0
|
2802
|
{ my ($details, $filename, $pkgs, $lazy, $undefs) = @_; |
|
360
|
|
|
|
|
|
|
|
|
361
|
2
|
|
|
|
|
14
|
trace "creating package details in $filename"; |
|
362
|
2
|
50
|
|
|
|
68
|
my $fh = IO::Zlib->new($filename, 'wb') |
|
363
|
|
|
|
|
|
|
or fault __x"generating gzipped {fn}", fn => $filename; |
|
364
|
|
|
|
|
|
|
|
|
365
|
2
|
|
|
|
|
4824
|
my $lines = keys %$pkgs; |
|
366
|
2
|
|
|
|
|
17
|
my $date = time2str time; |
|
367
|
2
|
100
|
|
|
|
57
|
my $how = $lazy ? "lazy" : "full"; |
|
368
|
|
|
|
|
|
|
|
|
369
|
2
|
|
|
|
|
18
|
info "produced list of $lines packages $how"; |
|
370
|
|
|
|
|
|
|
|
|
371
|
2
|
|
|
|
|
186
|
my $program = basename $0; |
|
372
|
2
|
|
|
|
|
9
|
my $module = __PACKAGE__; |
|
373
|
2
|
|
|
|
|
48
|
$fh->print (<<__HEADER); |
|
374
|
|
|
|
|
|
|
File: 02packages.details.txt |
|
375
|
|
|
|
|
|
|
URL: file://$details |
|
376
|
|
|
|
|
|
|
Description: Packages listed in CPAN and local repository |
|
377
|
|
|
|
|
|
|
Columns: package name, version, path |
|
378
|
|
|
|
|
|
|
Intended-For: private CPAN |
|
379
|
|
|
|
|
|
|
Line-Count: $lines |
|
380
|
|
|
|
|
|
|
Written-By: $program with $module $CPAN::Site::Index::VERSION ($how) |
|
381
|
|
|
|
|
|
|
Last-Updated: $date |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
__HEADER |
|
384
|
|
|
|
|
|
|
|
|
385
|
2
|
|
|
|
|
486
|
foreach my $pkg (sort { lc($a) cmp lc($b) } keys %$pkgs) |
|
|
104
|
|
|
|
|
137
|
|
|
386
|
32
|
|
|
|
|
2930
|
{ my ($version, $path) = @{$pkgs->{$pkg}}; |
|
|
32
|
|
|
|
|
79
|
|
|
387
|
|
|
|
|
|
|
|
|
388
|
32
|
100
|
66
|
|
|
110
|
$version = 'undef' |
|
389
|
|
|
|
|
|
|
if !defined $version || $version eq ''; |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
next |
|
392
|
32
|
50
|
66
|
|
|
90
|
if $version eq 'undef' && !$undefs; |
|
393
|
|
|
|
|
|
|
|
|
394
|
32
|
|
|
|
|
58
|
$path =~ s,\\,/,g; |
|
395
|
32
|
|
|
|
|
155
|
$fh->printf("%-30s\t%s\t%s\n", $pkg, $version, $path); |
|
396
|
|
|
|
|
|
|
} |
|
397
|
|
|
|
|
|
|
} |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
sub calculate_checksums($$) |
|
400
|
1
|
|
|
1
|
0
|
2
|
{ my $dirs = shift; |
|
401
|
1
|
|
|
|
|
3
|
my $root = shift; |
|
402
|
1
|
|
|
|
|
5
|
trace "updating checksums"; |
|
403
|
|
|
|
|
|
|
|
|
404
|
1
|
|
|
|
|
25
|
foreach my $dir (keys %$dirs) |
|
405
|
1
|
|
|
|
|
4
|
{ trace "summing $dir"; |
|
406
|
1
|
50
|
|
|
|
24
|
updatedir($dir, $root) |
|
407
|
|
|
|
|
|
|
or warning 'failed calculating checksums in {dir}', dir => $dir; |
|
408
|
|
|
|
|
|
|
} |
|
409
|
|
|
|
|
|
|
} |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub read_details($) |
|
412
|
0
|
|
|
0
|
0
|
0
|
{ my $fn = shift; |
|
413
|
0
|
0
|
|
|
|
0
|
-f $fn or return {}; |
|
414
|
0
|
|
|
|
|
0
|
trace "collecting all details from $fn"; |
|
415
|
|
|
|
|
|
|
|
|
416
|
0
|
0
|
|
|
|
0
|
my $fh = IO::Zlib->new($fn, 'rb') |
|
417
|
|
|
|
|
|
|
or fault __x"cannot read from {fn}", fn => $fn; |
|
418
|
|
|
|
|
|
|
|
|
419
|
0
|
|
|
|
|
0
|
my $line; # skip header, search first blank |
|
420
|
0
|
|
|
|
|
0
|
do { $line = $fh->getline } until $line =~ m/^\s*$/; |
|
|
0
|
|
|
|
|
0
|
|
|
421
|
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
0
|
my $time_last_update = (stat $fn)[9]; |
|
423
|
0
|
|
|
|
|
0
|
my %dists; |
|
424
|
|
|
|
|
|
|
|
|
425
|
0
|
|
|
|
|
0
|
while(my $line = $fh->getline) |
|
426
|
0
|
|
|
|
|
0
|
{ chomp $line; |
|
427
|
0
|
|
|
|
|
0
|
my ($pkg, $version, $dist) = split ' ', $line, 3; |
|
428
|
|
|
|
|
|
|
|
|
429
|
0
|
0
|
|
|
|
0
|
unless($dist) |
|
430
|
0
|
|
|
|
|
0
|
{ warning "$fn error line=\n $line"; |
|
431
|
0
|
|
|
|
|
0
|
next; |
|
432
|
|
|
|
|
|
|
} |
|
433
|
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
0
|
push @{$dists{$dist}}, [$pkg, $version]; |
|
|
0
|
|
|
|
|
0
|
|
|
435
|
|
|
|
|
|
|
} |
|
436
|
|
|
|
|
|
|
|
|
437
|
0
|
|
|
|
|
0
|
\%dists; |
|
438
|
|
|
|
|
|
|
} |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub remove_expired_details($$$) |
|
441
|
0
|
|
|
0
|
0
|
0
|
{ my ($mycpan, $dists, $newer) = @_; |
|
442
|
0
|
|
|
|
|
0
|
trace "extracting only existing local distributions"; |
|
443
|
|
|
|
|
|
|
|
|
444
|
0
|
|
|
|
|
0
|
my $authors = catdir $mycpan, 'authors', 'id'; |
|
445
|
0
|
|
|
|
|
0
|
foreach my $dist (keys %$dists) |
|
446
|
0
|
|
|
|
|
0
|
{ my $fn = catfile $authors, $dist; |
|
447
|
0
|
0
|
|
|
|
0
|
if(! -f $fn) |
|
|
|
0
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
{ # removed local or a global dist |
|
449
|
0
|
|
|
|
|
0
|
delete $dists->{$dist}; |
|
450
|
|
|
|
|
|
|
} |
|
451
|
|
|
|
|
|
|
elsif(-M $fn < $newer) |
|
452
|
0
|
|
|
|
|
0
|
{ trace "dist $dist file updated, reindexing"; |
|
453
|
0
|
|
|
|
|
0
|
delete $dists->{$dist}; |
|
454
|
|
|
|
|
|
|
} |
|
455
|
|
|
|
|
|
|
} |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub mkdirhier(@) |
|
459
|
5
|
|
|
5
|
0
|
12
|
{ foreach my $dir (@_) |
|
460
|
7
|
100
|
|
|
|
149
|
{ next if -d $dir; |
|
461
|
2
|
|
|
|
|
65
|
mkdirhier dirname $dir; |
|
462
|
|
|
|
|
|
|
|
|
463
|
2
|
50
|
|
|
|
86
|
mkdir $dir, 0755 |
|
464
|
|
|
|
|
|
|
or fault __x"cannot create directory {dir}", dir => $dir; |
|
465
|
|
|
|
|
|
|
|
|
466
|
2
|
|
|
|
|
14
|
trace "created $dir"; |
|
467
|
|
|
|
|
|
|
} |
|
468
|
5
|
|
|
|
|
35
|
1; |
|
469
|
|
|
|
|
|
|
} |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
sub cpan_mirror($$$@) |
|
472
|
0
|
|
|
0
|
0
|
|
{ my ($mycpan, $globalcpan, $mods, %opts) = @_; |
|
473
|
0
|
0
|
|
|
|
|
@$mods or return; |
|
474
|
0
|
|
|
|
|
|
my %need = map { ($_ => 1) } @$mods; |
|
|
0
|
|
|
|
|
|
|
|
475
|
0
|
|
|
|
|
|
my $auth = catdir $mycpan, 'authors', 'id'; |
|
476
|
|
|
|
|
|
|
|
|
477
|
0
|
0
|
|
|
|
|
unless($ua) |
|
478
|
0
|
|
|
|
|
|
{ $ua = LWP::UserAgent->new; |
|
479
|
0
|
0
|
|
|
|
|
$ua->env_proxy if $opts{env_proxy}; |
|
480
|
|
|
|
|
|
|
} |
|
481
|
|
|
|
|
|
|
|
|
482
|
0
|
|
|
|
|
|
my $globdetails |
|
483
|
|
|
|
|
|
|
= update_global_cpan $mycpan, $globalcpan; |
|
484
|
|
|
|
|
|
|
|
|
485
|
0
|
0
|
|
|
|
|
my $fh = IO::Zlib->new($globdetails, 'rb') |
|
486
|
|
|
|
|
|
|
or fault __x"cannot read from {fn}", fn => $globdetails; |
|
487
|
|
|
|
|
|
|
|
|
488
|
0
|
|
|
|
|
|
while(my $line = $fh->getline) # skip header, search first blank |
|
489
|
0
|
0
|
|
|
|
|
{ last if $line =~ m/^\s*$/; |
|
490
|
|
|
|
|
|
|
} |
|
491
|
|
|
|
|
|
|
|
|
492
|
0
|
|
0
|
|
|
|
$ua ||= LWP::UserAgent->new; |
|
493
|
0
|
|
|
|
|
|
while(my $line = $fh->getline) |
|
494
|
0
|
|
|
|
|
|
{ my ($pkg, $version, $dist) = split ' ', $line; |
|
495
|
0
|
0
|
|
|
|
|
delete $need{$pkg} or next; |
|
496
|
|
|
|
|
|
|
|
|
497
|
0
|
|
|
|
|
|
my $to = catfile $auth, split m#/#, $dist; |
|
498
|
0
|
0
|
|
|
|
|
if(-f $to) |
|
499
|
0
|
|
|
|
|
|
{ trace __x"package {pkg} present in distribution {dist}" |
|
500
|
|
|
|
|
|
|
, pkg => $pkg, dist => $dist; |
|
501
|
0
|
|
|
|
|
|
next; |
|
502
|
|
|
|
|
|
|
} |
|
503
|
|
|
|
|
|
|
|
|
504
|
0
|
|
|
|
|
|
my $source = "$globalcpan/authors/id/$dist"; |
|
505
|
0
|
|
|
|
|
|
mkdirhier dirname $to; |
|
506
|
0
|
|
|
|
|
|
my $response = $ua->get($source, ':content_file' => $to); |
|
507
|
0
|
0
|
|
|
|
|
unless($response->is_success) |
|
508
|
0
|
|
|
|
|
|
{ unlink $to; |
|
509
|
0
|
|
|
|
|
|
error __x"failed to get {uri} for {to}: {err}" |
|
510
|
|
|
|
|
|
|
, uri => $source, to => $to, err => $response->status_line; |
|
511
|
|
|
|
|
|
|
} |
|
512
|
|
|
|
|
|
|
|
|
513
|
0
|
|
|
|
|
|
info __x"got {pkg} in {dist}", pkg => $pkg, dist => $dist; |
|
514
|
|
|
|
|
|
|
} |
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
warning __x"package {pkg} does not exist", pkg => $_ |
|
517
|
0
|
|
|
|
|
|
for sort keys %need; |
|
518
|
|
|
|
|
|
|
} |
|
519
|
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
1; |