no trailing whitespace
[p5sagit/Module-Metadata.git] / lib / Module / Metadata.pm
CommitLineData
5ac756c6 1# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*-
2# vim:ts=8:sw=2:et:sta:sts=2
3package Module::Metadata;
4
cd41f0db 5# Adapted from Perl-licensed code originally distributed with
6# Module-Build by Ken Williams
5ac756c6 7
8# This module provides routines to gather information about
9# perl modules (assuming this may be expanded in the distant
10# parrot future to look at other types of modules).
11
12use strict;
13use vars qw($VERSION);
1e4aea7e 14$VERSION = '1.000011';
5ac756c6 15$VERSION = eval $VERSION;
16
6f3c7f28 17use Carp qw/croak/;
5ac756c6 18use File::Spec;
19use IO::File;
4850170c 20use version 0.87;
3db27017 21BEGIN {
22 if ($INC{'Log/Contextual.pm'}) {
23 Log::Contextual->import('log_info');
24 } else {
e6ddd765 25 *log_info = sub (&) { warn $_[0]->() };
3db27017 26 }
27}
5ac756c6 28use File::Find qw(find);
29
30my $V_NUM_REGEXP = qr{v?[0-9._]+}; # crudely, a v-string or decimal
31
32my $PKG_REGEXP = qr{ # match a package declaration
33 ^[\s\{;]* # intro chars on a line
34 package # the word 'package'
35 \s+ # whitespace
36 ([\w:]+) # a package name
37 \s* # optional whitespace
38 ($V_NUM_REGEXP)? # optional version number
39 \s* # optional whitesapce
710f253f 40 [;\{] # semicolon line terminator or block start (since 5.16)
5ac756c6 41}x;
42
43my $VARNAME_REGEXP = qr{ # match fully-qualified VERSION name
44 ([\$*]) # sigil - $ or *
45 (
46 ( # optional leading package name
47 (?:::|\')? # possibly starting like just :: (Ì la $::VERSION)
48 (?:\w+(?:::|\'))* # Foo::Bar:: ...
49 )?
50 VERSION
51 )\b
52}x;
53
54my $VERS_REGEXP = qr{ # match a VERSION definition
55 (?:
56 \(\s*$VARNAME_REGEXP\s*\) # with parens
57 |
58 $VARNAME_REGEXP # without parens
59 )
60 \s*
61 =[^=~] # = but not ==, nor =~
62}x;
63
5ac756c6 64sub new_from_file {
65 my $class = shift;
66 my $filename = File::Spec->rel2abs( shift );
67
68 return undef unless defined( $filename ) && -f $filename;
69 return $class->_init(undef, $filename, @_);
70}
71
f33c0a6c 72sub new_from_handle {
73 my $class = shift;
74 my $handle = shift;
75 my $filename = shift;
76 return undef unless defined($handle) && defined($filename);
77 $filename = File::Spec->rel2abs( $filename );
78
79 return $class->_init(undef, $filename, @_, handle => $handle);
80
81}
82
83
5ac756c6 84sub new_from_module {
85 my $class = shift;
86 my $module = shift;
87 my %props = @_;
88
89 $props{inc} ||= \@INC;
90 my $filename = $class->find_module_by_name( $module, $props{inc} );
91 return undef unless defined( $filename ) && -f $filename;
92 return $class->_init($module, $filename, %props);
93}
94
95{
dd5a4b10 96
5ac756c6 97 my $compare_versions = sub {
98 my ($v1, $op, $v2) = @_;
4850170c 99 $v1 = version->new($v1)
100 unless UNIVERSAL::isa($v1,'version');
dd5a4b10 101
5ac756c6 102 my $eval_str = "\$v1 $op \$v2";
103 my $result = eval $eval_str;
104 log_info { "error comparing versions: '$eval_str' $@" } if $@;
dd5a4b10 105
5ac756c6 106 return $result;
107 };
108
109 my $normalize_version = sub {
110 my ($version) = @_;
111 if ( $version =~ /[=<>!,]/ ) { # logic, not just version
112 # take as is without modification
113 }
4850170c 114 elsif ( ref $version eq 'version' ) { # version objects
5ac756c6 115 $version = $version->is_qv ? $version->normal : $version->stringify;
116 }
117 elsif ( $version =~ /^[^v][^.]*\.[^.]+\./ ) { # no leading v, multiple dots
118 # normalize string tuples without "v": "1.2.3" -> "v1.2.3"
119 $version = "v$version";
120 }
121 else {
122 # leave alone
123 }
124 return $version;
125 };
126
127 # separate out some of the conflict resolution logic
128
129 my $resolve_module_versions = sub {
130 my $packages = shift;
dd5a4b10 131
5ac756c6 132 my( $file, $version );
133 my $err = '';
134 foreach my $p ( @$packages ) {
135 if ( defined( $p->{version} ) ) {
136 if ( defined( $version ) ) {
137 if ( $compare_versions->( $version, '!=', $p->{version} ) ) {
138 $err .= " $p->{file} ($p->{version})\n";
139 } else {
140 # same version declared multiple times, ignore
141 }
142 } else {
143 $file = $p->{file};
144 $version = $p->{version};
145 }
146 }
147 $file ||= $p->{file} if defined( $p->{file} );
148 }
dd5a4b10 149
5ac756c6 150 if ( $err ) {
151 $err = " $file ($version)\n" . $err;
152 }
dd5a4b10 153
5ac756c6 154 my %result = (
155 file => $file,
156 version => $version,
157 err => $err
158 );
dd5a4b10 159
5ac756c6 160 return \%result;
161 };
162
ca33f3bd 163 sub provides {
164 my $class = shift;
165
6f3c7f28 166 croak "provides() requires key/value pairs \n" if @_ % 2;
ca33f3bd 167 my %args = @_;
168
6f3c7f28 169 croak "provides() takes only one of 'dir' or 'files'\n"
ca33f3bd 170 if $args{dir} && $args{files};
171
6f3c7f28 172 croak "provides() requires a 'version' argument"
c06d0187 173 unless defined $args{version};
174
6f3c7f28 175 croak "provides() does not support version '$args{version}' metadata"
c06d0187 176 unless grep { $args{version} eq $_ } qw/1.4 2/;
177
ca33f3bd 178 $args{prefix} = 'lib' unless defined $args{prefix};
179
180 my $p;
181 if ( $args{dir} ) {
182 $p = $class->package_versions_from_directory($args{dir});
183 }
184 else {
6f3c7f28 185 croak "provides() requires 'files' to be an array reference\n"
ca33f3bd 186 unless ref $args{files} eq 'ARRAY';
187 $p = $class->package_versions_from_directory($args{files});
188 }
189
190 # Now, fix up files with prefix
191 if ( length $args{prefix} ) { # check in case disabled with q{}
192 $args{prefix} =~ s{/$}{};
193 for my $v ( values %$p ) {
194 $v->{file} = "$args{prefix}/$v->{file}";
195 }
196 }
197
198 return $p
199 }
200
5ac756c6 201 sub package_versions_from_directory {
202 my ( $class, $dir, $files ) = @_;
203
204 my @files;
205
206 if ( $files ) {
207 @files = @$files;
208 } else {
209 find( {
210 wanted => sub {
211 push @files, $_ if -f $_ && /\.pm$/;
212 },
213 no_chdir => 1,
214 }, $dir );
215 }
216
217 # First, we enumerate all packages & versions,
218 # separating into primary & alternative candidates
219 my( %prime, %alt );
220 foreach my $file (@files) {
713aab0e 221 my $mapped_filename = File::Spec::Unix->abs2rel( $file, $dir );
5ac756c6 222 my @path = split( /\//, $mapped_filename );
223 (my $prime_package = join( '::', @path )) =~ s/\.pm$//;
dd5a4b10 224
5ac756c6 225 my $pm_info = $class->new_from_file( $file );
dd5a4b10 226
5ac756c6 227 foreach my $package ( $pm_info->packages_inside ) {
228 next if $package eq 'main'; # main can appear numerous times, ignore
229 next if $package eq 'DB'; # special debugging package, ignore
230 next if grep /^_/, split( /::/, $package ); # private package, ignore
dd5a4b10 231
5ac756c6 232 my $version = $pm_info->version( $package );
dd5a4b10 233
713aab0e 234 $prime_package = $package if lc($prime_package) eq lc($package);
5ac756c6 235 if ( $package eq $prime_package ) {
236 if ( exists( $prime{$package} ) ) {
6f3c7f28 237 croak "Unexpected conflict in '$package'; multiple versions found.\n";
5ac756c6 238 } else {
713aab0e 239 $mapped_filename = "$package.pm" if lc("$package.pm") eq lc($mapped_filename);
5ac756c6 240 $prime{$package}{file} = $mapped_filename;
241 $prime{$package}{version} = $version if defined( $version );
242 }
243 } else {
244 push( @{$alt{$package}}, {
245 file => $mapped_filename,
246 version => $version,
247 } );
248 }
249 }
250 }
dd5a4b10 251
5ac756c6 252 # Then we iterate over all the packages found above, identifying conflicts
253 # and selecting the "best" candidate for recording the file & version
254 # for each package.
255 foreach my $package ( keys( %alt ) ) {
256 my $result = $resolve_module_versions->( $alt{$package} );
dd5a4b10 257
5ac756c6 258 if ( exists( $prime{$package} ) ) { # primary package selected
dd5a4b10 259
5ac756c6 260 if ( $result->{err} ) {
261 # Use the selected primary package, but there are conflicting
262 # errors among multiple alternative packages that need to be
263 # reported
264 log_info {
265 "Found conflicting versions for package '$package'\n" .
266 " $prime{$package}{file} ($prime{$package}{version})\n" .
267 $result->{err}
268 };
dd5a4b10 269
5ac756c6 270 } elsif ( defined( $result->{version} ) ) {
271 # There is a primary package selected, and exactly one
272 # alternative package
dd5a4b10 273
5ac756c6 274 if ( exists( $prime{$package}{version} ) &&
275 defined( $prime{$package}{version} ) ) {
276 # Unless the version of the primary package agrees with the
277 # version of the alternative package, report a conflict
278 if ( $compare_versions->(
279 $prime{$package}{version}, '!=', $result->{version}
280 )
281 ) {
282
283 log_info {
284 "Found conflicting versions for package '$package'\n" .
285 " $prime{$package}{file} ($prime{$package}{version})\n" .
286 " $result->{file} ($result->{version})\n"
287 };
288 }
dd5a4b10 289
5ac756c6 290 } else {
291 # The prime package selected has no version so, we choose to
292 # use any alternative package that does have a version
293 $prime{$package}{file} = $result->{file};
294 $prime{$package}{version} = $result->{version};
295 }
dd5a4b10 296
5ac756c6 297 } else {
298 # no alt package found with a version, but we have a prime
299 # package so we use it whether it has a version or not
300 }
dd5a4b10 301
5ac756c6 302 } else { # No primary package was selected, use the best alternative
dd5a4b10 303
5ac756c6 304 if ( $result->{err} ) {
305 log_info {
306 "Found conflicting versions for package '$package'\n" .
307 $result->{err}
308 };
309 }
dd5a4b10 310
5ac756c6 311 # Despite possible conflicting versions, we choose to record
312 # something rather than nothing
313 $prime{$package}{file} = $result->{file};
314 $prime{$package}{version} = $result->{version}
315 if defined( $result->{version} );
316 }
317 }
dd5a4b10 318
5ac756c6 319 # Normalize versions. Can't use exists() here because of bug in YAML::Node.
320 # XXX "bug in YAML::Node" comment seems irrelvant -- dagolden, 2009-05-18
321 for (grep defined $_->{version}, values %prime) {
322 $_->{version} = $normalize_version->( $_->{version} );
323 }
dd5a4b10 324
5ac756c6 325 return \%prime;
326 }
dd5a4b10 327}
328
5ac756c6 329
330sub _init {
331 my $class = shift;
332 my $module = shift;
333 my $filename = shift;
334 my %props = @_;
335
f33c0a6c 336 my $handle = delete $props{handle};
5ac756c6 337 my( %valid_props, @valid_props );
338 @valid_props = qw( collect_pod inc );
339 @valid_props{@valid_props} = delete( @props{@valid_props} );
340 warn "Unknown properties: @{[keys %props]}\n" if scalar( %props );
341
342 my %data = (
343 module => $module,
344 filename => $filename,
345 version => undef,
346 packages => [],
347 versions => {},
348 pod => {},
349 pod_headings => [],
350 collect_pod => 0,
351
352 %valid_props,
353 );
354
355 my $self = bless(\%data, $class);
356
f33c0a6c 357 if ( $handle ) {
358 $self->_parse_fh($handle);
359 }
360 else {
361 $self->_parse_file();
362 }
5ac756c6 363
364 unless($self->{module} and length($self->{module})) {
365 my ($v, $d, $f) = File::Spec->splitpath($self->{filename});
366 if($f =~ /\.pm$/) {
367 $f =~ s/\..+$//;
368 my @candidates = grep /$f$/, @{$self->{packages}};
369 $self->{module} = shift(@candidates); # punt
370 }
371 else {
372 if(grep /main/, @{$self->{packages}}) {
373 $self->{module} = 'main';
374 }
375 else {
376 $self->{module} = $self->{packages}[0] || '';
377 }
378 }
379 }
380
381 $self->{version} = $self->{versions}{$self->{module}}
382 if defined( $self->{module} );
383
384 return $self;
385}
386
387# class method
388sub _do_find_module {
389 my $class = shift;
6f3c7f28 390 my $module = shift || croak 'find_module_by_name() requires a package name';
5ac756c6 391 my $dirs = shift || \@INC;
392
393 my $file = File::Spec->catfile(split( /::/, $module));
394 foreach my $dir ( @$dirs ) {
395 my $testfile = File::Spec->catfile($dir, $file);
396 return [ File::Spec->rel2abs( $testfile ), $dir ]
397 if -e $testfile and !-d _; # For stuff like ExtUtils::xsubpp
398 return [ File::Spec->rel2abs( "$testfile.pm" ), $dir ]
399 if -e "$testfile.pm";
400 }
401 return;
402}
403
404# class method
405sub find_module_by_name {
406 my $found = shift()->_do_find_module(@_) or return;
407 return $found->[0];
408}
409
410# class method
411sub find_module_dir_by_name {
412 my $found = shift()->_do_find_module(@_) or return;
413 return $found->[1];
414}
415
416
417# given a line of perl code, attempt to parse it if it looks like a
418# $VERSION assignment, returning sigil, full name, & package name
419sub _parse_version_expression {
420 my $self = shift;
421 my $line = shift;
422
423 my( $sig, $var, $pkg );
69859aa0 424 if ( $line =~ /$VERS_REGEXP/o ) {
5ac756c6 425 ( $sig, $var, $pkg ) = $2 ? ( $1, $2, $3 ) : ( $4, $5, $6 );
426 if ( $pkg ) {
427 $pkg = ($pkg eq '::') ? 'main' : $pkg;
428 $pkg =~ s/::$//;
429 }
430 }
431
432 return ( $sig, $var, $pkg );
433}
434
435sub _parse_file {
436 my $self = shift;
437
438 my $filename = $self->{filename};
439 my $fh = IO::File->new( $filename )
6f3c7f28 440 or croak( "Can't open '$filename': $!" );
5ac756c6 441
f77c3f08 442 $self->_handle_bom($fh, $filename);
443
5ac756c6 444 $self->_parse_fh($fh);
445}
446
f77c3f08 447# Look for a UTF-8/UTF-16BE/UTF-16LE BOM at the beginning of the stream.
448# If there's one, then skip it and set the :encoding layer appropriately.
449sub _handle_bom {
450 my ($self, $fh, $filename) = @_;
451
452 my $pos = $fh->getpos;
453 return unless defined $pos;
454
455 my $buf = ' ' x 2;
456 my $count = $fh->read( $buf, length $buf );
457 return unless defined $count and $count >= 2;
458
459 my $encoding;
460 if ( $buf eq "\x{FE}\x{FF}" ) {
461 $encoding = 'UTF-16BE';
462 } elsif ( $buf eq "\x{FF}\x{FE}" ) {
463 $encoding = 'UTF-16LE';
464 } elsif ( $buf eq "\x{EF}\x{BB}" ) {
465 $buf = ' ';
466 $count = $fh->read( $buf, length $buf );
467 if ( defined $count and $count >= 1 and $buf eq "\x{BF}" ) {
468 $encoding = 'UTF-8';
469 }
470 }
471
472 if ( defined $encoding ) {
473 if ( "$]" >= 5.008 ) {
474 # $fh->binmode requires perl 5.10
475 binmode( $fh, ":encoding($encoding)" );
476 }
477 } else {
478 $fh->setpos($pos)
479 or croak( sprintf "Can't reset position to the top of '$filename'" );
480 }
481
482 return $encoding;
483}
484
5ac756c6 485sub _parse_fh {
486 my ($self, $fh) = @_;
487
488 my( $in_pod, $seen_end, $need_vers ) = ( 0, 0, 0 );
489 my( @pkgs, %vers, %pod, @pod );
490 my $pkg = 'main';
491 my $pod_sect = '';
492 my $pod_data = '';
493
494 while (defined( my $line = <$fh> )) {
495 my $line_num = $.;
496
497 chomp( $line );
5ac756c6 498
cfedad89 499 # From toke.c : any line that begins by "=X", where X is an alphabetic
500 # character, introduces a POD segment.
921abefc 501 my $is_cut;
cfedad89 502 if ( $line =~ /^=([a-zA-Z].*)/ ) {
503 my $cmd = $1;
504 # Then it goes back to Perl code for "=cutX" where X is a non-alphabetic
505 # character (which includes the newline, but here we chomped it away).
506 $is_cut = $cmd =~ /^cut(?:[^a-zA-Z]|$)/;
921abefc 507 $in_pod = !$is_cut;
508 }
5ac756c6 509
617f8754 510 if ( $in_pod ) {
5ac756c6 511
a4aafbc2 512 if ( $line =~ /^=head[1-4]\s+(.+)\s*$/ ) {
5ac756c6 513 push( @pod, $1 );
514 if ( $self->{collect_pod} && length( $pod_data ) ) {
515 $pod{$pod_sect} = $pod_data;
516 $pod_data = '';
517 }
518 $pod_sect = $1;
519
5ac756c6 520 } elsif ( $self->{collect_pod} ) {
521 $pod_data .= "$line\n";
522
523 }
524
617f8754 525 } elsif ( $is_cut ) {
5ac756c6 526
617f8754 527 if ( $self->{collect_pod} && length( $pod_data ) ) {
528 $pod{$pod_sect} = $pod_data;
529 $pod_data = '';
530 }
5ac756c6 531 $pod_sect = '';
617f8754 532
533 } else {
5ac756c6 534
81ce8c82 535 # Skip comments in code
536 next if $line =~ /^\s*#/;
537
b48c592a 538 # Would be nice if we could also check $in_string or something too
539 last if $line =~ /^__(?:DATA|END)__$/;
540
5ac756c6 541 # parse $line to see if it's a $VERSION declaration
542 my( $vers_sig, $vers_fullname, $vers_pkg ) =
9922478c 543 ($line =~ /VERSION/)
544 ? $self->_parse_version_expression( $line )
545 : ();
5ac756c6 546
69859aa0 547 if ( $line =~ /$PKG_REGEXP/o ) {
5ac756c6 548 $pkg = $1;
549 push( @pkgs, $pkg ) unless grep( $pkg eq $_, @pkgs );
a88210e4 550 $vers{$pkg} = $2 unless exists( $vers{$pkg} );
5ac756c6 551 $need_vers = defined $2 ? 0 : 1;
552
553 # VERSION defined with full package spec, i.e. $Module::VERSION
554 } elsif ( $vers_fullname && $vers_pkg ) {
555 push( @pkgs, $vers_pkg ) unless grep( $vers_pkg eq $_, @pkgs );
556 $need_vers = 0 if $vers_pkg eq $pkg;
557
558 unless ( defined $vers{$vers_pkg} && length $vers{$vers_pkg} ) {
559 $vers{$vers_pkg} =
560 $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
5ac756c6 561 }
562
563 # first non-comment line in undeclared package main is VERSION
564 } elsif ( !exists($vers{main}) && $pkg eq 'main' && $vers_fullname ) {
565 $need_vers = 0;
566 my $v =
567 $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
568 $vers{$pkg} = $v;
569 push( @pkgs, 'main' );
570
571 # first non-comment line in undeclared package defines package main
572 } elsif ( !exists($vers{main}) && $pkg eq 'main' && $line =~ /\w+/ ) {
573 $need_vers = 1;
574 $vers{main} = '';
575 push( @pkgs, 'main' );
576
577 # only keep if this is the first $VERSION seen
578 } elsif ( $vers_fullname && $need_vers ) {
579 $need_vers = 0;
580 my $v =
581 $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
582
583
584 unless ( defined $vers{$pkg} && length $vers{$pkg} ) {
585 $vers{$pkg} = $v;
dd5a4b10 586 }
5ac756c6 587
588 }
589
590 }
591
592 }
593
594 if ( $self->{collect_pod} && length($pod_data) ) {
595 $pod{$pod_sect} = $pod_data;
596 }
597
598 $self->{versions} = \%vers;
599 $self->{packages} = \@pkgs;
600 $self->{pod} = \%pod;
601 $self->{pod_headings} = \@pod;
602}
603
604{
605my $pn = 0;
606sub _evaluate_version_line {
607 my $self = shift;
608 my( $sigil, $var, $line ) = @_;
609
610 # Some of this code came from the ExtUtils:: hierarchy.
611
612 # We compile into $vsub because 'use version' would cause
613 # compiletime/runtime issues with local()
614 my $vsub;
615 $pn++; # everybody gets their own package
616 my $eval = qq{BEGIN { q# Hide from _packages_inside()
617 #; package Module::Metadata::_version::p$pn;
4850170c 618 use version;
5ac756c6 619 no strict;
620
5ac756c6 621 \$vsub = sub {
398fe5a2 622 local $sigil$var;
623 \$$var=undef;
5ac756c6 624 $line;
625 \$$var
626 };
627 }};
628
629 local $^W;
630 # Try to get the $VERSION
631 eval $eval;
632 # some modules say $VERSION = $Foo::Bar::VERSION, but Foo::Bar isn't
633 # installed, so we need to hunt in ./lib for it
634 if ( $@ =~ /Can't locate/ && -d 'lib' ) {
635 local @INC = ('lib',@INC);
636 eval $eval;
637 }
638 warn "Error evaling version line '$eval' in $self->{filename}: $@\n"
639 if $@;
640 (ref($vsub) eq 'CODE') or
6f3c7f28 641 croak "failed to build version sub for $self->{filename}";
5ac756c6 642 my $result = eval { $vsub->() };
6f3c7f28 643 croak "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n"
5ac756c6 644 if $@;
645
d880ef1f 646 # Upgrade it into a version object
92ad06ed 647 my $version = eval { _dwim_version($result) };
648
6f3c7f28 649 croak "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n"
92ad06ed 650 unless defined $version; # "0" is OK!
5ac756c6 651
92ad06ed 652 return $version;
5ac756c6 653}
654}
655
92ad06ed 656# Try to DWIM when things fail the lax version test in obvious ways
657{
658 my @version_prep = (
659 # Best case, it just works
660 sub { return shift },
661
662 # If we still don't have a version, try stripping any
663 # trailing junk that is prohibited by lax rules
664 sub {
665 my $v = shift;
666 $v =~ s{([0-9])[a-z-].*$}{$1}i; # 1.23-alpha or 1.23b
667 return $v;
668 },
669
670 # Activestate apparently creates custom versions like '1.23_45_01', which
671 # cause version.pm to think it's an invalid alpha. So check for that
672 # and strip them
673 sub {
674 my $v = shift;
675 my $num_dots = () = $v =~ m{(\.)}g;
676 my $num_unders = () = $v =~ m{(_)}g;
677 my $leading_v = substr($v,0,1) eq 'v';
678 if ( ! $leading_v && $num_dots < 2 && $num_unders > 1 ) {
679 $v =~ s{_}{}g;
680 $num_unders = () = $v =~ m{(_)}g;
681 }
682 return $v;
683 },
684
685 # Worst case, try numifying it like we would have before version objects
686 sub {
687 my $v = shift;
688 no warnings 'numeric';
689 return 0 + $v;
690 },
691
692 );
693
694 sub _dwim_version {
695 my ($result) = shift;
696
697 return $result if ref($result) eq 'version';
698
699 my ($version, $error);
700 for my $f (@version_prep) {
701 $result = $f->($result);
702 $version = eval { version->new($result) };
703 $error ||= $@ if $@; # capture first failure
704 last if defined $version;
705 }
706
6f3c7f28 707 croak $error unless defined $version;
92ad06ed 708
709 return $version;
710 }
711}
5ac756c6 712
713############################################################
714
715# accessors
716sub name { $_[0]->{module} }
717
718sub filename { $_[0]->{filename} }
719sub packages_inside { @{$_[0]->{packages}} }
720sub pod_inside { @{$_[0]->{pod_headings}} }
721sub contains_pod { $#{$_[0]->{pod_headings}} }
722
723sub version {
724 my $self = shift;
725 my $mod = shift || $self->{module};
726 my $vers;
727 if ( defined( $mod ) && length( $mod ) &&
728 exists( $self->{versions}{$mod} ) ) {
729 return $self->{versions}{$mod};
730 } else {
731 return undef;
732 }
733}
734
735sub pod {
736 my $self = shift;
737 my $sect = shift;
738 if ( defined( $sect ) && length( $sect ) &&
739 exists( $self->{pod}{$sect} ) ) {
740 return $self->{pod}{$sect};
741 } else {
742 return undef;
743 }
744}
745
7461;
747
5ac756c6 748=head1 NAME
749
2c11e51d 750Module::Metadata - Gather package and POD information from perl module files
5ac756c6 751
6290f67c 752=head1 SYNOPSIS
753
754 use Module::Metadata;
755
756 # information about a .pm file
757 my $info = Module::Metadata->new_from_file( $file );
758 my $version = $info->version;
759
ca33f3bd 760 # CPAN META 'provides' field for .pm files in a directory
c06d0187 761 my $provides = Module::Metadata->provides(
762 dir => 'lib', version => 2
763 );
6290f67c 764
5ac756c6 765=head1 DESCRIPTION
766
6290f67c 767This module provides a standard way to gather metadata about a .pm file
768without executing unsafe code.
769
770=head1 USAGE
771
772=head2 Class methods
773
5ac756c6 774=over 4
775
6290f67c 776=item C<< new_from_file($filename, collect_pod => 1) >>
5ac756c6 777
4c401e3f 778Constructs a C<Module::Metadata> object given the path to a file. Returns
779undef if the filename does not exist.
780
781C<collect_pod> is a optional boolean argument that determines whether POD
782data is collected and stored for reference. POD data is not collected by
783default. POD headings are always collected.
784
785If the file begins by an UTF-8, UTF-16BE or UTF-16LE byte-order mark, then
786it is skipped before processing, and the content of the file is also decoded
787appropriately starting from perl 5.8.
5ac756c6 788
6290f67c 789=item C<< new_from_handle($handle, $filename, collect_pod => 1) >>
f33c0a6c 790
791This works just like C<new_from_file>, except that a handle can be provided
4c401e3f 792as the first argument.
793
794Note that there is no validation to confirm that the handle is a handle or
795something that can act like one. Passing something that isn't a handle will
796cause a exception when trying to read from it. The C<filename> argument is
797mandatory or undef will be returned.
798
799You are responsible for setting the decoding layers on C<$handle> if
800required.
f33c0a6c 801
6290f67c 802=item C<< new_from_module($module, collect_pod => 1, inc => \@dirs) >>
5ac756c6 803
4c401e3f 804Constructs a C<Module::Metadata> object given a module or package name.
805Returns undef if the module cannot be found.
806
807In addition to accepting the C<collect_pod> argument as described above,
808this method accepts a C<inc> argument which is a reference to an array of
809directories to search for the module. If none are given, the default is
810@INC.
811
812If the file that contains the module begins by an UTF-8, UTF-16BE or
813UTF-16LE byte-order mark, then it is skipped before processing, and the
814content of the file is also decoded appropriately starting from perl 5.8.
5ac756c6 815
6290f67c 816=item C<< find_module_by_name($module, \@dirs) >>
5ac756c6 817
818Returns the path to a module given the module or package name. A list
819of directories can be passed in as an optional parameter, otherwise
820@INC is searched.
821
822Can be called as either an object or a class method.
823
6290f67c 824=item C<< find_module_dir_by_name($module, \@dirs) >>
5ac756c6 825
826Returns the entry in C<@dirs> (or C<@INC> by default) that contains
827the module C<$module>. A list of directories can be passed in as an
828optional parameter, otherwise @INC is searched.
829
830Can be called as either an object or a class method.
831
ca33f3bd 832=item C<< provides( %options ) >>
833
834This is a convenience wrapper around C<package_versions_from_directory>
835to generate a CPAN META C<provides> data structure. It takes key/value
836pairs. Valid option keys include:
837
838=over
839
c06d0187 840=item version B<(required)>
841
842Specifies which version of the L<CPAN::Meta::Spec> should be used as
843the format of the C<provides> output. Currently only '1.4' and '2'
844are supported (and their format is identical). This may change in
845the future as the definition of C<provides> changes.
846
847The C<version> option is required. If it is omitted or if
848an unsupported version is given, then C<provides> will throw an error.
849
ca33f3bd 850=item dir
851
852Directory to search recursively for F<.pm> files. May not be specified with
853C<files>.
854
855=item files
856
857Array reference of files to examine. May not be specified with C<dir>.
858
859=item prefix
860
861String to prepend to the C<file> field of the resulting output. This defaults
862to F<lib>, which is the common case for most CPAN distributions with their
863F<.pm> files in F<lib>. This option ensures the META information has the
864correct relative path even when the C<dir> or C<files> arguments are
865absolute or have relative paths from a location other than the distribution
866root.
867
868=back
869
870For example, given C<dir> of 'lib' and C<prefix> of 'lib', the return value
871is a hashref of the form:
872
873 {
874 'Package::Name' => {
875 version => '0.123',
876 file => 'lib/Package/Name.pm'
877 },
878 'OtherPackage::Name' => ...
879 }
880
6290f67c 881=item C<< package_versions_from_directory($dir, \@files?) >>
2c11e51d 882
883Scans C<$dir> for .pm files (unless C<@files> is given, in which case looks
884for those files in C<$dir> - and reads each file for packages and versions,
885returning a hashref of the form:
5ac756c6 886
2c11e51d 887 {
888 'Package::Name' => {
889 version => '0.123',
890 file => 'Package/Name.pm'
891 },
892 'OtherPackage::Name' => ...
893 }
894
ca33f3bd 895The C<DB> and C<main> packages are always omitted, as are any "private"
896packages that have leading underscores in the namespace (e.g.
897C<Foo::_private>)
898
899Note that the file path is relative to C<$dir> if that is specified.
900This B<must not> be used directly for CPAN META C<provides>. See
901the C<provides> method instead.
902
6290f67c 903=item C<< log_info (internal) >>
2c11e51d 904
905Used internally to perform logging; imported from Log::Contextual if
906Log::Contextual has already been loaded, otherwise simply calls warn.
907
908=back
5ac756c6 909
6290f67c 910=head2 Object methods
911
912=over 4
913
914=item C<< name() >>
915
916Returns the name of the package represented by this module. If there
917are more than one packages, it makes a best guess based on the
918filename. If it's a script (i.e. not a *.pm) the package name is
919'main'.
920
921=item C<< version($package) >>
922
923Returns the version as defined by the $VERSION variable for the
924package as returned by the C<name> method if no arguments are
925given. If given the name of a package it will attempt to return the
926version of that package if it is specified in the file.
927
928=item C<< filename() >>
929
930Returns the absolute path to the file.
931
932=item C<< packages_inside() >>
933
1f67ffd7 934Returns a list of packages. Note: this is a raw list of packages
935discovered (or assumed, in the case of C<main>). It is not
936filtered for C<DB>, C<main> or private packages the way the
937C<provides> method does.
6290f67c 938
939=item C<< pod_inside() >>
940
941Returns a list of POD sections.
942
943=item C<< contains_pod() >>
944
945Returns true if there is any POD in the file.
946
947=item C<< pod($section) >>
948
949Returns the POD data in the given section.
950
951=back
952
5ac756c6 953=head1 AUTHOR
954
6290f67c 955Original code from Module::Build::ModuleInfo by Ken Williams
956<kwilliams@cpan.org>, Randy W. Sims <RandyS@ThePierianSpring.org>
5ac756c6 957
2c11e51d 958Released as Module::Metadata by Matt S Trout (mst) <mst@shadowcat.co.uk> with
6290f67c 959assistance from David Golden (xdg) <dagolden@cpan.org>.
5ac756c6 960
4c401e3f 961=head1 COPYRIGHT & LICENSE
5ac756c6 962
6290f67c 963Original code Copyright (c) 2001-2011 Ken Williams.
964Additional code Copyright (c) 2010-2011 Matt Trout and David Golden.
965All rights reserved.
5ac756c6 966
967This library is free software; you can redistribute it and/or
968modify it under the same terms as Perl itself.
969
5ac756c6 970=cut
971