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