Do the (dev) release dance
[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);
74b89743 14$VERSION = '1.000010_001';
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{
96
97 my $compare_versions = sub {
98 my ($v1, $op, $v2) = @_;
4850170c 99 $v1 = version->new($v1)
100 unless UNIVERSAL::isa($v1,'version');
5ac756c6 101
102 my $eval_str = "\$v1 $op \$v2";
103 my $result = eval $eval_str;
104 log_info { "error comparing versions: '$eval_str' $@" } if $@;
105
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;
131
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 }
149
150 if ( $err ) {
151 $err = " $file ($version)\n" . $err;
152 }
153
154 my %result = (
155 file => $file,
156 version => $version,
157 err => $err
158 );
159
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$//;
224
225 my $pm_info = $class->new_from_file( $file );
226
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
231
232 my $version = $pm_info->version( $package );
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 }
251
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} );
257
258 if ( exists( $prime{$package} ) ) { # primary package selected
259
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 };
269
270 } elsif ( defined( $result->{version} ) ) {
271 # There is a primary package selected, and exactly one
272 # alternative package
273
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 }
289
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 }
296
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 }
301
302 } else { # No primary package was selected, use the best alternative
303
304 if ( $result->{err} ) {
305 log_info {
306 "Found conflicting versions for package '$package'\n" .
307 $result->{err}
308 };
309 }
310
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 }
318
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 }
324
325 return \%prime;
326 }
327}
328
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;
586 } else {
587 warn <<"EOM";
588Package '$pkg' already declared with version '$vers{$pkg}'
589ignoring new version '$v' on line $line_num.
590EOM
591 }
592
593 }
594
595 }
596
597 }
598
599 if ( $self->{collect_pod} && length($pod_data) ) {
600 $pod{$pod_sect} = $pod_data;
601 }
602
603 $self->{versions} = \%vers;
604 $self->{packages} = \@pkgs;
605 $self->{pod} = \%pod;
606 $self->{pod_headings} = \@pod;
607}
608
609{
610my $pn = 0;
611sub _evaluate_version_line {
612 my $self = shift;
613 my( $sigil, $var, $line ) = @_;
614
615 # Some of this code came from the ExtUtils:: hierarchy.
616
617 # We compile into $vsub because 'use version' would cause
618 # compiletime/runtime issues with local()
619 my $vsub;
620 $pn++; # everybody gets their own package
621 my $eval = qq{BEGIN { q# Hide from _packages_inside()
622 #; package Module::Metadata::_version::p$pn;
4850170c 623 use version;
5ac756c6 624 no strict;
625
5ac756c6 626 \$vsub = sub {
398fe5a2 627 local $sigil$var;
628 \$$var=undef;
5ac756c6 629 $line;
630 \$$var
631 };
632 }};
633
634 local $^W;
635 # Try to get the $VERSION
636 eval $eval;
637 # some modules say $VERSION = $Foo::Bar::VERSION, but Foo::Bar isn't
638 # installed, so we need to hunt in ./lib for it
639 if ( $@ =~ /Can't locate/ && -d 'lib' ) {
640 local @INC = ('lib',@INC);
641 eval $eval;
642 }
643 warn "Error evaling version line '$eval' in $self->{filename}: $@\n"
644 if $@;
645 (ref($vsub) eq 'CODE') or
6f3c7f28 646 croak "failed to build version sub for $self->{filename}";
5ac756c6 647 my $result = eval { $vsub->() };
6f3c7f28 648 croak "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n"
5ac756c6 649 if $@;
650
d880ef1f 651 # Upgrade it into a version object
92ad06ed 652 my $version = eval { _dwim_version($result) };
653
6f3c7f28 654 croak "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n"
92ad06ed 655 unless defined $version; # "0" is OK!
5ac756c6 656
92ad06ed 657 return $version;
5ac756c6 658}
659}
660
92ad06ed 661# Try to DWIM when things fail the lax version test in obvious ways
662{
663 my @version_prep = (
664 # Best case, it just works
665 sub { return shift },
666
667 # If we still don't have a version, try stripping any
668 # trailing junk that is prohibited by lax rules
669 sub {
670 my $v = shift;
671 $v =~ s{([0-9])[a-z-].*$}{$1}i; # 1.23-alpha or 1.23b
672 return $v;
673 },
674
675 # Activestate apparently creates custom versions like '1.23_45_01', which
676 # cause version.pm to think it's an invalid alpha. So check for that
677 # and strip them
678 sub {
679 my $v = shift;
680 my $num_dots = () = $v =~ m{(\.)}g;
681 my $num_unders = () = $v =~ m{(_)}g;
682 my $leading_v = substr($v,0,1) eq 'v';
683 if ( ! $leading_v && $num_dots < 2 && $num_unders > 1 ) {
684 $v =~ s{_}{}g;
685 $num_unders = () = $v =~ m{(_)}g;
686 }
687 return $v;
688 },
689
690 # Worst case, try numifying it like we would have before version objects
691 sub {
692 my $v = shift;
693 no warnings 'numeric';
694 return 0 + $v;
695 },
696
697 );
698
699 sub _dwim_version {
700 my ($result) = shift;
701
702 return $result if ref($result) eq 'version';
703
704 my ($version, $error);
705 for my $f (@version_prep) {
706 $result = $f->($result);
707 $version = eval { version->new($result) };
708 $error ||= $@ if $@; # capture first failure
709 last if defined $version;
710 }
711
6f3c7f28 712 croak $error unless defined $version;
92ad06ed 713
714 return $version;
715 }
716}
5ac756c6 717
718############################################################
719
720# accessors
721sub name { $_[0]->{module} }
722
723sub filename { $_[0]->{filename} }
724sub packages_inside { @{$_[0]->{packages}} }
725sub pod_inside { @{$_[0]->{pod_headings}} }
726sub contains_pod { $#{$_[0]->{pod_headings}} }
727
728sub version {
729 my $self = shift;
730 my $mod = shift || $self->{module};
731 my $vers;
732 if ( defined( $mod ) && length( $mod ) &&
733 exists( $self->{versions}{$mod} ) ) {
734 return $self->{versions}{$mod};
735 } else {
736 return undef;
737 }
738}
739
740sub pod {
741 my $self = shift;
742 my $sect = shift;
743 if ( defined( $sect ) && length( $sect ) &&
744 exists( $self->{pod}{$sect} ) ) {
745 return $self->{pod}{$sect};
746 } else {
747 return undef;
748 }
749}
750
7511;
752
5ac756c6 753=head1 NAME
754
2c11e51d 755Module::Metadata - Gather package and POD information from perl module files
5ac756c6 756
6290f67c 757=head1 SYNOPSIS
758
759 use Module::Metadata;
760
761 # information about a .pm file
762 my $info = Module::Metadata->new_from_file( $file );
763 my $version = $info->version;
764
ca33f3bd 765 # CPAN META 'provides' field for .pm files in a directory
c06d0187 766 my $provides = Module::Metadata->provides(
767 dir => 'lib', version => 2
768 );
6290f67c 769
5ac756c6 770=head1 DESCRIPTION
771
6290f67c 772This module provides a standard way to gather metadata about a .pm file
773without executing unsafe code.
774
775=head1 USAGE
776
777=head2 Class methods
778
5ac756c6 779=over 4
780
6290f67c 781=item C<< new_from_file($filename, collect_pod => 1) >>
5ac756c6 782
4c401e3f 783Constructs a C<Module::Metadata> object given the path to a file. Returns
784undef if the filename does not exist.
785
786C<collect_pod> is a optional boolean argument that determines whether POD
787data is collected and stored for reference. POD data is not collected by
788default. POD headings are always collected.
789
790If the file begins by an UTF-8, UTF-16BE or UTF-16LE byte-order mark, then
791it is skipped before processing, and the content of the file is also decoded
792appropriately starting from perl 5.8.
5ac756c6 793
6290f67c 794=item C<< new_from_handle($handle, $filename, collect_pod => 1) >>
f33c0a6c 795
796This works just like C<new_from_file>, except that a handle can be provided
4c401e3f 797as the first argument.
798
799Note that there is no validation to confirm that the handle is a handle or
800something that can act like one. Passing something that isn't a handle will
801cause a exception when trying to read from it. The C<filename> argument is
802mandatory or undef will be returned.
803
804You are responsible for setting the decoding layers on C<$handle> if
805required.
f33c0a6c 806
6290f67c 807=item C<< new_from_module($module, collect_pod => 1, inc => \@dirs) >>
5ac756c6 808
4c401e3f 809Constructs a C<Module::Metadata> object given a module or package name.
810Returns undef if the module cannot be found.
811
812In addition to accepting the C<collect_pod> argument as described above,
813this method accepts a C<inc> argument which is a reference to an array of
814directories to search for the module. If none are given, the default is
815@INC.
816
817If the file that contains the module begins by an UTF-8, UTF-16BE or
818UTF-16LE byte-order mark, then it is skipped before processing, and the
819content of the file is also decoded appropriately starting from perl 5.8.
5ac756c6 820
6290f67c 821=item C<< find_module_by_name($module, \@dirs) >>
5ac756c6 822
823Returns the path to a module given the module or package name. A list
824of directories can be passed in as an optional parameter, otherwise
825@INC is searched.
826
827Can be called as either an object or a class method.
828
6290f67c 829=item C<< find_module_dir_by_name($module, \@dirs) >>
5ac756c6 830
831Returns the entry in C<@dirs> (or C<@INC> by default) that contains
832the module C<$module>. A list of directories can be passed in as an
833optional parameter, otherwise @INC is searched.
834
835Can be called as either an object or a class method.
836
ca33f3bd 837=item C<< provides( %options ) >>
838
839This is a convenience wrapper around C<package_versions_from_directory>
840to generate a CPAN META C<provides> data structure. It takes key/value
841pairs. Valid option keys include:
842
843=over
844
c06d0187 845=item version B<(required)>
846
847Specifies which version of the L<CPAN::Meta::Spec> should be used as
848the format of the C<provides> output. Currently only '1.4' and '2'
849are supported (and their format is identical). This may change in
850the future as the definition of C<provides> changes.
851
852The C<version> option is required. If it is omitted or if
853an unsupported version is given, then C<provides> will throw an error.
854
ca33f3bd 855=item dir
856
857Directory to search recursively for F<.pm> files. May not be specified with
858C<files>.
859
860=item files
861
862Array reference of files to examine. May not be specified with C<dir>.
863
864=item prefix
865
866String to prepend to the C<file> field of the resulting output. This defaults
867to F<lib>, which is the common case for most CPAN distributions with their
868F<.pm> files in F<lib>. This option ensures the META information has the
869correct relative path even when the C<dir> or C<files> arguments are
870absolute or have relative paths from a location other than the distribution
871root.
872
873=back
874
875For example, given C<dir> of 'lib' and C<prefix> of 'lib', the return value
876is a hashref of the form:
877
878 {
879 'Package::Name' => {
880 version => '0.123',
881 file => 'lib/Package/Name.pm'
882 },
883 'OtherPackage::Name' => ...
884 }
885
6290f67c 886=item C<< package_versions_from_directory($dir, \@files?) >>
2c11e51d 887
888Scans C<$dir> for .pm files (unless C<@files> is given, in which case looks
889for those files in C<$dir> - and reads each file for packages and versions,
890returning a hashref of the form:
5ac756c6 891
2c11e51d 892 {
893 'Package::Name' => {
894 version => '0.123',
895 file => 'Package/Name.pm'
896 },
897 'OtherPackage::Name' => ...
898 }
899
ca33f3bd 900The C<DB> and C<main> packages are always omitted, as are any "private"
901packages that have leading underscores in the namespace (e.g.
902C<Foo::_private>)
903
904Note that the file path is relative to C<$dir> if that is specified.
905This B<must not> be used directly for CPAN META C<provides>. See
906the C<provides> method instead.
907
6290f67c 908=item C<< log_info (internal) >>
2c11e51d 909
910Used internally to perform logging; imported from Log::Contextual if
911Log::Contextual has already been loaded, otherwise simply calls warn.
912
913=back
5ac756c6 914
6290f67c 915=head2 Object methods
916
917=over 4
918
919=item C<< name() >>
920
921Returns the name of the package represented by this module. If there
922are more than one packages, it makes a best guess based on the
923filename. If it's a script (i.e. not a *.pm) the package name is
924'main'.
925
926=item C<< version($package) >>
927
928Returns the version as defined by the $VERSION variable for the
929package as returned by the C<name> method if no arguments are
930given. If given the name of a package it will attempt to return the
931version of that package if it is specified in the file.
932
933=item C<< filename() >>
934
935Returns the absolute path to the file.
936
937=item C<< packages_inside() >>
938
1f67ffd7 939Returns a list of packages. Note: this is a raw list of packages
940discovered (or assumed, in the case of C<main>). It is not
941filtered for C<DB>, C<main> or private packages the way the
942C<provides> method does.
6290f67c 943
944=item C<< pod_inside() >>
945
946Returns a list of POD sections.
947
948=item C<< contains_pod() >>
949
950Returns true if there is any POD in the file.
951
952=item C<< pod($section) >>
953
954Returns the POD data in the given section.
955
956=back
957
5ac756c6 958=head1 AUTHOR
959
6290f67c 960Original code from Module::Build::ModuleInfo by Ken Williams
961<kwilliams@cpan.org>, Randy W. Sims <RandyS@ThePierianSpring.org>
5ac756c6 962
2c11e51d 963Released as Module::Metadata by Matt S Trout (mst) <mst@shadowcat.co.uk> with
6290f67c 964assistance from David Golden (xdg) <dagolden@cpan.org>.
5ac756c6 965
4c401e3f 966=head1 COPYRIGHT & LICENSE
5ac756c6 967
6290f67c 968Original code Copyright (c) 2001-2011 Ken Williams.
969Additional code Copyright (c) 2010-2011 Matt Trout and David Golden.
970All rights reserved.
5ac756c6 971
972This library is free software; you can redistribute it and/or
973modify it under the same terms as Perl itself.
974
5ac756c6 975=cut
976