line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::EPAN; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
69880
|
use 5.012; |
|
1
|
|
|
|
|
4
|
|
4
|
|
|
|
|
|
|
{ our $VERSION = '0.001002' } |
5
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
30
|
|
6
|
1
|
|
|
1
|
|
639
|
use English qw( -no_match_vars ); |
|
1
|
|
|
|
|
3871
|
|
|
1
|
|
|
|
|
6
|
|
7
|
1
|
|
|
1
|
|
821
|
use version; |
|
1
|
|
|
|
|
2366
|
|
|
1
|
|
|
|
|
5
|
|
8
|
1
|
|
|
1
|
|
665
|
use autodie; |
|
1
|
|
|
|
|
16362
|
|
|
1
|
|
|
|
|
5
|
|
9
|
1
|
|
|
1
|
|
7673
|
use Getopt::Long qw< :config gnu_getopt >; |
|
1
|
|
|
|
|
12751
|
|
|
1
|
|
|
|
|
5
|
|
10
|
1
|
|
|
1
|
|
710
|
use Pod::Usage qw< pod2usage >; |
|
1
|
|
|
|
|
49875
|
|
|
1
|
|
|
|
|
99
|
|
11
|
1
|
|
|
1
|
|
634
|
use Dist::Metadata (); |
|
1
|
|
|
|
|
31830
|
|
|
1
|
|
|
|
|
31
|
|
12
|
1
|
|
|
1
|
|
533
|
use Path::Class qw< file dir >; |
|
1
|
|
|
|
|
37048
|
|
|
1
|
|
|
|
|
82
|
|
13
|
1
|
|
|
1
|
|
22
|
use Cwd qw< cwd >; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
42
|
|
14
|
1
|
|
|
1
|
|
587
|
use File::Find::Rule (); |
|
1
|
|
|
|
|
8591
|
|
|
1
|
|
|
|
|
25
|
|
15
|
1
|
|
|
1
|
|
708
|
use Compress::Zlib (); |
|
1
|
|
|
|
|
55020
|
|
|
1
|
|
|
|
|
35
|
|
16
|
1
|
|
|
1
|
|
625
|
use Log::Log4perl::Tiny qw< :easy :dead_if_first >; |
|
1
|
|
|
|
|
15081
|
|
|
1
|
|
|
|
|
5
|
|
17
|
1
|
|
|
1
|
|
976
|
use Moo; |
|
1
|
|
|
|
|
12045
|
|
|
1
|
|
|
|
|
4
|
|
18
|
1
|
|
|
1
|
|
2732
|
use IPC::Run (); |
|
1
|
|
|
|
|
28741
|
|
|
1
|
|
|
|
|
34
|
|
19
|
1
|
|
|
1
|
|
795
|
use File::Copy (); |
|
1
|
|
|
|
|
2568
|
|
|
1
|
|
|
|
|
39
|
|
20
|
1
|
|
|
1
|
|
608
|
use File::Which qw< which >; |
|
1
|
|
|
|
|
1178
|
|
|
1
|
|
|
|
|
813
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
has configuration => ( |
23
|
|
|
|
|
|
|
is => 'rw', |
24
|
|
|
|
|
|
|
lazy => 1, |
25
|
|
|
|
|
|
|
predicate => 'has_config', |
26
|
|
|
|
|
|
|
clearer => 'clear_config', |
27
|
|
|
|
|
|
|
default => sub { {} }, |
28
|
|
|
|
|
|
|
); |
29
|
|
|
|
|
|
|
has action => (is => 'rw',); |
30
|
|
|
|
|
|
|
has last_index => (is => 'rw',); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub run { |
33
|
0
|
|
|
0
|
1
|
|
my $package = shift; |
34
|
0
|
|
|
|
|
|
my $self = $package->new(); |
35
|
0
|
|
|
|
|
|
$self->get_options(@_); |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
|
my $action = $self->action(); |
38
|
0
|
0
|
|
|
|
|
pod2usage(-verbose => 99, -sections => 'USAGE') unless defined $action; |
39
|
0
|
0
|
|
|
|
|
if (my $method = $self->can("action_$action")) { |
40
|
0
|
|
|
|
|
|
$self->$method(); |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
else { |
43
|
0
|
|
|
|
|
|
FATAL "action '$action' is not supported\n"; |
44
|
0
|
|
|
|
|
|
$self->action_list_actions; |
45
|
0
|
|
|
|
|
|
exit 1; |
46
|
|
|
|
|
|
|
} |
47
|
0
|
|
|
|
|
|
return; |
48
|
|
|
|
|
|
|
} ## end sub run |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub get_options { |
51
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
52
|
0
|
0
|
0
|
|
|
|
my $action = |
53
|
|
|
|
|
|
|
(scalar(@_) && length($_[0]) && (substr($_[0], 0, 1) ne '-')) |
54
|
|
|
|
|
|
|
? shift(@_) |
55
|
|
|
|
|
|
|
: 'list-actions'; |
56
|
0
|
|
|
|
|
|
$action =~ s{-}{_}gmxs; |
57
|
0
|
|
|
|
|
|
local @ARGV = @_; |
58
|
0
|
|
|
|
|
|
$self->action($action); |
59
|
0
|
|
|
|
|
|
my %config = (); |
60
|
0
|
0
|
|
|
|
|
GetOptions( |
61
|
|
|
|
|
|
|
\%config, |
62
|
|
|
|
|
|
|
qw( |
63
|
|
|
|
|
|
|
mailrc|m|1=s |
64
|
|
|
|
|
|
|
output|packages-details|o|2=s |
65
|
|
|
|
|
|
|
modlist|modlist-data|l|3=s |
66
|
|
|
|
|
|
|
target|t=s |
67
|
|
|
|
|
|
|
test|T! |
68
|
|
|
|
|
|
|
author|a=s |
69
|
|
|
|
|
|
|
usage! help! man! version! |
70
|
|
|
|
|
|
|
) |
71
|
|
|
|
|
|
|
) or pod2usage(-verbose => 99, -sections => 'USAGE'); |
72
|
0
|
|
0
|
|
|
|
our $VERSION ||= 'whateva'; |
73
|
|
|
|
|
|
|
pod2usage(message => "$0 $VERSION", -verbose => 99, -sections => ' ') |
74
|
0
|
0
|
|
|
|
|
if $config{version}; |
75
|
0
|
0
|
|
|
|
|
pod2usage(-verbose => 99, -sections => 'USAGE') if $config{usage}; |
76
|
|
|
|
|
|
|
pod2usage(-verbose => 99, -sections => 'USAGE|EXAMPLES|OPTIONS') |
77
|
0
|
0
|
|
|
|
|
if $config{help}; |
78
|
0
|
0
|
|
|
|
|
pod2usage(-verbose => 2) if $config{man}; |
79
|
0
|
|
|
|
|
|
$self->configuration( |
80
|
|
|
|
|
|
|
{ |
81
|
|
|
|
|
|
|
cmdline_config => \%config, |
82
|
|
|
|
|
|
|
config => \%config, |
83
|
|
|
|
|
|
|
args => [@ARGV], |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
); |
86
|
0
|
|
|
|
|
|
return; |
87
|
|
|
|
|
|
|
} ## end sub get_options |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub args { |
90
|
0
|
|
|
0
|
1
|
|
return @{$_[0]->configuration()->{args}}; |
|
0
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub config { |
94
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
95
|
0
|
0
|
|
|
|
|
return @{$self->configuration()->{config}}{@_} if wantarray(); |
|
0
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
|
return $self->configuration()->{config}{shift @_}; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub target_dir { |
100
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
101
|
0
|
|
0
|
|
|
|
return dir($self->config('target') // 'epan'); |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub execute_tests { |
105
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
106
|
0
|
|
|
|
|
|
return $self->config('test'); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub action_index { |
110
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
111
|
0
|
|
|
|
|
|
return $self->_do_index($self->target_dir); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
{ |
115
|
1
|
|
|
1
|
|
21
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2093
|
|
116
|
|
|
|
|
|
|
*{action_idx} = \&action_index; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub _save { |
120
|
0
|
|
|
0
|
|
|
my ($self, $name, $contents, $config_key, $output) = @_; |
121
|
|
|
|
|
|
|
|
122
|
0
|
0
|
|
|
|
|
if (defined(my $confout = $self->config($config_key))) { |
123
|
0
|
0
|
|
|
|
|
$output = |
|
|
0
|
|
|
|
|
|
124
|
|
|
|
|
|
|
!length($confout) ? undef |
125
|
|
|
|
|
|
|
: $confout eq '-' ? \*STDOUT |
126
|
|
|
|
|
|
|
: file($confout); |
127
|
|
|
|
|
|
|
} ## end if (defined(my $confout...)) |
128
|
0
|
0
|
|
|
|
|
if (defined $output) { |
129
|
0
|
|
|
|
|
|
INFO "saving output to $output"; |
130
|
0
|
0
|
|
|
|
|
$self->_save2($output, |
131
|
|
|
|
|
|
|
scalar(ref($contents) ? $contents->() : $contents)); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
else { |
134
|
0
|
|
|
|
|
|
INFO "empty filename for $name file, skipping"; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} ## end sub _save |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub _do_index { |
139
|
0
|
|
|
0
|
|
|
my ($self, $basedir) = @_; |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
$self->_save( |
142
|
|
|
|
|
|
|
'01mailrc', # name |
143
|
|
|
|
|
|
|
'', # contents |
144
|
|
|
|
|
|
|
'mailrc', # configuration key to look output file |
145
|
|
|
|
|
|
|
$basedir->file(qw< authors 01mailrc.txt.gz >) # default |
146
|
|
|
|
|
|
|
); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
$self->_save( |
149
|
|
|
|
|
|
|
'02packages.details', # name |
150
|
|
|
|
|
|
|
sub { # where to get data from. Call is avoided if |
151
|
|
|
|
|
|
|
# no file on output |
152
|
0
|
|
|
0
|
|
|
INFO "getting contributions for regenerated index..."; |
153
|
0
|
|
|
|
|
|
$self->_index_for($basedir); |
154
|
|
|
|
|
|
|
}, |
155
|
0
|
|
|
|
|
|
'output', # configuration key to look output file |
156
|
|
|
|
|
|
|
$basedir->file(qw< modules 02packages.details.txt.gz >) # default |
157
|
|
|
|
|
|
|
); |
158
|
|
|
|
|
|
|
|
159
|
0
|
|
|
|
|
|
$self->_save( |
160
|
|
|
|
|
|
|
'03modlist.data', # name |
161
|
|
|
|
|
|
|
<<'END_OF_03_MODLIST_DATA', |
162
|
|
|
|
|
|
|
File: 03modlist.data |
163
|
|
|
|
|
|
|
Description: These are the data that are published in the module |
164
|
|
|
|
|
|
|
list, but they may be more recent than the latest posted |
165
|
|
|
|
|
|
|
modulelist. Over time we'll make sure that these data |
166
|
|
|
|
|
|
|
can be used to print the whole part two of the |
167
|
|
|
|
|
|
|
modulelist. Currently this is not the case. |
168
|
|
|
|
|
|
|
Modcount: 0 |
169
|
|
|
|
|
|
|
Written-By: PAUSE version 1.005 |
170
|
|
|
|
|
|
|
Date: Sun, 28 Jul 2013 07:41:15 GMT |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
package CPAN::Modulelist; |
173
|
|
|
|
|
|
|
# Usage: print Data::Dumper->new([CPAN::Modulelist->data])->Dump or similar |
174
|
|
|
|
|
|
|
# cannot 'use strict', because we normally run under Safe |
175
|
|
|
|
|
|
|
# use strict; |
176
|
|
|
|
|
|
|
sub data { |
177
|
|
|
|
|
|
|
my $result = {}; |
178
|
|
|
|
|
|
|
my $primary = "modid"; |
179
|
|
|
|
|
|
|
for (@$CPAN::Modulelist::data){ |
180
|
|
|
|
|
|
|
my %hash; |
181
|
|
|
|
|
|
|
@hash{@$CPAN::Modulelist::cols} = @$_; |
182
|
|
|
|
|
|
|
$result->{$hash{$primary}} = \%hash; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
return $result; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
$CPAN::Modulelist::cols = [ ]; |
187
|
|
|
|
|
|
|
$CPAN::Modulelist::data = [ ]; |
188
|
|
|
|
|
|
|
END_OF_03_MODLIST_DATA |
189
|
|
|
|
|
|
|
'modlist', # configuration key to look output file |
190
|
|
|
|
|
|
|
$basedir->file(qw< modules 03modlist.data.gz >) # default |
191
|
|
|
|
|
|
|
); |
192
|
|
|
|
|
|
|
} ## end sub _do_index |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub _save2 { |
195
|
0
|
|
|
0
|
|
|
my ($self, $path, $contents) = @_; |
196
|
0
|
|
|
|
|
|
my ($fh, $is_gz); |
197
|
0
|
0
|
|
|
|
|
if (ref($path) eq 'GLOB') { |
198
|
0
|
|
|
|
|
|
$fh = $path; |
199
|
0
|
|
|
|
|
|
$is_gz = 0; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
else { |
202
|
0
|
0
|
|
|
|
|
$path->dir()->mkpath() unless -d $path->dir()->stringify(); |
203
|
0
|
|
|
|
|
|
$fh = $path->open('>'); |
204
|
0
|
|
|
|
|
|
$is_gz = $path->stringify() =~ m{\.gz$}mxs; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
0
|
0
|
|
|
|
|
if ($is_gz) { |
208
|
0
|
|
|
|
|
|
my $gz = Compress::Zlib::gzopen($fh, 'wb'); |
209
|
0
|
|
|
|
|
|
$gz->gzwrite($contents); |
210
|
0
|
|
|
|
|
|
$gz->gzclose(); |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
else { |
213
|
0
|
|
|
|
|
|
binmode $fh; |
214
|
0
|
|
|
|
|
|
print {$fh} $contents; |
|
0
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
} |
216
|
0
|
|
|
|
|
|
return; |
217
|
|
|
|
|
|
|
} ## end sub _save2 |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub _index_for { |
220
|
0
|
|
|
0
|
|
|
my ($self, $path) = @_; |
221
|
0
|
|
|
|
|
|
my @index = $self->_index_body_for($path); |
222
|
0
|
|
0
|
|
|
|
our $VERSION ||= 'whateva'; |
223
|
0
|
|
|
|
|
|
my $header = <<"END_OF_HEADER"; |
224
|
|
|
|
|
|
|
File: 02packages.details.txt |
225
|
|
|
|
|
|
|
URL: http://cpan.perl.org/modules/02packages.details.txt.gz |
226
|
|
|
|
|
|
|
Description: Package names found in directory \$CPAN/authors/id/ |
227
|
|
|
|
|
|
|
Columns: package name, version, path |
228
|
|
|
|
|
|
|
Intended-For: Automated fetch routines, namespace documentation. |
229
|
|
|
|
|
|
|
Written-By: epan $VERSION |
230
|
0
|
|
|
|
|
|
Line-Count: ${ \ scalar @index } |
231
|
0
|
|
|
|
|
|
Last-Updated: ${ \ scalar localtime() } |
232
|
|
|
|
|
|
|
END_OF_HEADER |
233
|
0
|
|
|
|
|
|
return join "\n", $header, @index, ''; |
234
|
|
|
|
|
|
|
} ## end sub _index_for |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub _collect_index_for { |
237
|
0
|
|
|
0
|
|
|
my ($self, $path) = @_; |
238
|
0
|
|
|
|
|
|
$path = dir($path); |
239
|
0
|
|
|
|
|
|
my $idpath = $path->subdir(qw< authors id >); |
240
|
0
|
|
|
|
|
|
my %data_for; |
241
|
0
|
|
|
|
|
|
for my $file (File::Find::Rule->extras({follow => 1})->file() |
242
|
|
|
|
|
|
|
->in($idpath->stringify())) |
243
|
|
|
|
|
|
|
{ |
244
|
0
|
|
|
|
|
|
INFO "indexing $file"; |
245
|
0
|
|
|
|
|
|
my $index_path = |
246
|
|
|
|
|
|
|
file($file)->relative($idpath)->as_foreign('Unix')->stringify(); |
247
|
0
|
|
|
|
|
|
my $dm = Dist::Metadata->new(file => $file); |
248
|
0
|
|
|
|
|
|
my $version_for = $dm->package_versions(); |
249
|
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
|
$data_for{distro}{$index_path} = $version_for; |
251
|
0
|
|
|
|
|
|
(my $bare_index_path = $index_path) =~ |
252
|
|
|
|
|
|
|
s{^(.)/(\1.)/(\2.*?)/}{$3/}mxs; |
253
|
0
|
|
|
|
|
|
$data_for{bare_distro}{$bare_index_path} = $version_for; |
254
|
|
|
|
|
|
|
|
255
|
0
|
|
|
|
|
|
my %_localdata_for; |
256
|
0
|
|
|
|
|
|
my $score = 0; |
257
|
0
|
|
|
|
|
|
my $previous; |
258
|
0
|
|
|
|
|
|
while (my ($module, $version) = each %$version_for) { |
259
|
0
|
|
0
|
|
|
|
my $print_version = $version // 'undef'; |
260
|
0
|
|
|
|
|
|
DEBUG "data for $module: [$print_version] [$index_path]"; |
261
|
0
|
|
|
|
|
|
$_localdata_for{$module} = { |
262
|
|
|
|
|
|
|
version => $version, |
263
|
|
|
|
|
|
|
distro => $index_path, |
264
|
|
|
|
|
|
|
_file => $file, |
265
|
|
|
|
|
|
|
}; |
266
|
0
|
0
|
|
|
|
|
next if $score != 0; |
267
|
0
|
0
|
|
|
|
|
next unless exists($data_for{module}{$module}); |
268
|
0
|
|
|
|
|
|
$previous = $data_for{module}{$module}; |
269
|
0
|
|
|
|
|
|
DEBUG 'some previous version exists'; |
270
|
0
|
0
|
|
|
|
|
if (! defined $version) { |
|
|
0
|
|
|
|
|
|
271
|
0
|
0
|
|
|
|
|
$score = -1 if defined($previous->{version}); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
elsif (defined $previous->{version}) { |
274
|
0
|
|
|
|
|
|
my $tv = version->parse($version); |
275
|
0
|
|
|
|
|
|
my $pv = version->parse($previous->{version}); |
276
|
0
|
|
|
|
|
|
$score = $tv <=> $pv; |
277
|
|
|
|
|
|
|
} |
278
|
0
|
|
|
|
|
|
DEBUG "score: $score"; |
279
|
|
|
|
|
|
|
} ## end while (my ($module, $version...)) |
280
|
|
|
|
|
|
|
|
281
|
0
|
|
|
|
|
|
DEBUG "FINAL SCORE $score"; |
282
|
|
|
|
|
|
|
|
283
|
0
|
0
|
|
|
|
|
if ($score < 0) { # didn't win against something already in |
284
|
0
|
|
|
|
|
|
DEBUG "marking $file as obsolete"; |
285
|
0
|
|
|
|
|
|
$data_for{obsolete}{$file} = 1; |
286
|
0
|
|
|
|
|
|
next; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
DEBUG "getting $file data as winner (for the moment)"; |
290
|
0
|
0
|
|
|
|
|
if ($previous) { |
291
|
0
|
|
|
|
|
|
my $oip = $previous->{distro}; |
292
|
0
|
|
|
|
|
|
DEBUG "marking $oip as obsolete"; |
293
|
0
|
|
|
|
|
|
$data_for{obsolete}{$previous->{_file}} = 1; |
294
|
|
|
|
|
|
|
delete $data_for{module}{$_} |
295
|
0
|
|
|
|
|
|
for keys %{$data_for{distro}{$oip}}; |
|
0
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
# copy stuff over to the "official" data for modules |
298
|
0
|
|
|
|
|
|
$data_for{module}{$_} = $_localdata_for{$_} for keys %_localdata_for; |
299
|
|
|
|
|
|
|
} ## end for my $file (File::Find::Rule...) |
300
|
0
|
|
|
|
|
|
$self->last_index(\%data_for); |
301
|
0
|
0
|
|
|
|
|
return %data_for if wantarray(); |
302
|
0
|
|
|
|
|
|
return \%data_for; |
303
|
|
|
|
|
|
|
} ## end sub _collect_index_for |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub _index_body_for { |
306
|
0
|
|
|
0
|
|
|
my ($self, $path) = @_; |
307
|
|
|
|
|
|
|
|
308
|
0
|
|
|
|
|
|
my $data_for = $self->_collect_index_for($path); |
309
|
0
|
|
|
|
|
|
my $module_data_for = $data_for->{module}; |
310
|
0
|
|
|
|
|
|
my @retval; |
311
|
0
|
|
|
|
|
|
for my $module (sort keys %{$module_data_for}) { |
|
0
|
|
|
|
|
|
|
312
|
0
|
|
|
|
|
|
my $md = $module_data_for->{$module}; |
313
|
0
|
|
0
|
|
|
|
my $version = $md->{version} || 'undef'; |
314
|
0
|
|
|
|
|
|
my $index_path = $md->{distro}; |
315
|
0
|
|
|
|
|
|
my $fw = 38 - length $version; |
316
|
0
|
0
|
|
|
|
|
$fw = length $module if $fw < length $module; |
317
|
0
|
|
|
|
|
|
push @retval, sprintf "%-${fw}s %s %s", $module, $version, |
318
|
|
|
|
|
|
|
$index_path; |
319
|
|
|
|
|
|
|
} ## end for my $module (sort keys...) |
320
|
0
|
0
|
|
|
|
|
return @retval if wantarray(); |
321
|
0
|
|
|
|
|
|
return \@retval; |
322
|
|
|
|
|
|
|
} ## end sub _index_body_for |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
sub action_create { |
325
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
326
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
|
my $target = $self->target_dir; |
328
|
0
|
0
|
|
|
|
|
LOGDIE "target directory $target exists, use update instead" |
329
|
|
|
|
|
|
|
if -d $target; |
330
|
0
|
|
|
|
|
|
$target->mkpath(); |
331
|
|
|
|
|
|
|
|
332
|
0
|
|
|
|
|
|
return $self->action_update(); |
333
|
|
|
|
|
|
|
} ## end sub action_create |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub action_update { |
336
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
337
|
|
|
|
|
|
|
|
338
|
0
|
|
|
|
|
|
my $target = $self->target_dir; |
339
|
0
|
0
|
|
|
|
|
$target->mkpath() unless -d $target; |
340
|
|
|
|
|
|
|
|
341
|
0
|
|
|
|
|
|
my $dists = $target->stringify(); |
342
|
0
|
|
|
|
|
|
my $local = $target->subdir('local')->stringify(); |
343
|
0
|
0
|
|
|
|
|
my @command = ( |
344
|
|
|
|
|
|
|
qw< cpanm --reinstall --quiet --self-contained >, |
345
|
|
|
|
|
|
|
($self->execute_tests ? () : '--notest'), |
346
|
|
|
|
|
|
|
'--local-lib-contained' => $local, |
347
|
|
|
|
|
|
|
'--save-dists' => $dists, |
348
|
|
|
|
|
|
|
$self->args(), |
349
|
|
|
|
|
|
|
); |
350
|
|
|
|
|
|
|
|
351
|
0
|
|
|
|
|
|
my ($out, $err); |
352
|
|
|
|
|
|
|
{ |
353
|
0
|
|
|
|
|
|
local $SIG{TERM} = sub { |
354
|
0
|
|
|
0
|
|
|
WARN "cpanm: received TERM signal, ignoring"; |
355
|
0
|
|
|
|
|
|
}; |
356
|
0
|
|
|
|
|
|
INFO "calling @command"; |
357
|
0
|
0
|
|
|
|
|
IPC::Run::run \@command, \undef, \*STDOUT, \*STDERR |
358
|
|
|
|
|
|
|
or LOGDIE "cpanm: $? ($err)"; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
|
INFO 'onboarding completed, indexing...'; |
362
|
0
|
|
|
|
|
|
$self->_do_index($target); |
363
|
0
|
|
|
|
|
|
my $data_for = $self->last_index(); |
364
|
|
|
|
|
|
|
|
365
|
0
|
|
|
|
|
|
INFO 'saving distlist'; |
366
|
0
|
|
|
|
|
|
my @distros = $self->last_distlist(); |
367
|
0
|
|
|
|
|
|
$self->_save2($target->file('distlist.txt'), join "\n", @distros, ''); |
368
|
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
INFO 'saving modlist'; |
370
|
0
|
|
|
|
|
|
my @modules = $self->last_modlist(); |
371
|
0
|
|
|
|
|
|
$self->_save2($target->file('modlist.txt'), join "\n", @modules, ''); |
372
|
|
|
|
|
|
|
|
373
|
0
|
|
|
|
|
|
my $file = $target->file('install.sh'); |
374
|
0
|
0
|
|
|
|
|
if (!-e $file) { |
375
|
0
|
|
|
|
|
|
$self->_save2($file, <<'END_OF_INSTALL'); |
376
|
|
|
|
|
|
|
#!/bin/bash |
377
|
|
|
|
|
|
|
ME=$(readlink -f "$0") |
378
|
|
|
|
|
|
|
MYDIR=$(dirname "$ME") |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
TARGET="$MYDIR/local" |
381
|
|
|
|
|
|
|
[ $# -gt 0 ] && TARGET=$1 |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
if [ -n "$TARGET" ]; then |
384
|
|
|
|
|
|
|
"$MYDIR/cpanm" --mirror "file://$MYDIR" --mirror-only \ |
385
|
|
|
|
|
|
|
-L "$TARGET" \ |
386
|
|
|
|
|
|
|
$(<"$MYDIR/modlist.txt") |
387
|
|
|
|
|
|
|
else |
388
|
|
|
|
|
|
|
"$MYDIR/cpanm" --mirror "file://$MYDIR" --mirror-only \ |
389
|
|
|
|
|
|
|
$(<"$MYDIR/modlist.txt") |
390
|
|
|
|
|
|
|
fi |
391
|
|
|
|
|
|
|
END_OF_INSTALL |
392
|
0
|
|
|
|
|
|
chmod 0777 & ~umask(), $file->stringify(); |
393
|
|
|
|
|
|
|
} ## end if (!-e $file) |
394
|
|
|
|
|
|
|
|
395
|
0
|
|
|
|
|
|
$file = $target->file('cpanm'); |
396
|
0
|
0
|
|
|
|
|
if (!-e $file) { |
397
|
0
|
|
|
|
|
|
my $cpanm = which('cpanm'); |
398
|
0
|
|
|
|
|
|
File::Copy::copy($cpanm, $file->stringify()); |
399
|
0
|
|
|
|
|
|
chmod 0777 & ~umask(), $file->stringify(); |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
} ## end sub action_update |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
{ |
404
|
1
|
|
|
1
|
|
12
|
no strict 'subs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
642
|
|
405
|
|
|
|
|
|
|
*action_install = \&action_update; |
406
|
|
|
|
|
|
|
*action_add = \&action_update; |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
sub action_inject { |
410
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
411
|
|
|
|
|
|
|
|
412
|
0
|
|
|
|
|
|
my $target = $self->target_dir; |
413
|
0
|
0
|
|
|
|
|
$target->mkpath() unless -d $target; |
414
|
|
|
|
|
|
|
|
415
|
0
|
|
0
|
|
|
|
my $author = $self->config('author') // $ENV{EPAN_AUTHOR} // 'LOCAL'; |
|
|
|
0
|
|
|
|
|
416
|
0
|
|
|
|
|
|
my $first = substr $author, 0, 1; |
417
|
0
|
|
|
|
|
|
my $first_two = substr $author, 0, 2; |
418
|
0
|
|
|
|
|
|
my $repo = $target->subdir(qw< authors id >, $first, $first_two, $author); |
419
|
0
|
|
|
|
|
|
$repo->mkpath; |
420
|
0
|
|
|
|
|
|
$repo = $repo->stringify; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
|
File::Copy::copy($_, $repo) for $self->args; |
423
|
|
|
|
|
|
|
|
424
|
0
|
|
|
|
|
|
INFO 'onboarding completed, indexing...'; |
425
|
0
|
|
|
|
|
|
$self->_do_index($target); |
426
|
|
|
|
|
|
|
|
427
|
0
|
|
|
|
|
|
return; |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub action_list_obsoletes { |
431
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
432
|
0
|
|
|
|
|
|
my $basedir = $self->target_dir; |
433
|
0
|
|
|
|
|
|
my $data_for = $self->_collect_index_for($basedir); |
434
|
0
|
|
|
|
|
|
my @obsoletes = sort {$a cmp $b} keys %{$data_for->{obsolete}}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
435
|
0
|
|
|
|
|
|
say for @obsoletes; |
436
|
0
|
|
|
|
|
|
return; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
sub action_purge_obsoletes { |
440
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
441
|
0
|
|
|
|
|
|
my $basedir = $self->target_dir; |
442
|
0
|
|
|
|
|
|
my $data_for = $self->_collect_index_for($basedir); |
443
|
0
|
|
|
|
|
|
my @obsoletes = sort {$a cmp $b} keys %{$data_for->{obsolete}}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
444
|
0
|
|
|
|
|
|
for my $file (@obsoletes) { |
445
|
0
|
|
|
|
|
|
INFO "removing $file"; |
446
|
0
|
|
|
|
|
|
unlink $file; |
447
|
|
|
|
|
|
|
} |
448
|
0
|
|
|
|
|
|
return; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
sub action_list_actions { |
452
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
453
|
1
|
|
|
1
|
|
9
|
no strict 'refs'; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
353
|
|
454
|
0
|
|
|
|
|
|
say 'Available actions:'; |
455
|
0
|
|
|
|
|
|
say for |
456
|
0
|
|
|
|
|
|
sort {$a cmp $b} |
457
|
0
|
|
|
|
|
|
map {s/^action_/- /; s/_/-/g; $_ } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
458
|
0
|
0
|
|
|
|
|
grep {/^action_/ && $self->can($_)} |
459
|
0
|
|
|
|
|
|
keys %{ref($self)."::"}; |
460
|
0
|
|
|
|
|
|
return; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
sub last_distlist { |
464
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
465
|
0
|
|
|
|
|
|
return keys %{$self->last_index()->{bare_distro}}; |
|
0
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sub last_modlist { |
469
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
470
|
|
|
|
|
|
|
my @retval = |
471
|
0
|
|
|
|
|
|
map { (sort keys %$_)[0] } |
472
|
0
|
|
|
|
|
|
values %{$self->last_index()->{bare_distro}}; |
|
0
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
} ## end sub last_modlist |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
1; |
476
|
|
|
|
|
|
|
__END__ |