line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::EPAN; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
72824
|
use 5.012; |
|
1
|
|
|
|
|
4
|
|
4
|
|
|
|
|
|
|
{ our $VERSION = '0.001001' } |
5
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
29
|
|
6
|
1
|
|
|
1
|
|
725
|
use English qw( -no_match_vars ); |
|
1
|
|
|
|
|
4016
|
|
|
1
|
|
|
|
|
6
|
|
7
|
1
|
|
|
1
|
|
869
|
use version; |
|
1
|
|
|
|
|
2153
|
|
|
1
|
|
|
|
|
5
|
|
8
|
1
|
|
|
1
|
|
699
|
use autodie; |
|
1
|
|
|
|
|
16936
|
|
|
1
|
|
|
|
|
5
|
|
9
|
1
|
|
|
1
|
|
7871
|
use Getopt::Long qw< :config gnu_getopt >; |
|
1
|
|
|
|
|
13439
|
|
|
1
|
|
|
|
|
5
|
|
10
|
1
|
|
|
1
|
|
820
|
use Pod::Usage qw< pod2usage >; |
|
1
|
|
|
|
|
53349
|
|
|
1
|
|
|
|
|
147
|
|
11
|
1
|
|
|
1
|
|
767
|
use Dist::Metadata (); |
|
1
|
|
|
|
|
34697
|
|
|
1
|
|
|
|
|
34
|
|
12
|
1
|
|
|
1
|
|
728
|
use Path::Class qw< file dir >; |
|
1
|
|
|
|
|
41583
|
|
|
1
|
|
|
|
|
98
|
|
13
|
1
|
|
|
1
|
|
25
|
use Cwd qw< cwd >; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
42
|
|
14
|
1
|
|
|
1
|
|
858
|
use File::Find::Rule (); |
|
1
|
|
|
|
|
9046
|
|
|
1
|
|
|
|
|
38
|
|
15
|
1
|
|
|
1
|
|
907
|
use Compress::Zlib (); |
|
1
|
|
|
|
|
62777
|
|
|
1
|
|
|
|
|
41
|
|
16
|
1
|
|
|
1
|
|
839
|
use Log::Log4perl::Tiny qw< :easy :dead_if_first >; |
|
1
|
|
|
|
|
17348
|
|
|
1
|
|
|
|
|
8
|
|
17
|
1
|
|
|
1
|
|
1223
|
use Moo; |
|
1
|
|
|
|
|
13065
|
|
|
1
|
|
|
|
|
7
|
|
18
|
1
|
|
|
1
|
|
2998
|
use IPC::Run (); |
|
1
|
|
|
|
|
28040
|
|
|
1
|
|
|
|
|
34
|
|
19
|
1
|
|
|
1
|
|
682
|
use File::Copy (); |
|
1
|
|
|
|
|
2612
|
|
|
1
|
|
|
|
|
39
|
|
20
|
1
|
|
|
1
|
|
681
|
use File::Which qw< which >; |
|
1
|
|
|
|
|
1061
|
|
|
1
|
|
|
|
|
793
|
|
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
|
|
39
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2245
|
|
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
|
|
|
|
|
|
my $_03modlist_data_1 = <<'END_OF_03_MODLIST_DATA_1'; |
160
|
|
|
|
|
|
|
File: 03modlist.data |
161
|
|
|
|
|
|
|
Description: These are the data that are published in the module |
162
|
|
|
|
|
|
|
list, but they may be more recent than the latest posted |
163
|
|
|
|
|
|
|
modulelist. Over time we'll make sure that these data |
164
|
|
|
|
|
|
|
can be used to print the whole part two of the |
165
|
|
|
|
|
|
|
modulelist. Currently this is not the case. |
166
|
|
|
|
|
|
|
Modcount: 0 |
167
|
|
|
|
|
|
|
Written-By: PAUSE version 1.005 |
168
|
|
|
|
|
|
|
Date: Sun, 28 Jul 2013 07:41:15 GMT |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
pac |
171
|
|
|
|
|
|
|
END_OF_03_MODLIST_DATA_1 |
172
|
0
|
|
|
|
|
|
my $_03modlist_data_2 = <<'END_OF_03_MODLIST_DATA_2'; |
173
|
|
|
|
|
|
|
kage CPAN::Modulelist; |
174
|
|
|
|
|
|
|
# Usage: print Data::Dumper->new([CPAN::Modulelist->data])->Dump or similar |
175
|
|
|
|
|
|
|
# cannot 'use strict', because we normally run under Safe |
176
|
|
|
|
|
|
|
# use strict; |
177
|
|
|
|
|
|
|
sub data { |
178
|
|
|
|
|
|
|
my $result = {}; |
179
|
|
|
|
|
|
|
my $primary = "modid"; |
180
|
|
|
|
|
|
|
for (@$CPAN::Modulelist::data){ |
181
|
|
|
|
|
|
|
my %hash; |
182
|
|
|
|
|
|
|
@hash{@$CPAN::Modulelist::cols} = @$_; |
183
|
|
|
|
|
|
|
$result->{$hash{$primary}} = \%hash; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
return $result; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
$CPAN::Modulelist::cols = [ ]; |
188
|
|
|
|
|
|
|
$CPAN::Modulelist::data = [ ]; |
189
|
|
|
|
|
|
|
END_OF_03_MODLIST_DATA_2 |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
$_03modlist_data_1 =~ s{\s+\z}{}mxs; |
192
|
0
|
|
|
|
|
|
$_03modlist_data_2 =~ s{\A\s+}{}mxs; |
193
|
0
|
|
|
|
|
|
$self->_save( |
194
|
|
|
|
|
|
|
'03modlist.data', # name |
195
|
|
|
|
|
|
|
"$_03modlist_data_1$_03modlist_data_2", |
196
|
|
|
|
|
|
|
'modlist', # configuration key to look output file |
197
|
|
|
|
|
|
|
$basedir->file(qw< modules 03modlist.data.gz >) # default |
198
|
|
|
|
|
|
|
); |
199
|
|
|
|
|
|
|
} ## end sub _do_index |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub _save2 { |
202
|
0
|
|
|
0
|
|
|
my ($self, $path, $contents) = @_; |
203
|
0
|
|
|
|
|
|
my ($fh, $is_gz); |
204
|
0
|
0
|
|
|
|
|
if (ref($path) eq 'GLOB') { |
205
|
0
|
|
|
|
|
|
$fh = $path; |
206
|
0
|
|
|
|
|
|
$is_gz = 0; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
else { |
209
|
0
|
0
|
|
|
|
|
$path->dir()->mkpath() unless -d $path->dir()->stringify(); |
210
|
0
|
|
|
|
|
|
$fh = $path->open('>'); |
211
|
0
|
|
|
|
|
|
$is_gz = $path->stringify() =~ m{\.gz$}mxs; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
0
|
0
|
|
|
|
|
if ($is_gz) { |
215
|
0
|
|
|
|
|
|
my $gz = Compress::Zlib::gzopen($fh, 'wb'); |
216
|
0
|
|
|
|
|
|
$gz->gzwrite($contents); |
217
|
0
|
|
|
|
|
|
$gz->gzclose(); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
else { |
220
|
0
|
|
|
|
|
|
binmode $fh; |
221
|
0
|
|
|
|
|
|
print {$fh} $contents; |
|
0
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
} |
223
|
0
|
|
|
|
|
|
return; |
224
|
|
|
|
|
|
|
} ## end sub _save2 |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub _index_for { |
227
|
0
|
|
|
0
|
|
|
my ($self, $path) = @_; |
228
|
0
|
|
|
|
|
|
my @index = $self->_index_body_for($path); |
229
|
0
|
|
0
|
|
|
|
our $VERSION ||= 'whateva'; |
230
|
0
|
|
|
|
|
|
my $header = <<"END_OF_HEADER"; |
231
|
|
|
|
|
|
|
File: 02packages.details.txt |
232
|
|
|
|
|
|
|
URL: http://cpan.perl.org/modules/02packages.details.txt.gz |
233
|
|
|
|
|
|
|
Description: Package names found in directory \$CPAN/authors/id/ |
234
|
|
|
|
|
|
|
Columns: package name, version, path |
235
|
|
|
|
|
|
|
Intended-For: Automated fetch routines, namespace documentation. |
236
|
|
|
|
|
|
|
Written-By: epan $VERSION |
237
|
0
|
|
|
|
|
|
Line-Count: ${ \ scalar @index } |
238
|
0
|
|
|
|
|
|
Last-Updated: ${ \ scalar localtime() } |
239
|
|
|
|
|
|
|
END_OF_HEADER |
240
|
0
|
|
|
|
|
|
return join "\n", $header, @index, ''; |
241
|
|
|
|
|
|
|
} ## end sub _index_for |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub _collect_index_for { |
244
|
0
|
|
|
0
|
|
|
my ($self, $path) = @_; |
245
|
0
|
|
|
|
|
|
$path = dir($path); |
246
|
0
|
|
|
|
|
|
my $idpath = $path->subdir(qw< authors id >); |
247
|
0
|
|
|
|
|
|
my %data_for; |
248
|
0
|
|
|
|
|
|
for my $file (File::Find::Rule->extras({follow => 1})->file() |
249
|
|
|
|
|
|
|
->in($idpath->stringify())) |
250
|
|
|
|
|
|
|
{ |
251
|
0
|
|
|
|
|
|
INFO "indexing $file"; |
252
|
0
|
|
|
|
|
|
my $index_path = |
253
|
|
|
|
|
|
|
file($file)->relative($idpath)->as_foreign('Unix')->stringify(); |
254
|
0
|
|
|
|
|
|
my $dm = Dist::Metadata->new(file => $file); |
255
|
0
|
|
|
|
|
|
my $version_for = $dm->package_versions(); |
256
|
|
|
|
|
|
|
|
257
|
0
|
|
|
|
|
|
$data_for{distro}{$index_path} = $version_for; |
258
|
0
|
|
|
|
|
|
(my $bare_index_path = $index_path) =~ |
259
|
|
|
|
|
|
|
s{^(.)/(\1.)/(\2.*?)/}{$3/}mxs; |
260
|
0
|
|
|
|
|
|
$data_for{bare_distro}{$bare_index_path} = $version_for; |
261
|
|
|
|
|
|
|
|
262
|
0
|
|
|
|
|
|
my %_localdata_for; |
263
|
0
|
|
|
|
|
|
my $score = 0; |
264
|
0
|
|
|
|
|
|
my $previous; |
265
|
0
|
|
|
|
|
|
while (my ($module, $version) = each %$version_for) { |
266
|
0
|
|
0
|
|
|
|
my $print_version = $version // 'undef'; |
267
|
0
|
|
|
|
|
|
DEBUG "data for $module: [$print_version] [$index_path]"; |
268
|
0
|
|
|
|
|
|
$_localdata_for{$module} = { |
269
|
|
|
|
|
|
|
version => $version, |
270
|
|
|
|
|
|
|
distro => $index_path, |
271
|
|
|
|
|
|
|
_file => $file, |
272
|
|
|
|
|
|
|
}; |
273
|
0
|
0
|
|
|
|
|
next if $score != 0; |
274
|
0
|
0
|
|
|
|
|
next unless exists($data_for{module}{$module}); |
275
|
0
|
|
|
|
|
|
$previous = $data_for{module}{$module}; |
276
|
0
|
|
|
|
|
|
DEBUG 'some previous version exists'; |
277
|
0
|
0
|
|
|
|
|
if (! defined $version) { |
|
|
0
|
|
|
|
|
|
278
|
0
|
0
|
|
|
|
|
$score = -1 if defined($previous->{version}); |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
elsif (defined $previous->{version}) { |
281
|
0
|
|
|
|
|
|
my $tv = version->parse($version); |
282
|
0
|
|
|
|
|
|
my $pv = version->parse($previous->{version}); |
283
|
0
|
|
|
|
|
|
$score = $tv <=> $pv; |
284
|
|
|
|
|
|
|
} |
285
|
0
|
|
|
|
|
|
DEBUG "score: $score"; |
286
|
|
|
|
|
|
|
} ## end while (my ($module, $version...)) |
287
|
|
|
|
|
|
|
|
288
|
0
|
|
|
|
|
|
DEBUG "FINAL SCORE $score"; |
289
|
|
|
|
|
|
|
|
290
|
0
|
0
|
|
|
|
|
if ($score < 0) { # didn't win against something already in |
291
|
0
|
|
|
|
|
|
DEBUG "marking $file as obsolete"; |
292
|
0
|
|
|
|
|
|
$data_for{obsolete}{$file} = 1; |
293
|
0
|
|
|
|
|
|
next; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
0
|
|
|
|
|
|
DEBUG "getting $file data as winner (for the moment)"; |
297
|
0
|
0
|
|
|
|
|
if ($previous) { |
298
|
0
|
|
|
|
|
|
my $oip = $previous->{distro}; |
299
|
0
|
|
|
|
|
|
DEBUG "marking $oip as obsolete"; |
300
|
0
|
|
|
|
|
|
$data_for{obsolete}{$previous->{_file}} = 1; |
301
|
|
|
|
|
|
|
delete $data_for{module}{$_} |
302
|
0
|
|
|
|
|
|
for keys %{$data_for{distro}{$oip}}; |
|
0
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
# copy stuff over to the "official" data for modules |
305
|
0
|
|
|
|
|
|
$data_for{module}{$_} = $_localdata_for{$_} for keys %_localdata_for; |
306
|
|
|
|
|
|
|
} ## end for my $file (File::Find::Rule...) |
307
|
0
|
|
|
|
|
|
$self->last_index(\%data_for); |
308
|
0
|
0
|
|
|
|
|
return %data_for if wantarray(); |
309
|
0
|
|
|
|
|
|
return \%data_for; |
310
|
|
|
|
|
|
|
} ## end sub _collect_index_for |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub _index_body_for { |
313
|
0
|
|
|
0
|
|
|
my ($self, $path) = @_; |
314
|
|
|
|
|
|
|
|
315
|
0
|
|
|
|
|
|
my $data_for = $self->_collect_index_for($path); |
316
|
0
|
|
|
|
|
|
my $module_data_for = $data_for->{module}; |
317
|
0
|
|
|
|
|
|
my @retval; |
318
|
0
|
|
|
|
|
|
for my $module (sort keys %{$module_data_for}) { |
|
0
|
|
|
|
|
|
|
319
|
0
|
|
|
|
|
|
my $md = $module_data_for->{$module}; |
320
|
0
|
|
0
|
|
|
|
my $version = $md->{version} || 'undef'; |
321
|
0
|
|
|
|
|
|
my $index_path = $md->{distro}; |
322
|
0
|
|
|
|
|
|
my $fw = 38 - length $version; |
323
|
0
|
0
|
|
|
|
|
$fw = length $module if $fw < length $module; |
324
|
0
|
|
|
|
|
|
push @retval, sprintf "%-${fw}s %s %s", $module, $version, |
325
|
|
|
|
|
|
|
$index_path; |
326
|
|
|
|
|
|
|
} ## end for my $module (sort keys...) |
327
|
0
|
0
|
|
|
|
|
return @retval if wantarray(); |
328
|
0
|
|
|
|
|
|
return \@retval; |
329
|
|
|
|
|
|
|
} ## end sub _index_body_for |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub action_create { |
332
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
333
|
|
|
|
|
|
|
|
334
|
0
|
|
|
|
|
|
my $target = $self->target_dir; |
335
|
0
|
0
|
|
|
|
|
LOGDIE "target directory $target exists, use update instead" |
336
|
|
|
|
|
|
|
if -d $target; |
337
|
0
|
|
|
|
|
|
$target->mkpath(); |
338
|
|
|
|
|
|
|
|
339
|
0
|
|
|
|
|
|
return $self->action_update(); |
340
|
|
|
|
|
|
|
} ## end sub action_create |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
sub action_update { |
343
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
344
|
|
|
|
|
|
|
|
345
|
0
|
|
|
|
|
|
my $target = $self->target_dir; |
346
|
0
|
0
|
|
|
|
|
$target->mkpath() unless -d $target; |
347
|
|
|
|
|
|
|
|
348
|
0
|
|
|
|
|
|
my $dists = $target->stringify(); |
349
|
0
|
|
|
|
|
|
my $local = $target->subdir('local')->stringify(); |
350
|
0
|
0
|
|
|
|
|
my @command = ( |
351
|
|
|
|
|
|
|
qw< cpanm --reinstall --quiet --self-contained >, |
352
|
|
|
|
|
|
|
($self->execute_tests ? () : '--notest'), |
353
|
|
|
|
|
|
|
'--local-lib-contained' => $local, |
354
|
|
|
|
|
|
|
'--save-dists' => $dists, |
355
|
|
|
|
|
|
|
$self->args(), |
356
|
|
|
|
|
|
|
); |
357
|
|
|
|
|
|
|
|
358
|
0
|
|
|
|
|
|
my ($out, $err); |
359
|
|
|
|
|
|
|
{ |
360
|
0
|
|
|
|
|
|
local $SIG{TERM} = sub { |
361
|
0
|
|
|
0
|
|
|
WARN "cpanm: received TERM signal, ignoring"; |
362
|
0
|
|
|
|
|
|
}; |
363
|
0
|
|
|
|
|
|
INFO "calling @command"; |
364
|
0
|
0
|
|
|
|
|
IPC::Run::run \@command, \undef, \*STDOUT, \*STDERR |
365
|
|
|
|
|
|
|
or LOGDIE "cpanm: $? ($err)"; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
0
|
|
|
|
|
|
INFO 'onboarding completed, indexing...'; |
369
|
0
|
|
|
|
|
|
$self->_do_index($target); |
370
|
0
|
|
|
|
|
|
my $data_for = $self->last_index(); |
371
|
|
|
|
|
|
|
|
372
|
0
|
|
|
|
|
|
INFO 'saving distlist'; |
373
|
0
|
|
|
|
|
|
my @distros = $self->last_distlist(); |
374
|
0
|
|
|
|
|
|
$self->_save2($target->file('distlist.txt'), join "\n", @distros, ''); |
375
|
|
|
|
|
|
|
|
376
|
0
|
|
|
|
|
|
INFO 'saving modlist'; |
377
|
0
|
|
|
|
|
|
my @modules = $self->last_modlist(); |
378
|
0
|
|
|
|
|
|
$self->_save2($target->file('modlist.txt'), join "\n", @modules, ''); |
379
|
|
|
|
|
|
|
|
380
|
0
|
|
|
|
|
|
my $file = $target->file('install.sh'); |
381
|
0
|
0
|
|
|
|
|
if (!-e $file) { |
382
|
0
|
|
|
|
|
|
$self->_save2($file, <<'END_OF_INSTALL'); |
383
|
|
|
|
|
|
|
#!/bin/bash |
384
|
|
|
|
|
|
|
ME=$(readlink -f "$0") |
385
|
|
|
|
|
|
|
MYDIR=$(dirname "$ME") |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
TARGET="$MYDIR/local" |
388
|
|
|
|
|
|
|
[ $# -gt 0 ] && TARGET=$1 |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
if [ -n "$TARGET" ]; then |
391
|
|
|
|
|
|
|
"$MYDIR/cpanm" --mirror "file://$MYDIR" --mirror-only \ |
392
|
|
|
|
|
|
|
-L "$TARGET" \ |
393
|
|
|
|
|
|
|
$(<"$MYDIR/modlist.txt") |
394
|
|
|
|
|
|
|
else |
395
|
|
|
|
|
|
|
"$MYDIR/cpanm" --mirror "file://$MYDIR" --mirror-only \ |
396
|
|
|
|
|
|
|
$(<"$MYDIR/modlist.txt") |
397
|
|
|
|
|
|
|
fi |
398
|
|
|
|
|
|
|
END_OF_INSTALL |
399
|
0
|
|
|
|
|
|
chmod 0777 & ~umask(), $file->stringify(); |
400
|
|
|
|
|
|
|
} ## end if (!-e $file) |
401
|
|
|
|
|
|
|
|
402
|
0
|
|
|
|
|
|
$file = $target->file('cpanm'); |
403
|
0
|
0
|
|
|
|
|
if (!-e $file) { |
404
|
0
|
|
|
|
|
|
my $cpanm = which('cpanm'); |
405
|
0
|
|
|
|
|
|
File::Copy::copy($cpanm, $file->stringify()); |
406
|
0
|
|
|
|
|
|
chmod 0777 & ~umask(), $file->stringify(); |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
} ## end sub action_update |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
{ |
411
|
1
|
|
|
1
|
|
13
|
no strict 'subs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
525
|
|
412
|
|
|
|
|
|
|
*action_install = \&action_update; |
413
|
|
|
|
|
|
|
*action_add = \&action_update; |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
sub action_inject { |
417
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
418
|
|
|
|
|
|
|
|
419
|
0
|
|
|
|
|
|
my $target = $self->target_dir; |
420
|
0
|
0
|
|
|
|
|
$target->mkpath() unless -d $target; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
0
|
|
|
|
my $author = $self->config('author') // $ENV{EPAN_AUTHOR} // 'LOCAL'; |
|
|
|
0
|
|
|
|
|
423
|
0
|
|
|
|
|
|
my $first = substr $author, 0, 1; |
424
|
0
|
|
|
|
|
|
my $first_two = substr $author, 0, 2; |
425
|
0
|
|
|
|
|
|
my $repo = $target->subdir(qw< authors id >, $first, $first_two, $author); |
426
|
0
|
|
|
|
|
|
$repo->mkpath; |
427
|
0
|
|
|
|
|
|
$repo = $repo->stringify; |
428
|
|
|
|
|
|
|
|
429
|
0
|
|
|
|
|
|
File::Copy::copy($_, $repo) for $self->args; |
430
|
|
|
|
|
|
|
|
431
|
0
|
|
|
|
|
|
INFO 'onboarding completed, indexing...'; |
432
|
0
|
|
|
|
|
|
$self->_do_index($target); |
433
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
|
return; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
sub action_list_obsoletes { |
438
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
439
|
0
|
|
|
|
|
|
my $basedir = $self->target_dir; |
440
|
0
|
|
|
|
|
|
my $data_for = $self->_collect_index_for($basedir); |
441
|
0
|
|
|
|
|
|
my @obsoletes = sort {$a cmp $b} keys %{$data_for->{obsolete}}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
442
|
0
|
|
|
|
|
|
say for @obsoletes; |
443
|
0
|
|
|
|
|
|
return; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub action_purge_obsoletes { |
447
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
448
|
0
|
|
|
|
|
|
my $basedir = $self->target_dir; |
449
|
0
|
|
|
|
|
|
my $data_for = $self->_collect_index_for($basedir); |
450
|
0
|
|
|
|
|
|
my @obsoletes = sort {$a cmp $b} keys %{$data_for->{obsolete}}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
451
|
0
|
|
|
|
|
|
for my $file (@obsoletes) { |
452
|
0
|
|
|
|
|
|
INFO "removing $file"; |
453
|
0
|
|
|
|
|
|
unlink $file; |
454
|
|
|
|
|
|
|
} |
455
|
0
|
|
|
|
|
|
return; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub action_list_actions { |
459
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
460
|
1
|
|
|
1
|
|
9
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
354
|
|
461
|
0
|
|
|
|
|
|
say 'Available actions:'; |
462
|
0
|
|
|
|
|
|
say for |
463
|
0
|
|
|
|
|
|
sort {$a cmp $b} |
464
|
0
|
|
|
|
|
|
map {s/^action_/- /; s/_/-/g; $_ } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
465
|
0
|
0
|
|
|
|
|
grep {/^action_/ && $self->can($_)} |
466
|
0
|
|
|
|
|
|
keys %{ref($self)."::"}; |
467
|
0
|
|
|
|
|
|
return; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
sub last_distlist { |
471
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
472
|
0
|
|
|
|
|
|
return keys %{$self->last_index()->{bare_distro}}; |
|
0
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
sub last_modlist { |
476
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
477
|
|
|
|
|
|
|
my @retval = |
478
|
0
|
|
|
|
|
|
map { (sort keys %$_)[0] } |
479
|
0
|
|
|
|
|
|
values %{$self->last_index()->{bare_distro}}; |
|
0
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
} ## end sub last_modlist |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
1; |
483
|
|
|
|
|
|
|
__END__ |