File Coverage

blib/lib/Parse/PMFile.pm
Criterion Covered Total %
statement 310 474 65.4
branch 132 236 55.9
condition 53 146 36.3
subroutine 32 41 78.0
pod 2 2 100.0
total 529 899 58.8


line stmt bran cond sub pod time code
1             package Parse::PMFile;
2              
3 80     80   9247 sub __clean_eval { eval $_[0] } # needs to be here (RT#101273)
4              
5 48     48   2940557 use strict;
  48         555  
  48         1245  
6 48     48   203 use warnings;
  48         72  
  48         1191  
7 48     48   22042 use Safe;
  48         1610234  
  48         2312  
8 48     48   29105 use JSON::PP ();
  48         634616  
  48         1367  
9 48     48   21173 use Dumpvalue;
  48         201018  
  48         1463  
10 48     48   19052 use version ();
  48         85177  
  48         1333  
11 48     48   352 use File::Spec ();
  48         84  
  48         47513  
12              
13             our $VERSION = '0.42';
14             our $VERBOSE = 0;
15             our $ALLOW_DEV_VERSION = 0;
16             our $FORK = 0;
17             our $UNSAFE = $] < 5.010000 ? 1 : 0;
18              
19             sub new {
20 128     128 1 365749 my ($class, $meta, $opts) = @_;
21 128 100       306 bless {%{ $opts || {} }, META_CONTENT => $meta}, $class;
  128         1531  
22             }
23              
24             # from PAUSE::pmfile::examine_fio
25             sub parse {
26 128     128 1 853 my ($self, $pmfile) = @_;
27              
28 128         377 $pmfile =~ s|\\|/|g;
29              
30 128         2351 my($filemtime) = (stat $pmfile)[9];
31 128         712 $self->{MTIME} = $filemtime;
32 128         368 $self->{PMFILE} = $pmfile;
33              
34 128 100       422 unless ($self->_version_from_meta_ok) {
35 122         192 my $version;
36 122 50       208 unless (eval { $version = $self->_parse_version; 1 }) {
  122         325  
  97         406  
37 0         0 $self->_verbose(1, "error with version in $pmfile: $@");
38 0         0 return;
39             }
40              
41 97         510 $self->{VERSION} = $version;
42 97 50 66     1437 if ($self->{VERSION} =~ /^\{.*\}$/) {
    100 100        
43             # JSON error message
44             } elsif ($self->{VERSION} =~ /[_\s]/ && !$self->{ALLOW_DEV_VERSION} && !$ALLOW_DEV_VERSION){ # ignore developer releases and "You suck!"
45 5         36 return;
46             }
47             }
48              
49 98         931 my($ppp) = $self->_packages_per_pmfile;
50 98         899 my @keys_ppp = $self->_filter_ppps(sort keys %$ppp);
51 98         548 $self->_verbose(1,"Will check keys_ppp[@keys_ppp]\n");
52              
53             #
54             # Immediately after each package (pmfile) examined contact
55             # the database
56             #
57              
58 98         678 my ($package, %errors);
59 98         0 my %checked_in;
60 98         376 DBPACK: foreach $package (@keys_ppp) {
61             # this part is taken from PAUSE::package::examine_pkg
62             # and PAUSE::package::_pkg_name_insane
63 92 50 33     3194 if ($package !~ /^\w[\w\:\']*\w?\z/
      33        
      33        
      33        
      33        
64             || $package !~ /\w\z/
65             || $package =~ /:/ && $package !~ /::/
66             || $package =~ /\w:\w/
67             || $package =~ /:::/
68             ){
69 0         0 $self->_verbose(1,"Package[$package] did not pass the ultimate sanity check");
70 0         0 delete $ppp->{$package};
71 0         0 next;
72             }
73              
74 92 0 33     325 if ($self->{USERID} && $self->{PERMISSIONS} && !$self->_perm_check($package)) {
      0        
75 0         0 delete $ppp->{$package};
76 0         0 next;
77             }
78              
79             # Check that package name matches case of file name
80             {
81 92         129 my (undef, $module) = split m{/lib/}, $self->{PMFILE}, 2;
  92         416  
82 92 100       305 if ($module) {
83 6         33 $module =~ s{\.pm\z}{};
84 6         32 $module =~ s{/}{::}g;
85              
86 6 50 33     53 if (lc $module eq lc $package && $module ne $package) {
87             # warn "/// $self->{PMFILE} vs. $module vs. $package\n";
88             $errors{$package} = {
89             indexing_warning => "Capitalization of package ($package) does not match filename!",
90             infile => $self->{PMFILE},
91 0         0 };
92             }
93             }
94             }
95              
96 92         194 my $pp = $ppp->{$package};
97 92 50 66     695 if ($pp->{version} && $pp->{version} =~ /^\{.*\}$/) { # JSON parser error
98 0         0 my $err = JSON::PP::decode_json($pp->{version});
99 0 0       0 if ($err->{x_normalize}) {
    0          
100             $errors{$package} = {
101             normalize => $err->{version},
102             infile => $pp->{infile},
103 0         0 };
104 0         0 $pp->{version} = "undef";
105             } elsif ($err->{openerr}) {
106 0         0 $pp->{version} = "undef";
107 0         0 $self->_verbose(1,
108             qq{Parse::PMFile was not able to
109             read the file. It issued the following error: C< $err->{r} >},
110             );
111             $errors{$package} = {
112             open => $err->{r},
113             infile => $pp->{infile},
114 0         0 };
115             } else {
116 0         0 $pp->{version} = "undef";
117 0         0 $self->_verbose(1,
118             qq{Parse::PMFile was not able to
119             parse the following line in that file: C< $err->{line} >
120              
121             Note: the indexer is running in a Safe compartement and cannot
122             provide the full functionality of perl in the VERSION line. It
123             is trying hard, but sometime it fails. As a workaround, please
124             consider writing a META.yml that contains a 'provides'
125             attribute or contact the CPAN admins to investigate (yet
126             another) workaround against "Safe" limitations.)},
127              
128             );
129             $errors{$package} = {
130             parse_version => $err->{line},
131             infile => $err->{file},
132 0         0 };
133             }
134             }
135              
136             # Sanity checks
137              
138 92         290 for (
139             $package,
140             $pp->{version},
141             ) {
142 184 50 66     1481 if (!defined || /^\s*$/ || /\s/){ # for whatever reason I come here
      66        
143 4         8 delete $ppp->{$package};
144 4         8 next; # don't screw up 02packages
145             }
146             }
147 92 100       421 unless ($self->_version_ok($pp)) {
148             $errors{$package} = {
149             long_version => qq{Version string exceeds maximum allowed length of 16b: "$pp->{version}"},
150             infile => $pp->{infile},
151 3         24 };
152 3         9 next;
153             }
154 89         476 $checked_in{$package} = $ppp->{$package};
155             } # end foreach package
156              
157 98 100 66     994 return (wantarray && %errors) ? (\%checked_in, \%errors) : \%checked_in;
158             }
159              
160             sub _version_ok {
161 92     92   234 my ($self, $pp) = @_;
162 92 100 100     401 return if length($pp->{version} || 0) > 16;
163 89         254 return 1
164             }
165              
166             sub _perm_check {
167 0     0   0 my ($self, $package) = @_;
168 0         0 my $userid = $self->{USERID};
169 0         0 my $module = $self->{PERMISSIONS}->module_permissions($package);
170 0 0       0 return 1 if !$module; # not listed yet
171 0 0 0     0 return 1 if defined $module->m && $module->m eq $userid;
172 0 0 0     0 return 1 if defined $module->f && $module->f eq $userid;
173 0 0 0     0 return 1 if defined $module->c && grep {$_ eq $userid} @{$module->c};
  0         0  
  0         0  
174 0         0 return;
175             }
176              
177             # from PAUSE::pmfile;
178             sub _parse_version {
179 122     122   232 my $self = shift;
180              
181 48     48   367 use strict;
  48         94  
  48         12171  
182              
183 122         253 my $pmfile = $self->{PMFILE};
184 122         5257 my $tmpfile = File::Spec->catfile(File::Spec->tmpdir, "ParsePMFile$$" . rand(1000));
185              
186 122         329 my $pmcp = $pmfile;
187 122         887 for ($pmcp) {
188 122         368 s/([^\\](\\\\)*)@/$1\\@/g; # thanks to Raphael Manfredi for the
189             # solution to escape @s and \
190             }
191 122         176 my($v);
192             {
193              
194 122         231 package main; # seems necessary
195              
196             # XXX: do we need to fork as PAUSE does?
197             # or, is alarm() just fine?
198 122         155 my $pid;
199 122 100 66     732 if ($self->{FORK} || $FORK) {
200 61         128719 $pid = fork();
201 61 50       5085 die "Can't fork: $!" unless defined $pid;
202             }
203 122 100       2021 if ($pid) {
204 36         14081045 waitpid($pid, 0);
205 36 50       7599 if (open my $fh, '<', $tmpfile) {
206 36         4354 $v = <$fh>;
207             }
208             } else {
209             # XXX Limit Resources too
210              
211 86         3193 my($comp) = Safe->new;
212 86         130245 my $eval = qq{
213             local(\$^W) = 0;
214             Parse::PMFile::_parse_version_safely("$pmcp");
215             };
216 86         735 $comp->permit("entereval"); # for MBARBON/Module-Info-0.30.tar.gz
217 86         1097 $comp->share("*Parse::PMFile::_parse_version_safely");
218 86         8810 $comp->share("*version::new");
219 86         4184 $comp->share("*version::numify");
220 86         4318 $comp->share_from('main', ['*version::',
221             '*charstar::',
222             '*Exporter::',
223             '*DynaLoader::']);
224 86         109407 $comp->share_from('version', ['&qv']);
225 86         4195 $comp->permit(":base_math"); # atan2 (Acme-Pi)
226             # $comp->permit("require"); # no strict!
227 86         933 $comp->deny(qw/enteriter iter unstack goto/); # minimum protection against Acme::BadExample
228              
229 86 50 33     2376 version->import('qv') if $self->{UNSAFE} || $UNSAFE;
230             {
231 48     48   320 no strict;
  48         142  
  48         14138  
  86         480  
232 86 50 33     2210 $v = ($self->{UNSAFE} || $UNSAFE) ? eval $eval : $comp->reval($eval);
233             }
234 86 100       82404 if ($@){ # still in the child process, out of Safe::reval
235 21         68 my $err = $@;
236             # warn ">>>>>>>err[$err]<<<<<<<<";
237 21 50       127 if (ref $err) {
238 21 50       709 if ($err->{line} =~ /([\$*])([\w\:\']*)\bVERSION\b.*?\=(.*)/) {
239 21         115 local($^W) = 0;
240 21         119 my ($sigil, $vstr) = ($1, $3);
241 21 50       399 $self->_restore_overloaded_stuff(1) if $err->{line} =~ /use\s+version\b|version\->|qv\(/;
242 21 50 33     273 $v = ($self->{UNSAFE} || $UNSAFE) ? eval $vstr : $comp->reval($vstr);
243 21 50 33     18866 $v = $$v if $sigil eq '*' && ref $v;
244             }
245 21 50 33     978 if ($@ or !$v) {
246 0         0 $self->_verbose(1, sprintf("reval failed: err[%s] for eval[%s]",
247             JSON::PP::encode_json($err),
248             $eval,
249             ));
250 0         0 $v = JSON::PP::encode_json($err);
251             }
252             } else {
253 0         0 $v = JSON::PP::encode_json({ openerr => $err });
254             }
255             }
256 86 50       405 if (defined $v) {
257 48     48   346 no warnings;
  48         94  
  48         12532  
258 86 100       786 $v = $v->numify if ref($v) =~ /^version(::vpp)?$/;
259             } else {
260 0         0 $v = "";
261             }
262 86 100 66     1328 if ($self->{FORK} || $FORK) {
263 25         3032 open my $fh, '>:utf8', $tmpfile;
264 25         2843 print $fh $v;
265 25         3032 exit 0;
266             } else {
267 61         393 utf8::encode($v);
268             # undefine empty $v as if read from the tmpfile
269 61 50 33     589 $v = undef if defined $v && !length $v;
270 61         331 $comp->erase;
271 61         54732 $self->_restore_overloaded_stuff;
272             }
273             }
274             }
275 97 100 66     9400 unlink $tmpfile if ($self->{FORK} || $FORK) && -e $tmpfile;
      66        
276              
277 97         1072 return $self->_normalize_version($v);
278             }
279              
280             sub _restore_overloaded_stuff {
281 82     82   349 my ($self, $used_version_in_safe) = @_;
282 82 50 33     777 return if $self->{UNSAFE} || $UNSAFE;
283              
284 48     48   353 no strict 'refs';
  48         110  
  48         1489  
285 48     48   275 no warnings 'redefine';
  48         618  
  48         43647  
286              
287             # version XS in CPAN
288 82         196 my $restored;
289 82 50       358 if ($INC{'version/vxs.pm'}) {
290 0         0 *{'version::(""'} = \&version::vxs::stringify;
  0         0  
291 0         0 *{'version::(0+'} = \&version::vxs::numify;
  0         0  
292 0         0 *{'version::(cmp'} = \&version::vxs::VCMP;
  0         0  
293 0         0 *{'version::(<=>'} = \&version::vxs::VCMP;
  0         0  
294 0         0 *{'version::(bool'} = \&version::vxs::boolean;
  0         0  
295 0         0 $restored = 1;
296             }
297             # version PP in CPAN
298 82 50       266 if ($INC{'version/vpp.pm'}) {
299             {
300 0         0 package # hide from PAUSE
301             charstar;
302 0         0 overload->import;
303             }
304 0 0       0 if (!$used_version_in_safe) {
305             package # hide from PAUSE
306             version::vpp;
307 0         0 overload->import;
308             }
309 0 0       0 unless ($restored) {
310 0         0 *{'version::(""'} = \&version::vpp::stringify;
  0         0  
311 0         0 *{'version::(0+'} = \&version::vpp::numify;
  0         0  
312 0         0 *{'version::(cmp'} = \&version::vpp::vcmp;
  0         0  
313 0         0 *{'version::(<=>'} = \&version::vpp::vcmp;
  0         0  
314 0         0 *{'version::(bool'} = \&version::vpp::vbool;
  0         0  
315             }
316 0         0 *{'version::vpp::(""'} = \&version::vpp::stringify;
  0         0  
317 0         0 *{'version::vpp::(0+'} = \&version::vpp::numify;
  0         0  
318 0         0 *{'version::vpp::(cmp'} = \&version::vpp::vcmp;
  0         0  
319 0         0 *{'version::vpp::(<=>'} = \&version::vpp::vcmp;
  0         0  
320 0         0 *{'version::vpp::(bool'} = \&version::vpp::vbool;
  0         0  
321 0         0 *{'charstar::(""'} = \&charstar::thischar;
  0         0  
322 0         0 *{'charstar::(0+'} = \&charstar::thischar;
  0         0  
323 0         0 *{'charstar::(++'} = \&charstar::increment;
  0         0  
324 0         0 *{'charstar::(--'} = \&charstar::decrement;
  0         0  
325 0         0 *{'charstar::(+'} = \&charstar::plus;
  0         0  
326 0         0 *{'charstar::(-'} = \&charstar::minus;
  0         0  
327 0         0 *{'charstar::(*'} = \&charstar::multiply;
  0         0  
328 0         0 *{'charstar::(cmp'} = \&charstar::cmp;
  0         0  
329 0         0 *{'charstar::(<=>'} = \&charstar::spaceship;
  0         0  
330 0         0 *{'charstar::(bool'} = \&charstar::thischar;
  0         0  
331 0         0 *{'charstar::(='} = \&charstar::clone;
  0         0  
332 0         0 $restored = 1;
333             }
334             # version in core
335 82 50       351 if (!$restored) {
336 82         168 *{'version::(""'} = \&version::stringify;
  82         418  
337 82         176 *{'version::(0+'} = \&version::numify;
  82         332  
338 82         211 *{'version::(cmp'} = \&version::vcmp;
  82         281  
339 82         255 *{'version::(<=>'} = \&version::vcmp;
  82         189  
340 82         136 *{'version::(bool'} = \&version::boolean;
  82         420  
341             }
342             }
343              
344             # from PAUSE::pmfile;
345             sub _packages_per_pmfile {
346 98     98   243 my $self = shift;
347              
348 98         233 my $ppp = {};
349 98         299 my $pmfile = $self->{PMFILE};
350 98         239 my $filemtime = $self->{MTIME};
351 98         214 my $version = $self->{VERSION};
352              
353 98 50       4122 open my $fh, "<", "$pmfile" or return $ppp;
354              
355 98         1022 local $/ = "\n";
356 98         234 my $inpod = 0;
357              
358 98         2527 PLINE: while (<$fh>) {
359 5248         6187 chomp;
360 5248         7092 my($pline) = $_;
361 5248 50       10009 $inpod = $pline =~ /^=(?!cut)/ ? 1 :
    50          
362             $pline =~ /^=cut/ ? 0 : $inpod;
363 5248 50       7008 next if $inpod;
364 5248 50       8228 next if substr($pline,0,4) eq "=cut";
365              
366 5248         7998 $pline =~ s/\#.*//;
367 5248 100       11991 next if $pline =~ /^\s*$/;
368 4142 100 66     7206 if ($pline =~ /^__(?:END|DATA)__\b/
369             and $pmfile !~ /\.PL$/ # PL files may well have code after __DATA__
370             ){
371 9         29 last PLINE;
372             }
373              
374 4133         4843 my $pkg;
375             my $strict_version;
376              
377 4133 100       17330 if (
378             $pline =~ m{
379             # (.*) # takes too much time if $pline is long
380             #(?
381             ^[\s\{;]*
382             \bpackage\s+
383             ([\w\:\']+)
384             \s*
385             (?: $ | [\}\;] | \{ | \s+($version::STRICT) )
386             }x) {
387 101         464 $pkg = $1;
388 101         243 $strict_version = $2;
389 101 50       325 if ($pkg eq "DB"){
390             # XXX if pumpkin and perl make him comaintainer! I
391             # think I always made the pumpkins comaint on DB
392             # without further ado (?)
393 0         0 next PLINE;
394             }
395             }
396              
397 4133 100       12336 if ($pkg) {
398             # Found something
399              
400             # from package
401 101         266 $pkg =~ s/\'/::/g;
402 101 50       527 next PLINE unless $pkg =~ /^[A-Za-z]/;
403 101 50       527 next PLINE unless $pkg =~ /\w$/;
404 101 100       304 next PLINE if $pkg eq "main";
405             # Perl::Critic::Policy::TestingAndDebugging::ProhibitShebangWarningsArg
406             # database for modid in mods, package in packages, package in perms
407             # alter table mods modify modid varchar(128) binary NOT NULL default '';
408             # alter table packages modify package varchar(128) binary NOT NULL default '';
409 95 50       256 next PLINE if length($pkg) > 128;
410             #restriction
411 95         547 $ppp->{$pkg}{parsed}++;
412 95         367 $ppp->{$pkg}{infile} = $pmfile;
413 95 50       414 if ($self->_simile($pmfile,$pkg)) {
414 95         249 $ppp->{$pkg}{simile} = $pmfile;
415 95 100       404 if ($self->_version_from_meta_ok) {
416 6         9 my $provides = $self->{META_CONTENT}{provides};
417 6 50       25 if (exists $provides->{$pkg}) {
418 6 50       15 if (defined $provides->{$pkg}{version}) {
419 6         12 my $v = $provides->{$pkg}{version};
420 6 100 33     67 if ($v =~ /[_\s]/ && !$self->{ALLOW_DEV_VERSION} && !$ALLOW_DEV_VERSION){ # ignore developer releases and "You suck!"
      66        
421 4         164 next PLINE;
422             }
423              
424 2 50       16 unless (eval { $version = $self->_normalize_version($v); 1 }) {
  2         6  
  2         19  
425 0         0 $self->_verbose(1, "error with version in $pmfile: $@");
426 0         0 next;
427              
428             }
429 2         11 $ppp->{$pkg}{version} = $version;
430             } else {
431 0         0 $ppp->{$pkg}{version} = "undef";
432             }
433             }
434             } else {
435 89 100       247 if (defined $strict_version){
436 3         12 $ppp->{$pkg}{version} = $strict_version ;
437             } else {
438 86 50       342 $ppp->{$pkg}{version} = defined $version ? $version : "";
439             }
440 48     48   326 no warnings;
  48         75  
  48         9540  
441 89 100       280 if ($version eq 'undef') {
442 3 50       11 $ppp->{$pkg}{version} = $version unless defined $ppp->{$pkg}{version};
443             } else {
444             $ppp->{$pkg}{version} =
445             $version
446             if $version
447             > $ppp->{$pkg}{version} ||
448             $version
449 86 50 33     776 gt $ppp->{$pkg}{version};
450             }
451             }
452             } else { # not simile
453             #### it comes later, it would be nonsense
454             #### to set to "undef". MM_Unix gives us
455             #### the best we can reasonably consider
456             $ppp->{$pkg}{version} =
457             $version
458             unless defined $ppp->{$pkg}{version} &&
459 0 0 0     0 length($ppp->{$pkg}{version});
460             }
461 91         471 $ppp->{$pkg}{filemtime} = $filemtime;
462             } else {
463             # $self->_verbose(2,"no pkg found");
464             }
465             }
466              
467 98         963 close $fh;
468 98         3222 $ppp;
469             }
470              
471             # from PAUSE::pmfile;
472             {
473 48     48   378 no strict;
  48         87  
  48         19544  
474             sub _parse_version_safely {
475 86     86   45432 my($parsefile) = @_;
476 86         301 my $result;
477 86         293 local *FH;
478 86         864 local $/ = "\n";
479 86 50       5403 open(FH,$parsefile) or die "Could not open '$parsefile': $!";
480 86         612 my $inpod = 0;
481 86         2667 while () {
482 257 50       1208 $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod;
    50          
483 257 50 33     1458 next if $inpod || /^\s*#/;
484 257 100       681 last if /^__(?:END|DATA)__\b/; # fails on quoted __END__ but this is rare -> __END__ in the middle of a line is rarer
485 254         578 chop;
486              
487 254 100       1264 if (my ($ver) = /package \s+ \S+ \s+ (\S+) \s* [;{]/x) {
488             # XXX: should handle this better if version is bogus -- rjbs,
489             # 2014-03-16
490 6 100       68 return $ver if version::is_lax($ver);
491             }
492              
493             # next unless /\$(([\w\:\']*)\bVERSION)\b.*\=/;
494 251 100       1634 next unless /(?<=])\=(?![=>])/;
495 80         301 my $current_parsed_line = $_;
496 80         1012 my $eval = qq{
497             package #
498             ExtUtils::MakeMaker::_version;
499              
500             local $1$2;
501             \$$2=undef; do {
502             $_
503             }; \$$2
504             };
505 80         668 local $^W = 0;
506 80     0   1074 local $SIG{__WARN__} = sub {};
507 80         699 $result = __clean_eval($eval);
508             # warn "current_parsed_line[$current_parsed_line]\$\@[$@]";
509 80 100 66     824 if ($@ or !defined $result){
510 21         1148 die +{
511             eval => $eval,
512             line => $current_parsed_line,
513             file => $parsefile,
514             err => $@,
515             };
516             }
517 59         374 last;
518             } #;
519 62         734 close FH;
520              
521 62 100       265 $result = "undef" unless defined $result;
522 62 100       225 if ((ref $result) =~ /^version(?:::vpp)?\b/) {
523 48     48   313 no warnings;
  48         239  
  48         34138  
524 6         46 $result = $result->numify;
525             }
526 62         2754 return $result;
527             }
528             }
529              
530             # from PAUSE::pmfile;
531             sub _filter_ppps {
532 98     98   392 my($self,@ppps) = @_;
533 98         228 my @res;
534              
535             # very similar code is in PAUSE::dist::filter_pms
536 98         374 MANI: for my $ppp ( @ppps ) {
537 95 100       333 if ($self->{META_CONTENT}){
538             my $no_index = $self->{META_CONTENT}{no_index}
539 9   66     61 || $self->{META_CONTENT}{private}; # backward compat
540 9 100       31 if (ref($no_index) eq 'HASH') {
541 3         62 my %map = (
542             package => qr{\z},
543             namespace => qr{::},
544             );
545 3         10 for my $k (qw(package namespace)) {
546 3 50       15 next unless my $v = $no_index->{$k};
547 3         7 my $rest = $map{$k};
548 3 50       9 if (ref $v eq "ARRAY") {
549 3         8 for my $ve (@$v) {
550 3         7 $ve =~ s|::$||;
551 3 50       40 if ($ppp =~ /^$ve$rest/){
552 3         19 $self->_verbose(1,"Skipping ppp[$ppp] due to ve[$ve]");
553 3         16 next MANI;
554             } else {
555 0         0 $self->_verbose(1,"NOT skipping ppp[$ppp] due to ve[$ve]");
556             }
557             }
558             } else {
559 0         0 $v =~ s|::$||;
560 0 0       0 if ($ppp =~ /^$v$rest/){
561 0         0 $self->_verbose(1,"Skipping ppp[$ppp] due to v[$v]");
562 0         0 next MANI;
563             } else {
564 0         0 $self->_verbose(1,"NOT skipping ppp[$ppp] due to v[$v]");
565             }
566             }
567             }
568             } else {
569 6         14 $self->_verbose(1,"No keyword 'no_index' or 'private' in META_CONTENT");
570             }
571             } else {
572             # $self->_verbose(1,"no META_CONTENT"); # too noisy
573             }
574 92         315 push @res, $ppp;
575             }
576 98         791 $self->_verbose(1,"Result of filter_ppps: res[@res]");
577 98         273 @res;
578             }
579              
580             # from PAUSE::pmfile;
581             sub _simile {
582 95     95   353 my($self,$file,$package) = @_;
583             # MakeMaker gives them the chance to have the file Simple.pm in
584             # this directory but have the package HTML::Simple in it.
585             # Afaik, they wouldn't be able to do so with deeper nested packages
586 95         629 $file =~ s|.*/||;
587 95         577 $file =~ s|\.pm(?:\.PL)?||;
588 95         983 my $ret = $package =~ m/\b\Q$file\E$/;
589 95   50     285 $ret ||= 0;
590 95 50       319 unless ($ret) {
591             # Apache::mod_perl_guide stuffs it into Version.pm
592 0 0       0 $ret = 1 if lc $file eq 'version';
593             }
594 95         603 $self->_verbose(1,"Result of simile(): file[$file] package[$package] ret[$ret]\n");
595 95         281 $ret;
596             }
597              
598             # from PAUSE::pmfile
599             sub _normalize_version {
600 99     99   808 my($self,$v) = @_;
601 99 50       438 $v = "undef" unless defined $v;
602 99         1805 my $dv = Dumpvalue->new;
603 99         6593 my $sdv = $dv->stringify($v,1); # second argument prevents ticks
604 99         4746 $self->_verbose(1,"Result of normalize_version: sdv[$sdv]\n");
605              
606 99 100       454 return $v if $v eq "undef";
607 96 50       720 return $v if $v =~ /^\{.*\}$/; # JSON object
608 96         475 $v =~ s/^\s+//;
609 96         581 $v =~ s/\s+\z//;
610 96 100       1099 if ($v =~ /_/) {
611             # XXX should pass something like EDEVELOPERRELEASE up e.g.
612             # SIXTEASE/XML-Entities-0.0306.tar.gz had nothing but one
613             # such modules and the mesage was not helpful that "nothing
614             # was found".
615 10         115 return $v ;
616             }
617 86 50       853 if (!version::is_lax($v)) {
618 0         0 return JSON::PP::encode_json({ x_normalize => 'version::is_lax failed', version => $v });
619             }
620             # may warn "Integer overflow"
621 48     48   327 my $vv = eval { no warnings; version->new($v)->numify };
  48         88  
  48         4358  
  86         5050  
  86         2276  
622 86 50       453 if ($@) {
623             # warn "$v: $@";
624 0         0 return JSON::PP::encode_json({ x_normalize => $@, version => $v });
625             # return "undef";
626             }
627 86 100       412 if ($vv eq $v) {
628             # the boring 3.14
629             } else {
630 59         300 my $forced = $self->_force_numeric($v);
631 59 50       342 if ($forced eq $vv) {
    50          
632             } elsif ($forced =~ /^v(.+)/) {
633             # rare case where a v1.0.23 slipped in (JANL/w3mir-1.0.10.tar.gz)
634 48     48   283 no warnings;
  48         86  
  48         59301  
635 0         0 $vv = version->new($1)->numify;
636             } else {
637             # warn "Unequal forced[$forced] and vv[$vv]";
638 59 50       336 if ($forced == $vv) {
639             # the trailing zeroes would cause unnecessary havoc
640 59         108 $vv = $forced;
641             }
642             }
643             }
644 86         943 return $vv;
645             }
646              
647             # from PAUSE::pmfile;
648             sub _force_numeric {
649 59     59   204 my($self,$v) = @_;
650 59         366 $v = $self->_readable($v);
651              
652 59 50 33     1062 if (
      33        
653             $v =~
654             /^(\+?)(\d*)(\.(\d*))?/ &&
655             # "$2$4" ne ''
656             (
657             defined $2 && length $2
658             ||
659             defined $4 && length $4
660             )
661             ) {
662 59 50       342 my $two = defined $2 ? $2 : "";
663 59 50       304 my $three = defined $3 ? $3 : "";
664 59         141 $v = "$two$three";
665             }
666             # no else branch! We simply say, everything else is a string.
667 59         146 $v;
668             }
669              
670             # from PAUSE::dist
671             sub _version_from_meta_ok {
672 223     223   487 my($self) = @_;
673 223 100       869 return $self->{VERSION_FROM_META_OK} if exists $self->{VERSION_FROM_META_OK};
674 128         251 my $c = $self->{META_CONTENT};
675              
676             # If there's no provides hash, we can't get our module versions from the
677             # provides hash! -- rjbs, 2012-03-31
678 128 100       644 return($self->{VERSION_FROM_META_OK} = 0) unless $c->{provides};
679              
680             # Some versions of Module::Build geneated an empty provides hash. If we're
681             # *not* looking at a Module::Build-generated metafile, then it's okay.
682 6 50       20 my ($mb_v) = (defined $c->{generated_by} ? $c->{generated_by} : '') =~ /Module::Build version ([\d\.]+)/;
683 6 50       35 return($self->{VERSION_FROM_META_OK} = 1) unless $mb_v;
684              
685             # ??? I don't know why this is here.
686 0 0       0 return($self->{VERSION_FROM_META_OK} = 1) if $mb_v eq '0.250.0';
687              
688 0 0 0     0 if ($mb_v >= 0.19 && $mb_v < 0.26 && ! keys %{$c->{provides}}) {
  0   0     0  
689             # RSAVAGE/Javascript-SHA1-1.01.tgz had an empty provides hash. Ron
690             # did not find the reason why this happened, but let's not go
691             # overboard, 0.26 seems a good threshold from the statistics: there
692             # are not many empty provides hashes from 0.26 up.
693 0         0 return($self->{VERSION_FROM_META_OK} = 0);
694             }
695              
696             # We're not in the suspect range of M::B versions. It's good to go.
697 0         0 return($self->{VERSION_FROM_META_OK} = 1);
698             }
699              
700             sub _verbose {
701 399     399   1099 my($self,$level,@what) = @_;
702 399 50 33     3047 warn @what if $level <= ((ref $self && $self->{VERBOSE}) || $VERBOSE);
703             }
704              
705             # all of the following methods are stripped from CPAN::Version
706             # (as of version 5.5001, bundled in CPAN 2.03), and slightly
707             # modified (ie. made private, as well as CPAN->debug(...) are
708             # replaced with $self->_verbose(9, ...).)
709              
710             # CPAN::Version::vcmp courtesy Jost Krieger
711             sub _vcmp {
712 0     0   0 my($self,$l,$r) = @_;
713 0         0 local($^W) = 0;
714 0         0 $self->_verbose(9, "l[$l] r[$r]");
715              
716 0 0       0 return 0 if $l eq $r; # short circuit for quicker success
717              
718 0         0 for ($l,$r) {
719 0         0 s/_//g;
720             }
721 0         0 $self->_verbose(9, "l[$l] r[$r]");
722 0         0 for ($l,$r) {
723 0 0 0     0 next unless tr/.// > 1 || /^v/;
724 0         0 s/^v?/v/;
725 0         0 1 while s/\.0+(\d)/.$1/; # remove leading zeroes per group
726             }
727 0         0 $self->_verbose(9, "l[$l] r[$r]");
728 0 0       0 if ($l=~/^v/ <=> $r=~/^v/) {
729 0         0 for ($l,$r) {
730 0 0       0 next if /^v/;
731 0         0 $_ = $self->_float2vv($_);
732             }
733             }
734 0         0 $self->_verbose(9, "l[$l] r[$r]");
735 0         0 my $lvstring = "v0";
736 0         0 my $rvstring = "v0";
737 0 0 0     0 if ($] >= 5.006
      0        
738             && $l =~ /^v/
739             && $r =~ /^v/) {
740 0         0 $lvstring = $self->_vstring($l);
741 0         0 $rvstring = $self->_vstring($r);
742 0         0 $self->_verbose(9, sprintf "lv[%vd] rv[%vd]", $lvstring, $rvstring);
743             }
744              
745             return (
746 0   0     0 ($l ne "undef") <=> ($r ne "undef")
747             ||
748             $lvstring cmp $rvstring
749             ||
750             $l <=> $r
751             ||
752             $l cmp $r
753             );
754             }
755              
756             sub _vgt {
757 0     0   0 my($self,$l,$r) = @_;
758 0         0 $self->_vcmp($l,$r) > 0;
759             }
760              
761             sub _vlt {
762 0     0   0 my($self,$l,$r) = @_;
763 0         0 $self->_vcmp($l,$r) < 0;
764             }
765              
766             sub _vge {
767 0     0   0 my($self,$l,$r) = @_;
768 0         0 $self->_vcmp($l,$r) >= 0;
769             }
770              
771             sub _vle {
772 0     0   0 my($self,$l,$r) = @_;
773 0         0 $self->_vcmp($l,$r) <= 0;
774             }
775              
776             sub _vstring {
777 0     0   0 my($self,$n) = @_;
778 0 0       0 $n =~ s/^v// or die "Parse::PMFile::_vstring() called with invalid arg [$n]";
779 0         0 pack "U*", split /\./, $n;
780             }
781              
782             # vv => visible vstring
783             sub _float2vv {
784 0     0   0 my($self,$n) = @_;
785 0         0 my($rev) = int($n);
786 0   0     0 $rev ||= 0;
787 0         0 my($mantissa) = $n =~ /\.(\d{1,12})/; # limit to 12 digits to limit
788             # architecture influence
789 0   0     0 $mantissa ||= 0;
790 0         0 $mantissa .= "0" while length($mantissa)%3;
791 0         0 my $ret = "v" . $rev;
792 0         0 while ($mantissa) {
793 0 0       0 $mantissa =~ s/(\d{1,3})// or
794             die "Panic: length>0 but not a digit? mantissa[$mantissa]";
795 0         0 $ret .= ".".int($1);
796             }
797             # warn "n[$n]ret[$ret]";
798 0         0 $ret =~ s/(\.0)+/.0/; # v1.0.0 => v1.0
799 0         0 $ret;
800             }
801              
802             sub _readable {
803 59     59   239 my($self,$n) = @_;
804 59         455 $n =~ /^([\w\-\+\.]+)/;
805              
806 59 50 33     844 return $1 if defined $1 && length($1)>0;
807             # if the first user reaches version v43, he will be treated as "+".
808             # We'll have to decide about a new rule here then, depending on what
809             # will be the prevailing versioning behavior then.
810              
811 0 0         if ($] < 5.006) { # or whenever v-strings were introduced
812             # we get them wrong anyway, whatever we do, because 5.005 will
813             # have already interpreted 0.2.4 to be "0.24". So even if he
814             # indexer sends us something like "v0.2.4" we compare wrongly.
815              
816             # And if they say v1.2, then the old perl takes it as "v12"
817              
818 0           $self->_verbose(9, "Suspicious version string seen [$n]\n");
819 0           return $n;
820             }
821 0           my $better = sprintf "v%vd", $n;
822 0           $self->_verbose(9, "n[$n] better[$better]");
823 0           return $better;
824             }
825              
826             1;
827              
828             __END__