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