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