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