line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- |
2
|
|
|
|
|
|
|
# vim:ts=8:sw=2:et:sta:sts=2:tw=78 |
3
|
|
|
|
|
|
|
package Module::Metadata; # git description: v1.000035-3-gaa51be1 |
4
|
|
|
|
|
|
|
# ABSTRACT: Gather package and POD information from perl module files |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# Adapted from Perl-licensed code originally distributed with |
7
|
|
|
|
|
|
|
# Module-Build by Ken Williams |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# This module provides routines to gather information about |
10
|
|
|
|
|
|
|
# perl modules (assuming this may be expanded in the distant |
11
|
|
|
|
|
|
|
# parrot future to look at other types of modules). |
12
|
|
|
|
|
|
|
|
13
|
111
|
|
|
111
|
|
10473
|
sub __clean_eval { eval $_[0] } |
|
6
|
|
|
7
|
|
48
|
|
|
6
|
|
|
5
|
|
12
|
|
|
6
|
|
|
5
|
|
41
|
|
|
4
|
|
|
5
|
|
29
|
|
|
4
|
|
|
5
|
|
19
|
|
|
4
|
|
|
4
|
|
19
|
|
|
4
|
|
|
4
|
|
33
|
|
|
4
|
|
|
4
|
|
19
|
|
|
4
|
|
|
4
|
|
18
|
|
|
4
|
|
|
1
|
|
29
|
|
|
4
|
|
|
1
|
|
9
|
|
|
4
|
|
|
1
|
|
21
|
|
|
4
|
|
|
1
|
|
31
|
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
19
|
|
|
3
|
|
|
|
|
22
|
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
23
|
|
|
3
|
|
|
|
|
21
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
27
|
|
|
3
|
|
|
|
|
22
|
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
14
|
|
|
3
|
|
|
|
|
30
|
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
16
|
|
14
|
10
|
|
|
10
|
|
481229
|
use strict; |
|
10
|
|
|
|
|
97
|
|
|
10
|
|
|
|
|
240
|
|
15
|
10
|
|
|
10
|
|
54
|
use warnings; |
|
10
|
|
|
|
|
27
|
|
|
10
|
|
|
|
|
378
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '1.000036'; |
18
|
|
|
|
|
|
|
|
19
|
10
|
|
|
10
|
|
63
|
use Carp qw/croak/; |
|
10
|
|
|
|
|
40
|
|
|
10
|
|
|
|
|
403
|
|
20
|
10
|
|
|
10
|
|
66
|
use File::Spec; |
|
10
|
|
|
|
|
27
|
|
|
10
|
|
|
|
|
657
|
|
21
|
|
|
|
|
|
|
BEGIN { |
22
|
|
|
|
|
|
|
# Try really hard to not depend ony any DynaLoaded module, such as IO::File or Fcntl |
23
|
|
|
|
|
|
|
eval { |
24
|
10
|
|
|
|
|
56
|
require Fcntl; Fcntl->import('SEEK_SET'); 1; |
|
10
|
|
|
|
|
273
|
|
|
10
|
|
|
|
|
282
|
|
25
|
2
|
|
|
|
|
4
|
} or *SEEK_SET = sub { 0 } |
26
|
10
|
50
|
|
10
|
|
40
|
} |
27
|
10
|
|
|
10
|
|
3629
|
use version 0.87; |
|
10
|
|
|
|
|
15609
|
|
|
10
|
|
|
|
|
68
|
|
28
|
|
|
|
|
|
|
BEGIN { |
29
|
10
|
50
|
|
10
|
|
1207
|
if ($INC{'Log/Contextual.pm'}) { |
30
|
2
|
|
|
|
|
19
|
require "Log/Contextual/WarnLogger.pm"; # Hide from AutoPrereqs |
31
|
2
|
|
|
|
|
5
|
Log::Contextual->import('log_info', |
32
|
|
|
|
|
|
|
'-default_logger' => Log::Contextual::WarnLogger->new({ env_prefix => 'MODULE_METADATA', }), |
33
|
|
|
|
|
|
|
); |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
else { |
36
|
10
|
|
|
2
|
|
196
|
*log_info = sub (&) { warn $_[0]->() }; |
|
2
|
|
|
|
|
15
|
|
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
} |
39
|
10
|
|
|
10
|
|
426
|
use File::Find qw(find); |
|
10
|
|
|
|
|
41
|
|
|
10
|
|
|
|
|
36166
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my $V_NUM_REGEXP = qr{v?[0-9._]+}; # crudely, a v-string or decimal |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my $PKG_FIRST_WORD_REGEXP = qr{ # the FIRST word in a package name |
44
|
|
|
|
|
|
|
[a-zA-Z_] # the first word CANNOT start with a digit |
45
|
|
|
|
|
|
|
(?: |
46
|
|
|
|
|
|
|
[\w']? # can contain letters, digits, _, or ticks |
47
|
|
|
|
|
|
|
\w # But, NO multi-ticks or trailing ticks |
48
|
|
|
|
|
|
|
)* |
49
|
|
|
|
|
|
|
}x; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
my $PKG_ADDL_WORD_REGEXP = qr{ # the 2nd+ word in a package name |
52
|
|
|
|
|
|
|
\w # the 2nd+ word CAN start with digits |
53
|
|
|
|
|
|
|
(?: |
54
|
|
|
|
|
|
|
[\w']? # and can contain letters or ticks |
55
|
|
|
|
|
|
|
\w # But, NO multi-ticks or trailing ticks |
56
|
|
|
|
|
|
|
)* |
57
|
|
|
|
|
|
|
}x; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
my $PKG_NAME_REGEXP = qr{ # match a package name |
60
|
|
|
|
|
|
|
(?: :: )? # a pkg name can start with arisdottle |
61
|
|
|
|
|
|
|
$PKG_FIRST_WORD_REGEXP # a package word |
62
|
|
|
|
|
|
|
(?: |
63
|
|
|
|
|
|
|
(?: :: )+ ### arisdottle (allow one or many times) |
64
|
|
|
|
|
|
|
$PKG_ADDL_WORD_REGEXP ### a package word |
65
|
|
|
|
|
|
|
)* # ^ zero, one or many times |
66
|
|
|
|
|
|
|
(?: |
67
|
|
|
|
|
|
|
:: # allow trailing arisdottle |
68
|
|
|
|
|
|
|
)? |
69
|
|
|
|
|
|
|
}x; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
my $PKG_REGEXP = qr{ # match a package declaration |
72
|
|
|
|
|
|
|
^[\s\{;]* # intro chars on a line |
73
|
|
|
|
|
|
|
package # the word 'package' |
74
|
|
|
|
|
|
|
\s+ # whitespace |
75
|
|
|
|
|
|
|
($PKG_NAME_REGEXP) # a package name |
76
|
|
|
|
|
|
|
\s* # optional whitespace |
77
|
|
|
|
|
|
|
($V_NUM_REGEXP)? # optional version number |
78
|
|
|
|
|
|
|
\s* # optional whitesapce |
79
|
|
|
|
|
|
|
[;\{] # semicolon line terminator or block start (since 5.16) |
80
|
|
|
|
|
|
|
}x; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
my $VARNAME_REGEXP = qr{ # match fully-qualified VERSION name |
83
|
|
|
|
|
|
|
([\$*]) # sigil - $ or * |
84
|
|
|
|
|
|
|
( |
85
|
|
|
|
|
|
|
( # optional leading package name |
86
|
|
|
|
|
|
|
(?:::|\')? # possibly starting like just :: (a la $::VERSION) |
87
|
|
|
|
|
|
|
(?:\w+(?:::|\'))* # Foo::Bar:: ... |
88
|
|
|
|
|
|
|
)? |
89
|
|
|
|
|
|
|
VERSION |
90
|
|
|
|
|
|
|
)\b |
91
|
|
|
|
|
|
|
}x; |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
my $VERS_REGEXP = qr{ # match a VERSION definition |
94
|
|
|
|
|
|
|
(?: |
95
|
|
|
|
|
|
|
\(\s*$VARNAME_REGEXP\s*\) # with parens |
96
|
|
|
|
|
|
|
| |
97
|
|
|
|
|
|
|
$VARNAME_REGEXP # without parens |
98
|
|
|
|
|
|
|
) |
99
|
|
|
|
|
|
|
\s* |
100
|
|
|
|
|
|
|
=[^=~>] # = but not ==, nor =~, nor => |
101
|
|
|
|
|
|
|
}x; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub new_from_file { |
104
|
103
|
|
|
103
|
1
|
259345
|
my $class = shift; |
105
|
103
|
|
|
|
|
1721
|
my $filename = File::Spec->rel2abs( shift ); |
106
|
|
|
|
|
|
|
|
107
|
103
|
100
|
66
|
|
|
1997
|
return undef unless defined( $filename ) && -f $filename; |
108
|
102
|
|
|
|
|
472
|
return $class->_init(undef, $filename, @_); |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub new_from_handle { |
112
|
7
|
|
|
7
|
1
|
2661
|
my $class = shift; |
113
|
7
|
|
|
|
|
18
|
my $handle = shift; |
114
|
7
|
|
|
|
|
30
|
my $filename = shift; |
115
|
7
|
100
|
66
|
|
|
47
|
return undef unless defined($handle) && defined($filename); |
116
|
6
|
|
|
|
|
134
|
$filename = File::Spec->rel2abs( $filename ); |
117
|
|
|
|
|
|
|
|
118
|
6
|
|
|
|
|
40
|
return $class->_init(undef, $filename, @_, handle => $handle); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub new_from_module { |
124
|
8
|
|
|
8
|
1
|
3584
|
my $class = shift; |
125
|
8
|
|
|
|
|
17
|
my $module = shift; |
126
|
8
|
|
|
|
|
28
|
my %props = @_; |
127
|
|
|
|
|
|
|
|
128
|
8
|
|
100
|
|
|
44
|
$props{inc} ||= \@INC; |
129
|
8
|
|
|
|
|
27
|
my $filename = $class->find_module_by_name( $module, $props{inc} ); |
130
|
8
|
100
|
66
|
|
|
114
|
return undef unless defined( $filename ) && -f $filename; |
131
|
7
|
|
|
|
|
49
|
return $class->_init($module, $filename, %props); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
{ |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
my $compare_versions = sub { |
137
|
|
|
|
|
|
|
my ($v1, $op, $v2) = @_; |
138
|
|
|
|
|
|
|
$v1 = version->new($v1) |
139
|
|
|
|
|
|
|
unless UNIVERSAL::isa($v1,'version'); |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
my $eval_str = "\$v1 $op \$v2"; |
142
|
|
|
|
|
|
|
my $result = eval $eval_str; |
143
|
|
|
|
|
|
|
log_info { "error comparing versions: '$eval_str' $@" } if $@; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
return $result; |
146
|
|
|
|
|
|
|
}; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
my $normalize_version = sub { |
149
|
|
|
|
|
|
|
my ($version) = @_; |
150
|
|
|
|
|
|
|
if ( $version =~ /[=<>!,]/ ) { # logic, not just version |
151
|
|
|
|
|
|
|
# take as is without modification |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
elsif ( ref $version eq 'version' ) { # version objects |
154
|
|
|
|
|
|
|
$version = $version->is_qv ? $version->normal : $version->stringify; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
elsif ( $version =~ /^[^v][^.]*\.[^.]+\./ ) { # no leading v, multiple dots |
157
|
|
|
|
|
|
|
# normalize string tuples without "v": "1.2.3" -> "v1.2.3" |
158
|
|
|
|
|
|
|
$version = "v$version"; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
else { |
161
|
|
|
|
|
|
|
# leave alone |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
return $version; |
164
|
|
|
|
|
|
|
}; |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# separate out some of the conflict resolution logic |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
my $resolve_module_versions = sub { |
169
|
|
|
|
|
|
|
my $packages = shift; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
my( $file, $version ); |
172
|
|
|
|
|
|
|
my $err = ''; |
173
|
|
|
|
|
|
|
foreach my $p ( @$packages ) { |
174
|
|
|
|
|
|
|
if ( defined( $p->{version} ) ) { |
175
|
|
|
|
|
|
|
if ( defined( $version ) ) { |
176
|
|
|
|
|
|
|
if ( $compare_versions->( $version, '!=', $p->{version} ) ) { |
177
|
|
|
|
|
|
|
$err .= " $p->{file} ($p->{version})\n"; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
else { |
180
|
|
|
|
|
|
|
# same version declared multiple times, ignore |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
else { |
184
|
|
|
|
|
|
|
$file = $p->{file}; |
185
|
|
|
|
|
|
|
$version = $p->{version}; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
$file ||= $p->{file} if defined( $p->{file} ); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
if ( $err ) { |
192
|
|
|
|
|
|
|
$err = " $file ($version)\n" . $err; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
my %result = ( |
196
|
|
|
|
|
|
|
file => $file, |
197
|
|
|
|
|
|
|
version => $version, |
198
|
|
|
|
|
|
|
err => $err |
199
|
|
|
|
|
|
|
); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
return \%result; |
202
|
|
|
|
|
|
|
}; |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
sub provides { |
205
|
4
|
|
|
4
|
1
|
1916
|
my $class = shift; |
206
|
|
|
|
|
|
|
|
207
|
4
|
50
|
|
|
|
23
|
croak "provides() requires key/value pairs \n" if @_ % 2; |
208
|
4
|
|
|
|
|
33
|
my %args = @_; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
croak "provides() takes only one of 'dir' or 'files'\n" |
211
|
4
|
50
|
33
|
|
|
18
|
if $args{dir} && $args{files}; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
croak "provides() requires a 'version' argument" |
214
|
4
|
50
|
|
|
|
27
|
unless defined $args{version}; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
croak "provides() does not support version '$args{version}' metadata" |
217
|
4
|
50
|
|
|
|
36
|
unless grep $args{version} eq $_, qw/1.4 2/; |
218
|
|
|
|
|
|
|
|
219
|
4
|
100
|
|
|
|
14
|
$args{prefix} = 'lib' unless defined $args{prefix}; |
220
|
|
|
|
|
|
|
|
221
|
4
|
|
|
|
|
16
|
my $p; |
222
|
4
|
50
|
|
|
|
125
|
if ( $args{dir} ) { |
223
|
4
|
|
|
|
|
9
|
$p = $class->package_versions_from_directory($args{dir}); |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
else { |
226
|
|
|
|
|
|
|
croak "provides() requires 'files' to be an array reference\n" |
227
|
2
|
0
|
|
|
|
10
|
unless ref $args{files} eq 'ARRAY'; |
228
|
2
|
|
|
|
|
25
|
$p = $class->package_versions_from_directory($args{files}); |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# Now, fix up files with prefix |
232
|
4
|
50
|
|
|
|
12
|
if ( length $args{prefix} ) { # check in case disabled with q{} |
233
|
4
|
|
|
|
|
15
|
$args{prefix} =~ s{/$}{}; |
234
|
4
|
|
|
|
|
105
|
for my $v ( values %$p ) { |
235
|
6
|
|
|
|
|
29
|
$v->{file} = "$args{prefix}/$v->{file}"; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
4
|
|
|
|
|
22
|
return $p |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub package_versions_from_directory { |
243
|
6
|
|
|
6
|
1
|
1228
|
my ( $class, $dir, $files ) = @_; |
244
|
|
|
|
|
|
|
|
245
|
6
|
|
|
|
|
11
|
my @files; |
246
|
|
|
|
|
|
|
|
247
|
6
|
100
|
|
|
|
24
|
if ( $files ) { |
248
|
3
|
|
|
|
|
18
|
@files = @$files; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
else { |
251
|
|
|
|
|
|
|
find( { |
252
|
|
|
|
|
|
|
wanted => sub { |
253
|
8
|
100
|
66
|
8
|
|
418
|
push @files, $_ if -f $_ && /\.pm$/; |
254
|
|
|
|
|
|
|
}, |
255
|
5
|
|
|
|
|
281
|
no_chdir => 1, |
256
|
|
|
|
|
|
|
}, $dir ); |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# First, we enumerate all packages & versions, |
260
|
|
|
|
|
|
|
# separating into primary & alternative candidates |
261
|
6
|
|
|
|
|
40
|
my( %prime, %alt ); |
262
|
6
|
|
|
|
|
17
|
foreach my $file (@files) { |
263
|
6
|
|
|
|
|
322
|
my $mapped_filename = File::Spec->abs2rel( $file, $dir ); |
264
|
6
|
|
|
|
|
47
|
my @path = File::Spec->splitdir( $mapped_filename ); |
265
|
6
|
|
|
|
|
37
|
(my $prime_package = join( '::', @path )) =~ s/\.pm$//; |
266
|
|
|
|
|
|
|
|
267
|
6
|
|
|
|
|
34
|
my $pm_info = $class->new_from_file( $file ); |
268
|
|
|
|
|
|
|
|
269
|
6
|
|
|
|
|
36
|
foreach my $package ( $pm_info->packages_inside ) { |
270
|
22
|
100
|
|
|
|
49
|
next if $package eq 'main'; # main can appear numerous times, ignore |
271
|
18
|
100
|
|
|
|
45
|
next if $package eq 'DB'; # special debugging package, ignore |
272
|
14
|
100
|
|
|
|
88
|
next if grep /^_/, split( /::/, $package ); # private package, ignore |
273
|
|
|
|
|
|
|
|
274
|
10
|
|
|
|
|
30
|
my $version = $pm_info->version( $package ); |
275
|
|
|
|
|
|
|
|
276
|
10
|
100
|
|
|
|
35
|
$prime_package = $package if lc($prime_package) eq lc($package); |
277
|
9
|
100
|
|
|
|
29
|
if ( $package eq $prime_package ) { |
278
|
5
|
50
|
|
|
|
13
|
if ( exists( $prime{$package} ) ) { |
279
|
1
|
|
|
|
|
7
|
croak "Unexpected conflict in '$package'; multiple versions found.\n"; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
else { |
282
|
5
|
50
|
|
|
|
22
|
$mapped_filename = "$package.pm" if lc("$package.pm") eq lc($mapped_filename); |
283
|
5
|
|
|
|
|
21
|
$prime{$package}{file} = $mapped_filename; |
284
|
5
|
50
|
|
|
|
20
|
$prime{$package}{version} = $version if defined( $version ); |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
else { |
288
|
5
|
|
|
|
|
14
|
push( @{$alt{$package}}, { |
|
5
|
|
|
|
|
26
|
|
289
|
|
|
|
|
|
|
file => $mapped_filename, |
290
|
|
|
|
|
|
|
version => $version, |
291
|
|
|
|
|
|
|
} ); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# Then we iterate over all the packages found above, identifying conflicts |
297
|
|
|
|
|
|
|
# and selecting the "best" candidate for recording the file & version |
298
|
|
|
|
|
|
|
# for each package. |
299
|
5
|
|
|
|
|
20
|
foreach my $package ( keys( %alt ) ) { |
300
|
5
|
|
|
|
|
19
|
my $result = $resolve_module_versions->( $alt{$package} ); |
301
|
|
|
|
|
|
|
|
302
|
5
|
50
|
|
|
|
13
|
if ( exists( $prime{$package} ) ) { # primary package selected |
303
|
|
|
|
|
|
|
|
304
|
1
|
0
|
|
|
|
8
|
if ( $result->{err} ) { |
|
|
0
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# Use the selected primary package, but there are conflicting |
306
|
|
|
|
|
|
|
# errors among multiple alternative packages that need to be |
307
|
|
|
|
|
|
|
# reported |
308
|
|
|
|
|
|
|
log_info { |
309
|
|
|
|
|
|
|
"Found conflicting versions for package '$package'\n" . |
310
|
|
|
|
|
|
|
" $prime{$package}{file} ($prime{$package}{version})\n" . |
311
|
|
|
|
|
|
|
$result->{err} |
312
|
1
|
|
|
2
|
|
7
|
}; |
|
1
|
|
|
|
|
15
|
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
elsif ( defined( $result->{version} ) ) { |
316
|
|
|
|
|
|
|
# There is a primary package selected, and exactly one |
317
|
|
|
|
|
|
|
# alternative package |
318
|
|
|
|
|
|
|
|
319
|
1
|
0
|
0
|
|
|
6
|
if ( exists( $prime{$package}{version} ) && |
320
|
|
|
|
|
|
|
defined( $prime{$package}{version} ) ) { |
321
|
|
|
|
|
|
|
# Unless the version of the primary package agrees with the |
322
|
|
|
|
|
|
|
# version of the alternative package, report a conflict |
323
|
1
|
0
|
|
|
|
20
|
if ( $compare_versions->( |
324
|
|
|
|
|
|
|
$prime{$package}{version}, '!=', $result->{version} |
325
|
|
|
|
|
|
|
) |
326
|
|
|
|
|
|
|
) { |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
log_info { |
329
|
1
|
|
|
2
|
|
13
|
"Found conflicting versions for package '$package'\n" . |
330
|
|
|
|
|
|
|
" $prime{$package}{file} ($prime{$package}{version})\n" . |
331
|
|
|
|
|
|
|
" $result->{file} ($result->{version})\n" |
332
|
1
|
|
|
|
|
2
|
}; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
else { |
337
|
|
|
|
|
|
|
# The prime package selected has no version so, we choose to |
338
|
|
|
|
|
|
|
# use any alternative package that does have a version |
339
|
1
|
|
|
|
|
7
|
$prime{$package}{file} = $result->{file}; |
340
|
1
|
|
|
|
|
14
|
$prime{$package}{version} = $result->{version}; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
else { |
345
|
|
|
|
|
|
|
# no alt package found with a version, but we have a prime |
346
|
|
|
|
|
|
|
# package so we use it whether it has a version or not |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
else { # No primary package was selected, use the best alternative |
351
|
|
|
|
|
|
|
|
352
|
5
|
50
|
|
|
|
27
|
if ( $result->{err} ) { |
353
|
|
|
|
|
|
|
log_info { |
354
|
|
|
|
|
|
|
"Found conflicting versions for package '$package'\n" . |
355
|
|
|
|
|
|
|
$result->{err} |
356
|
1
|
|
|
2
|
|
7
|
}; |
|
1
|
|
|
|
|
11
|
|
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# Despite possible conflicting versions, we choose to record |
360
|
|
|
|
|
|
|
# something rather than nothing |
361
|
5
|
|
|
|
|
19
|
$prime{$package}{file} = $result->{file}; |
362
|
|
|
|
|
|
|
$prime{$package}{version} = $result->{version} |
363
|
5
|
50
|
|
|
|
25
|
if defined( $result->{version} ); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# Normalize versions. Can't use exists() here because of bug in YAML::Node. |
368
|
|
|
|
|
|
|
# XXX "bug in YAML::Node" comment seems irrelevant -- dagolden, 2009-05-18 |
369
|
5
|
|
|
|
|
21
|
for (grep defined $_->{version}, values %prime) { |
370
|
9
|
|
|
|
|
22
|
$_->{version} = $normalize_version->( $_->{version} ); |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
5
|
|
|
|
|
27
|
return \%prime; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub _init { |
379
|
110
|
|
|
111
|
|
261
|
my $class = shift; |
380
|
110
|
|
|
|
|
171
|
my $module = shift; |
381
|
110
|
|
|
|
|
186
|
my $filename = shift; |
382
|
110
|
|
|
|
|
226
|
my %props = @_; |
383
|
|
|
|
|
|
|
|
384
|
110
|
|
|
|
|
223
|
my $handle = delete $props{handle}; |
385
|
110
|
|
|
|
|
189
|
my( %valid_props, @valid_props ); |
386
|
110
|
|
|
|
|
277
|
@valid_props = qw( collect_pod inc ); |
387
|
110
|
|
|
|
|
384
|
@valid_props{@valid_props} = delete( @props{@valid_props} ); |
388
|
110
|
50
|
|
|
|
260
|
warn "Unknown properties: @{[keys %props]}\n" if scalar( %props ); |
|
1
|
|
|
|
|
2
|
|
389
|
|
|
|
|
|
|
|
390
|
110
|
|
|
|
|
941
|
my %data = ( |
391
|
|
|
|
|
|
|
module => $module, |
392
|
|
|
|
|
|
|
filename => $filename, |
393
|
|
|
|
|
|
|
version => undef, |
394
|
|
|
|
|
|
|
packages => [], |
395
|
|
|
|
|
|
|
versions => {}, |
396
|
|
|
|
|
|
|
pod => {}, |
397
|
|
|
|
|
|
|
pod_headings => [], |
398
|
|
|
|
|
|
|
collect_pod => 0, |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
%valid_props, |
401
|
|
|
|
|
|
|
); |
402
|
|
|
|
|
|
|
|
403
|
110
|
|
|
|
|
303
|
my $self = bless(\%data, $class); |
404
|
|
|
|
|
|
|
|
405
|
110
|
100
|
|
|
|
257
|
if ( not $handle ) { |
406
|
106
|
|
|
|
|
215
|
my $filename = $self->{filename}; |
407
|
106
|
50
|
|
|
|
3439
|
open $handle, '<', $filename |
408
|
|
|
|
|
|
|
or croak( "Can't open '$filename': $!" ); |
409
|
|
|
|
|
|
|
|
410
|
106
|
|
|
|
|
473
|
$self->_handle_bom($handle, $filename); |
411
|
|
|
|
|
|
|
} |
412
|
110
|
|
|
|
|
345
|
$self->_parse_fh($handle); |
413
|
|
|
|
|
|
|
|
414
|
110
|
|
|
|
|
323
|
@{$self->{packages}} = __uniq(@{$self->{packages}}); |
|
110
|
|
|
|
|
311
|
|
|
110
|
|
|
|
|
401
|
|
415
|
|
|
|
|
|
|
|
416
|
110
|
100
|
66
|
|
|
354
|
unless($self->{module} and length($self->{module})) { |
417
|
|
|
|
|
|
|
# CAVEAT (possible TODO): .pmc files not treated the same as .pm |
418
|
105
|
100
|
|
|
|
652
|
if ($self->{filename} =~ /\.pm$/) { |
419
|
96
|
|
|
|
|
1372
|
my ($v, $d, $f) = File::Spec->splitpath($self->{filename}); |
420
|
96
|
|
|
|
|
398
|
$f =~ s/\..+$//; |
421
|
96
|
|
|
|
|
159
|
my @candidates = grep /(^|::)$f$/, @{$self->{packages}}; |
|
96
|
|
|
|
|
784
|
|
422
|
96
|
|
|
|
|
331
|
$self->{module} = shift(@candidates); # this may be undef |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
else { |
425
|
|
|
|
|
|
|
# this seems like an atrocious heuristic, albeit marginally better than |
426
|
|
|
|
|
|
|
# what was here before. It should be rewritten entirely to be more like |
427
|
|
|
|
|
|
|
# "if it's not a .pm file, it's not require()able as a name, therefore |
428
|
|
|
|
|
|
|
# name() should be undef." |
429
|
10
|
100
|
100
|
|
|
24
|
if ((grep /main/, @{$self->{packages}}) |
|
10
|
|
|
|
|
54
|
|
430
|
4
|
|
|
|
|
20
|
or (grep /main/, keys %{$self->{versions}})) { |
431
|
9
|
|
|
|
|
24
|
$self->{module} = 'main'; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
else { |
434
|
|
|
|
|
|
|
# TODO: this should maybe default to undef instead |
435
|
2
|
|
50
|
|
|
15
|
$self->{module} = $self->{packages}[0] || ''; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
$self->{version} = $self->{versions}{$self->{module}} |
441
|
110
|
100
|
|
|
|
355
|
if defined( $self->{module} ); |
442
|
|
|
|
|
|
|
|
443
|
110
|
|
|
|
|
1824
|
return $self; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
# class method |
447
|
|
|
|
|
|
|
sub _do_find_module { |
448
|
8
|
|
|
9
|
|
20
|
my $class = shift; |
449
|
8
|
|
33
|
|
|
29
|
my $module = shift || croak 'find_module_by_name() requires a package name'; |
450
|
8
|
|
100
|
|
|
34
|
my $dirs = shift || \@INC; |
451
|
|
|
|
|
|
|
|
452
|
8
|
|
|
|
|
105
|
my $file = File::Spec->catfile(split( /::/, $module)); |
453
|
8
|
|
|
|
|
28
|
foreach my $dir ( @$dirs ) { |
454
|
10
|
|
|
|
|
75
|
my $testfile = File::Spec->catfile($dir, $file); |
455
|
9
|
50
|
33
|
|
|
158
|
return [ File::Spec->rel2abs( $testfile ), $dir ] |
456
|
|
|
|
|
|
|
if -e $testfile and !-d _; # For stuff like ExtUtils::xsubpp |
457
|
|
|
|
|
|
|
# CAVEAT (possible TODO): .pmc files are not discoverable here |
458
|
9
|
|
|
|
|
24
|
$testfile .= '.pm'; |
459
|
9
|
100
|
|
|
|
276
|
return [ File::Spec->rel2abs( $testfile ), $dir ] |
460
|
|
|
|
|
|
|
if -e $testfile; |
461
|
|
|
|
|
|
|
} |
462
|
1
|
|
|
|
|
4
|
return; |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
# class method |
466
|
|
|
|
|
|
|
sub find_module_by_name { |
467
|
7
|
100
|
|
9
|
1
|
487
|
my $found = shift()->_do_find_module(@_) or return; |
468
|
6
|
|
|
|
|
26
|
return $found->[0]; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# class method |
472
|
|
|
|
|
|
|
sub find_module_dir_by_name { |
473
|
0
|
0
|
|
2
|
1
|
0
|
my $found = shift()->_do_find_module(@_) or return; |
474
|
0
|
|
|
|
|
0
|
return $found->[1]; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
# given a line of perl code, attempt to parse it if it looks like a |
479
|
|
|
|
|
|
|
# $VERSION assignment, returning sigil, full name, & package name |
480
|
|
|
|
|
|
|
sub _parse_version_expression { |
481
|
133
|
|
|
135
|
|
234
|
my $self = shift; |
482
|
133
|
|
|
|
|
248
|
my $line = shift; |
483
|
|
|
|
|
|
|
|
484
|
133
|
|
|
|
|
218
|
my( $sigil, $variable_name, $package); |
485
|
133
|
100
|
|
|
|
935
|
if ( $line =~ /$VERS_REGEXP/o ) { |
486
|
114
|
100
|
|
|
|
530
|
( $sigil, $variable_name, $package) = $2 ? ( $1, $2, $3 ) : ( $4, $5, $6 ); |
487
|
114
|
100
|
|
|
|
262
|
if ( $package ) { |
488
|
20
|
100
|
|
|
|
58
|
$package = ($package eq '::') ? 'main' : $package; |
489
|
20
|
|
|
|
|
85
|
$package =~ s/::$//; |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
133
|
|
|
|
|
449
|
return ( $sigil, $variable_name, $package ); |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
# Look for a UTF-8/UTF-16BE/UTF-16LE BOM at the beginning of the stream. |
497
|
|
|
|
|
|
|
# If there's one, then skip it and set the :encoding layer appropriately. |
498
|
|
|
|
|
|
|
sub _handle_bom { |
499
|
105
|
|
|
107
|
|
284
|
my ($self, $fh, $filename) = @_; |
500
|
|
|
|
|
|
|
|
501
|
105
|
|
|
|
|
267
|
my $pos = tell $fh; |
502
|
105
|
50
|
|
|
|
218
|
return unless defined $pos; |
503
|
|
|
|
|
|
|
|
504
|
105
|
|
|
|
|
181
|
my $buf = ' ' x 2; |
505
|
105
|
|
|
|
|
1237
|
my $count = read $fh, $buf, length $buf; |
506
|
105
|
50
|
33
|
|
|
569
|
return unless defined $count and $count >= 2; |
507
|
|
|
|
|
|
|
|
508
|
105
|
|
|
|
|
156
|
my $encoding; |
509
|
105
|
100
|
|
|
|
389
|
if ( $buf eq "\x{FE}\x{FF}" ) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
510
|
1
|
|
|
|
|
2
|
$encoding = 'UTF-16BE'; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
elsif ( $buf eq "\x{FF}\x{FE}" ) { |
513
|
1
|
|
|
|
|
2
|
$encoding = 'UTF-16LE'; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
elsif ( $buf eq "\x{EF}\x{BB}" ) { |
516
|
1
|
|
|
|
|
3
|
$buf = ' '; |
517
|
1
|
|
|
|
|
3
|
$count = read $fh, $buf, length $buf; |
518
|
1
|
50
|
33
|
|
|
9
|
if ( defined $count and $count >= 1 and $buf eq "\x{BF}" ) { |
|
|
|
33
|
|
|
|
|
519
|
1
|
|
|
|
|
3
|
$encoding = 'UTF-8'; |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
|
523
|
105
|
100
|
|
|
|
222
|
if ( defined $encoding ) { |
524
|
3
|
50
|
|
|
|
15
|
if ( "$]" >= 5.008 ) { |
525
|
3
|
|
|
2
|
|
51
|
binmode( $fh, ":encoding($encoding)" ); |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
6
|
|
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
else { |
529
|
102
|
50
|
|
|
|
1098
|
seek $fh, $pos, SEEK_SET |
530
|
|
|
|
|
|
|
or croak( sprintf "Can't reset position to the top of '$filename'" ); |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
105
|
|
|
|
|
15512
|
return $encoding; |
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
sub _parse_fh { |
537
|
109
|
|
|
111
|
|
275
|
my ($self, $fh) = @_; |
538
|
|
|
|
|
|
|
|
539
|
109
|
|
|
|
|
221
|
my( $in_pod, $seen_end, $need_vers ) = ( 0, 0, 0 ); |
540
|
109
|
|
|
|
|
168
|
my( @packages, %vers, %pod, @pod ); |
541
|
109
|
|
|
|
|
179
|
my $package = 'main'; |
542
|
109
|
|
|
|
|
150
|
my $pod_sect = ''; |
543
|
109
|
|
|
|
|
171
|
my $pod_data = ''; |
544
|
109
|
|
|
|
|
169
|
my $in_end = 0; |
545
|
|
|
|
|
|
|
|
546
|
109
|
|
|
|
|
1015
|
while (defined( my $line = <$fh> )) { |
547
|
1651
|
|
|
|
|
3059
|
my $line_num = $.; |
548
|
|
|
|
|
|
|
|
549
|
1651
|
|
|
|
|
2531
|
chomp( $line ); |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
# From toke.c : any line that begins by "=X", where X is an alphabetic |
552
|
|
|
|
|
|
|
# character, introduces a POD segment. |
553
|
1651
|
|
|
|
|
2171
|
my $is_cut; |
554
|
1651
|
100
|
|
|
|
3131
|
if ( $line =~ /^=([a-zA-Z].*)/ ) { |
555
|
89
|
|
|
|
|
177
|
my $cmd = $1; |
556
|
|
|
|
|
|
|
# Then it goes back to Perl code for "=cutX" where X is a non-alphabetic |
557
|
|
|
|
|
|
|
# character (which includes the newline, but here we chomped it away). |
558
|
89
|
|
|
|
|
172
|
$is_cut = $cmd =~ /^cut(?:[^a-zA-Z]|$)/; |
559
|
89
|
|
|
|
|
139
|
$in_pod = !$is_cut; |
560
|
|
|
|
|
|
|
} |
561
|
|
|
|
|
|
|
|
562
|
1651
|
100
|
|
|
|
3124
|
if ( $in_pod ) { |
|
|
100
|
|
|
|
|
|
563
|
|
|
|
|
|
|
|
564
|
430
|
100
|
|
|
|
915
|
if ( $line =~ /^=head[1-4]\s+(.+)\s*$/ ) { |
|
|
100
|
|
|
|
|
|
565
|
42
|
|
|
|
|
99
|
push( @pod, $1 ); |
566
|
42
|
100
|
100
|
|
|
106
|
if ( $self->{collect_pod} && length( $pod_data ) ) { |
567
|
1
|
|
|
|
|
4
|
$pod{$pod_sect} = $pod_data; |
568
|
1
|
|
|
|
|
33
|
$pod_data = ''; |
569
|
|
|
|
|
|
|
} |
570
|
42
|
|
|
|
|
82
|
$pod_sect = $1; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
elsif ( $self->{collect_pod} ) { |
573
|
12
|
|
|
|
|
76
|
$pod_data .= "$line\n"; |
574
|
|
|
|
|
|
|
} |
575
|
430
|
|
|
|
|
1227
|
next; |
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
elsif ( $is_cut ) { |
578
|
9
|
100
|
66
|
|
|
36
|
if ( $self->{collect_pod} && length( $pod_data ) ) { |
579
|
1
|
|
|
|
|
6
|
$pod{$pod_sect} = $pod_data; |
580
|
1
|
|
|
|
|
2
|
$pod_data = ''; |
581
|
|
|
|
|
|
|
} |
582
|
9
|
|
|
|
|
17
|
$pod_sect = ''; |
583
|
9
|
|
|
|
|
95
|
next; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# Skip after __END__ |
587
|
1212
|
100
|
|
|
|
1931
|
next if $in_end; |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
# Skip comments in code |
590
|
1210
|
100
|
|
|
|
2722
|
next if $line =~ /^\s*#/; |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
# Would be nice if we could also check $in_string or something too |
593
|
1112
|
100
|
|
|
|
2217
|
if ($line eq '__END__') { |
594
|
2
|
|
|
|
|
7
|
$in_end++; |
595
|
2
|
|
|
|
|
9
|
next; |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
1110
|
100
|
|
|
|
2056
|
last if $line eq '__DATA__'; |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
# parse $line to see if it's a $VERSION declaration |
601
|
1109
|
100
|
|
|
|
3168
|
my( $version_sigil, $version_fullname, $version_package ) = |
602
|
|
|
|
|
|
|
index($line, 'VERSION') >= 1 |
603
|
|
|
|
|
|
|
? $self->_parse_version_expression( $line ) |
604
|
|
|
|
|
|
|
: (); |
605
|
|
|
|
|
|
|
|
606
|
1109
|
100
|
100
|
|
|
9095
|
if ( $line =~ /$PKG_REGEXP/o ) { |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
607
|
134
|
|
|
|
|
385
|
$package = $1; |
608
|
134
|
|
|
|
|
245
|
my $version = $2; |
609
|
134
|
100
|
|
|
|
503
|
push( @packages, $package ) unless grep( $package eq $_, @packages ); |
610
|
134
|
100
|
|
|
|
314
|
$need_vers = defined $version ? 0 : 1; |
611
|
|
|
|
|
|
|
|
612
|
134
|
100
|
100
|
|
|
956
|
if ( not exists $vers{$package} and defined $version ){ |
613
|
|
|
|
|
|
|
# Upgrade to a version object. |
614
|
6
|
|
|
|
|
13
|
my $dwim_version = eval { _dwim_version($version) }; |
|
6
|
|
|
|
|
18
|
|
615
|
6
|
50
|
|
|
|
17
|
croak "Version '$version' from $self->{filename} does not appear to be valid:\n$line\n\nThe fatal error was: $@\n" |
616
|
|
|
|
|
|
|
unless defined $dwim_version; # "0" is OK! |
617
|
6
|
|
|
|
|
55
|
$vers{$package} = $dwim_version; |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
} |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
# VERSION defined with full package spec, i.e. $Module::VERSION |
622
|
|
|
|
|
|
|
elsif ( $version_fullname && $version_package ) { |
623
|
|
|
|
|
|
|
# we do NOT save this package in found @packages |
624
|
20
|
100
|
|
|
|
66
|
$need_vers = 0 if $version_package eq $package; |
625
|
|
|
|
|
|
|
|
626
|
20
|
100
|
66
|
|
|
140
|
unless ( defined $vers{$version_package} && length $vers{$version_package} ) { |
627
|
18
|
|
|
|
|
49
|
$vers{$version_package} = $self->_evaluate_version_line( $version_sigil, $version_fullname, $line ); |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
} |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
# first non-comment line in undeclared package main is VERSION |
632
|
|
|
|
|
|
|
elsif ( $package eq 'main' && $version_fullname && !exists($vers{main}) ) { |
633
|
8
|
|
|
|
|
15
|
$need_vers = 0; |
634
|
8
|
|
|
|
|
24
|
my $v = $self->_evaluate_version_line( $version_sigil, $version_fullname, $line ); |
635
|
8
|
|
|
|
|
22
|
$vers{$package} = $v; |
636
|
8
|
|
|
|
|
90
|
push( @packages, 'main' ); |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
# first non-comment line in undeclared package defines package main |
640
|
|
|
|
|
|
|
elsif ( $package eq 'main' && !exists($vers{main}) && $line =~ /\w/ ) { |
641
|
8
|
|
|
|
|
23
|
$need_vers = 1; |
642
|
8
|
|
|
|
|
21
|
$vers{main} = ''; |
643
|
8
|
|
|
|
|
78
|
push( @packages, 'main' ); |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
# only keep if this is the first $VERSION seen |
647
|
|
|
|
|
|
|
elsif ( $version_fullname && $need_vers ) { |
648
|
83
|
|
|
|
|
133
|
$need_vers = 0; |
649
|
83
|
|
|
|
|
195
|
my $v = $self->_evaluate_version_line( $version_sigil, $version_fullname, $line ); |
650
|
|
|
|
|
|
|
|
651
|
83
|
50
|
66
|
|
|
286
|
unless ( defined $vers{$package} && length $vers{$package} ) { |
652
|
83
|
|
|
|
|
712
|
$vers{$package} = $v; |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
} |
655
|
|
|
|
|
|
|
} # end loop over each line |
656
|
|
|
|
|
|
|
|
657
|
109
|
100
|
100
|
|
|
445
|
if ( $self->{collect_pod} && length($pod_data) ) { |
658
|
1
|
|
|
|
|
3
|
$pod{$pod_sect} = $pod_data; |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
|
661
|
109
|
|
|
|
|
350
|
$self->{versions} = \%vers; |
662
|
109
|
|
|
|
|
248
|
$self->{packages} = \@packages; |
663
|
109
|
|
|
|
|
191
|
$self->{pod} = \%pod; |
664
|
109
|
|
|
|
|
342
|
$self->{pod_headings} = \@pod; |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
sub __uniq (@) |
668
|
|
|
|
|
|
|
{ |
669
|
109
|
|
|
111
|
|
188
|
my (%seen, $key); |
670
|
109
|
|
|
|
|
614
|
grep !$seen{ $key = $_ }++, @_; |
671
|
|
|
|
|
|
|
} |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
{ |
674
|
|
|
|
|
|
|
my $pn = 0; |
675
|
|
|
|
|
|
|
sub _evaluate_version_line { |
676
|
109
|
|
|
110
|
|
169
|
my $self = shift; |
677
|
109
|
|
|
|
|
255
|
my( $sigil, $variable_name, $line ) = @_; |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
# We compile into a local sub because 'use version' would cause |
680
|
|
|
|
|
|
|
# compiletime/runtime issues with local() |
681
|
109
|
|
|
|
|
181
|
$pn++; # everybody gets their own package |
682
|
109
|
|
|
|
|
516
|
my $eval = qq{ my \$dummy = q# Hide from _packages_inside() |
683
|
|
|
|
|
|
|
#; package Module::Metadata::_version::p${pn}; |
684
|
|
|
|
|
|
|
use version; |
685
|
|
|
|
|
|
|
sub { |
686
|
|
|
|
|
|
|
local $sigil$variable_name; |
687
|
|
|
|
|
|
|
$line; |
688
|
|
|
|
|
|
|
return \$$variable_name if defined \$$variable_name; |
689
|
|
|
|
|
|
|
return \$Module::Metadata::_version::p${pn}::$variable_name; |
690
|
|
|
|
|
|
|
}; |
691
|
|
|
|
|
|
|
}; |
692
|
|
|
|
|
|
|
|
693
|
109
|
50
|
|
|
|
557
|
$eval = $1 if $eval =~ m{^(.+)}s; |
694
|
|
|
|
|
|
|
|
695
|
109
|
|
|
|
|
384
|
local $^W; |
696
|
|
|
|
|
|
|
# Try to get the $VERSION |
697
|
109
|
|
|
|
|
244
|
my $vsub = __clean_eval($eval); |
698
|
|
|
|
|
|
|
# some modules say $VERSION $Foo::Bar::VERSION, but Foo::Bar isn't |
699
|
|
|
|
|
|
|
# installed, so we need to hunt in ./lib for it |
700
|
109
|
50
|
33
|
|
|
429
|
if ( $@ =~ /Can't locate/ && -d 'lib' ) { |
701
|
0
|
|
|
|
|
0
|
local @INC = ('lib',@INC); |
702
|
0
|
|
|
|
|
0
|
$vsub = __clean_eval($eval); |
703
|
|
|
|
|
|
|
} |
704
|
109
|
50
|
|
|
|
241
|
warn "Error evaling version line '$eval' in $self->{filename}: $@\n" |
705
|
|
|
|
|
|
|
if $@; |
706
|
|
|
|
|
|
|
|
707
|
109
|
50
|
|
|
|
310
|
(ref($vsub) eq 'CODE') or |
708
|
|
|
|
|
|
|
croak "failed to build version sub for $self->{filename}"; |
709
|
|
|
|
|
|
|
|
710
|
109
|
|
|
|
|
177
|
my $result = eval { $vsub->() }; |
|
109
|
|
|
|
|
2271
|
|
711
|
|
|
|
|
|
|
# FIXME: $eval is not the right thing to print here |
712
|
109
|
50
|
|
|
|
283
|
croak "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n" |
713
|
|
|
|
|
|
|
if $@; |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
# Upgrade it into a version object |
716
|
109
|
|
|
|
|
160
|
my $version = eval { _dwim_version($result) }; |
|
109
|
|
|
|
|
264
|
|
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
# FIXME: $eval is not the right thing to print here |
719
|
109
|
50
|
|
|
|
241
|
croak "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n" |
720
|
|
|
|
|
|
|
unless defined $version; # "0" is OK! |
721
|
|
|
|
|
|
|
|
722
|
109
|
|
|
|
|
1078
|
return $version; |
723
|
|
|
|
|
|
|
} |
724
|
|
|
|
|
|
|
} |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
# Try to DWIM when things fail the lax version test in obvious ways |
727
|
|
|
|
|
|
|
{ |
728
|
|
|
|
|
|
|
my @version_prep = ( |
729
|
|
|
|
|
|
|
# Best case, it just works |
730
|
|
|
|
|
|
|
sub { return shift }, |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
# If we still don't have a version, try stripping any |
733
|
|
|
|
|
|
|
# trailing junk that is prohibited by lax rules |
734
|
|
|
|
|
|
|
sub { |
735
|
|
|
|
|
|
|
my $v = shift; |
736
|
|
|
|
|
|
|
$v =~ s{([0-9])[a-z-].*$}{$1}i; # 1.23-alpha or 1.23b |
737
|
|
|
|
|
|
|
return $v; |
738
|
|
|
|
|
|
|
}, |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
# Activestate apparently creates custom versions like '1.23_45_01', which |
741
|
|
|
|
|
|
|
# cause version.pm to think it's an invalid alpha. So check for that |
742
|
|
|
|
|
|
|
# and strip them |
743
|
|
|
|
|
|
|
sub { |
744
|
|
|
|
|
|
|
my $v = shift; |
745
|
|
|
|
|
|
|
my $num_dots = () = $v =~ m{(\.)}g; |
746
|
|
|
|
|
|
|
my $num_unders = () = $v =~ m{(_)}g; |
747
|
|
|
|
|
|
|
my $leading_v = substr($v,0,1) eq 'v'; |
748
|
|
|
|
|
|
|
if ( ! $leading_v && $num_dots < 2 && $num_unders > 1 ) { |
749
|
|
|
|
|
|
|
$v =~ s{_}{}g; |
750
|
|
|
|
|
|
|
$num_unders = () = $v =~ m{(_)}g; |
751
|
|
|
|
|
|
|
} |
752
|
|
|
|
|
|
|
return $v; |
753
|
|
|
|
|
|
|
}, |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
# Worst case, try numifying it like we would have before version objects |
756
|
|
|
|
|
|
|
sub { |
757
|
|
|
|
|
|
|
my $v = shift; |
758
|
10
|
|
|
10
|
|
86
|
no warnings 'numeric'; |
|
10
|
|
|
|
|
45
|
|
|
10
|
|
|
|
|
4316
|
|
759
|
|
|
|
|
|
|
return 0 + $v; |
760
|
|
|
|
|
|
|
}, |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
); |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
sub _dwim_version { |
765
|
115
|
|
|
116
|
|
217
|
my ($result) = shift; |
766
|
|
|
|
|
|
|
|
767
|
115
|
100
|
|
|
|
250
|
return $result if ref($result) eq 'version'; |
768
|
|
|
|
|
|
|
|
769
|
110
|
|
|
|
|
183
|
my ($version, $error); |
770
|
110
|
|
|
|
|
240
|
for my $f (@version_prep) { |
771
|
122
|
|
|
|
|
285
|
$result = $f->($result); |
772
|
122
|
|
|
|
|
203
|
$version = eval { version->new($result) }; |
|
122
|
|
|
|
|
1010
|
|
773
|
122
|
100
|
66
|
|
|
341
|
$error ||= $@ if $@; # capture first failure |
774
|
122
|
100
|
|
|
|
302
|
last if defined $version; |
775
|
|
|
|
|
|
|
} |
776
|
|
|
|
|
|
|
|
777
|
110
|
50
|
|
|
|
226
|
croak $error unless defined $version; |
778
|
|
|
|
|
|
|
|
779
|
110
|
|
|
|
|
236
|
return $version; |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
############################################################ |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# accessors |
786
|
21
|
|
|
22
|
1
|
210
|
sub name { $_[0]->{module} } |
787
|
|
|
|
|
|
|
|
788
|
1
|
|
|
2
|
1
|
3
|
sub filename { $_[0]->{filename} } |
789
|
31
|
|
|
32
|
1
|
461
|
sub packages_inside { @{$_[0]->{packages}} } |
|
31
|
|
|
|
|
126
|
|
790
|
2
|
|
|
3
|
1
|
5
|
sub pod_inside { @{$_[0]->{pod_headings}} } |
|
2
|
|
|
|
|
12
|
|
791
|
4
|
|
|
5
|
1
|
1085
|
sub contains_pod { 0+@{$_[0]->{pod_headings}} } |
|
4
|
|
|
|
|
26
|
|
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
sub version { |
794
|
100
|
|
|
101
|
1
|
1073
|
my $self = shift; |
795
|
100
|
|
100
|
|
|
481
|
my $mod = shift || $self->{module}; |
796
|
100
|
|
|
|
|
148
|
my $vers; |
797
|
100
|
100
|
66
|
|
|
537
|
if ( defined( $mod ) && length( $mod ) && |
|
|
|
100
|
|
|
|
|
798
|
|
|
|
|
|
|
exists( $self->{versions}{$mod} ) ) { |
799
|
85
|
|
|
|
|
350
|
return $self->{versions}{$mod}; |
800
|
|
|
|
|
|
|
} |
801
|
|
|
|
|
|
|
else { |
802
|
15
|
|
|
|
|
49
|
return undef; |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
sub pod { |
807
|
4
|
|
|
5
|
1
|
689
|
my $self = shift; |
808
|
4
|
|
|
|
|
8
|
my $sect = shift; |
809
|
4
|
100
|
33
|
|
|
26
|
if ( defined( $sect ) && length( $sect ) && |
|
|
|
66
|
|
|
|
|
810
|
|
|
|
|
|
|
exists( $self->{pod}{$sect} ) ) { |
811
|
2
|
|
|
|
|
6
|
return $self->{pod}{$sect}; |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
else { |
814
|
2
|
|
|
|
|
10
|
return undef; |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
} |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
sub is_indexable { |
819
|
8
|
|
|
9
|
1
|
22
|
my ($self, $package) = @_; |
820
|
|
|
|
|
|
|
|
821
|
8
|
|
|
|
|
21
|
my @indexable_packages = grep $_ ne 'main', $self->packages_inside; |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
# check for specific package, if provided |
824
|
8
|
100
|
|
|
|
60
|
return !! grep $_ eq $package, @indexable_packages if $package; |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
# otherwise, check for any indexable packages at all |
827
|
2
|
|
|
|
|
12
|
return !! @indexable_packages; |
828
|
|
|
|
|
|
|
} |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
1; |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
__END__ |