1 # -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*-
2 # vim:ts=8:sw=2:et:sta:sts=2
3 package Module::Metadata;
5 # Adapted from Perl-licensed code originally distributed with
6 # Module-Build by Ken Williams
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).
13 use vars qw($VERSION $V_CLASS);
14 $VERSION = '1.000010';
15 $VERSION = eval $VERSION;
23 unless (eval { version->VERSION(0.87) }) {
24 require version::fallback;
25 version::fallback->VERSION(0.87);
26 version::fallback->import;
27 $V_CLASS = 'version::fallback';
31 if ($INC{'Log/Contextual.pm'}) {
32 Log::Contextual->import('log_info');
34 *log_info = sub (&) { warn $_[0]->() };
37 use File::Find qw(find);
39 my $V_NUM_REGEXP = qr{v?[0-9._]+}; # crudely, a v-string or decimal
41 my $PKG_REGEXP = qr{ # match a package declaration
42 ^[\s\{;]* # intro chars on a line
43 package # the word 'package'
45 ([\w:]+) # a package name
46 \s* # optional whitespace
47 ($V_NUM_REGEXP)? # optional version number
48 \s* # optional whitesapce
49 [;\{] # semicolon line terminator or block start (since 5.16)
52 my $VARNAME_REGEXP = qr{ # match fully-qualified VERSION name
53 ([\$*]) # sigil - $ or *
55 ( # optional leading package name
56 (?:::|\')? # possibly starting like just :: (Ì la $::VERSION)
57 (?:\w+(?:::|\'))* # Foo::Bar:: ...
63 my $VERS_REGEXP = qr{ # match a VERSION definition
65 \(\s*$VARNAME_REGEXP\s*\) # with parens
67 $VARNAME_REGEXP # without parens
70 =[^=~] # = but not ==, nor =~
73 my $PODSECT_REGEXP = qr{
74 ^=(cut|pod|head[1-4]|over|item|back|begin|end|for|encoding)\b
79 my $filename = File::Spec->rel2abs( shift );
81 return undef unless defined( $filename ) && -f $filename;
82 return $class->_init(undef, $filename, @_);
89 return undef unless defined($handle) && defined($filename);
90 $filename = File::Spec->rel2abs( $filename );
92 return $class->_init(undef, $filename, @_, handle => $handle);
102 $props{inc} ||= \@INC;
103 my $filename = $class->find_module_by_name( $module, $props{inc} );
104 return undef unless defined( $filename ) && -f $filename;
105 return $class->_init($module, $filename, %props);
110 my $compare_versions = sub {
111 my ($v1, $op, $v2) = @_;
112 $v1 = $V_CLASS->new($v1)
113 unless UNIVERSAL::isa($v1,$V_CLASS);
115 my $eval_str = "\$v1 $op \$v2";
116 my $result = eval $eval_str;
117 log_info { "error comparing versions: '$eval_str' $@" } if $@;
122 my $normalize_version = sub {
124 if ( $version =~ /[=<>!,]/ ) { # logic, not just version
125 # take as is without modification
127 elsif ( ref $version eq $V_CLASS ) { # version objects
128 $version = $version->is_qv ? $version->normal : $version->stringify;
130 elsif ( $version =~ /^[^v][^.]*\.[^.]+\./ ) { # no leading v, multiple dots
131 # normalize string tuples without "v": "1.2.3" -> "v1.2.3"
132 $version = "v$version";
140 # separate out some of the conflict resolution logic
142 my $resolve_module_versions = sub {
143 my $packages = shift;
145 my( $file, $version );
147 foreach my $p ( @$packages ) {
148 if ( defined( $p->{version} ) ) {
149 if ( defined( $version ) ) {
150 if ( $compare_versions->( $version, '!=', $p->{version} ) ) {
151 $err .= " $p->{file} ($p->{version})\n";
153 # same version declared multiple times, ignore
157 $version = $p->{version};
160 $file ||= $p->{file} if defined( $p->{file} );
164 $err = " $file ($version)\n" . $err;
179 croak "provides() requires key/value pairs \n" if @_ % 2;
182 croak "provides() takes only one of 'dir' or 'files'\n"
183 if $args{dir} && $args{files};
185 croak "provides() requires a 'version' argument"
186 unless defined $args{version};
188 croak "provides() does not support version '$args{version}' metadata"
189 unless grep { $args{version} eq $_ } qw/1.4 2/;
191 $args{prefix} = 'lib' unless defined $args{prefix};
195 $p = $class->package_versions_from_directory($args{dir});
198 croak "provides() requires 'files' to be an array reference\n"
199 unless ref $args{files} eq 'ARRAY';
200 $p = $class->package_versions_from_directory($args{files});
203 # Now, fix up files with prefix
204 if ( length $args{prefix} ) { # check in case disabled with q{}
205 $args{prefix} =~ s{/$}{};
206 for my $v ( values %$p ) {
207 $v->{file} = "$args{prefix}/$v->{file}";
214 sub package_versions_from_directory {
215 my ( $class, $dir, $files ) = @_;
224 push @files, $_ if -f $_ && /\.pm$/;
230 # First, we enumerate all packages & versions,
231 # separating into primary & alternative candidates
233 foreach my $file (@files) {
234 my $mapped_filename = File::Spec::Unix->abs2rel( $file, $dir );
235 my @path = split( /\//, $mapped_filename );
236 (my $prime_package = join( '::', @path )) =~ s/\.pm$//;
238 my $pm_info = $class->new_from_file( $file );
240 foreach my $package ( $pm_info->packages_inside ) {
241 next if $package eq 'main'; # main can appear numerous times, ignore
242 next if $package eq 'DB'; # special debugging package, ignore
243 next if grep /^_/, split( /::/, $package ); # private package, ignore
245 my $version = $pm_info->version( $package );
247 $prime_package = $package if lc($prime_package) eq lc($package);
248 if ( $package eq $prime_package ) {
249 if ( exists( $prime{$package} ) ) {
250 croak "Unexpected conflict in '$package'; multiple versions found.\n";
252 $mapped_filename = "$package.pm" if lc("$package.pm") eq lc($mapped_filename);
253 $prime{$package}{file} = $mapped_filename;
254 $prime{$package}{version} = $version if defined( $version );
257 push( @{$alt{$package}}, {
258 file => $mapped_filename,
265 # Then we iterate over all the packages found above, identifying conflicts
266 # and selecting the "best" candidate for recording the file & version
268 foreach my $package ( keys( %alt ) ) {
269 my $result = $resolve_module_versions->( $alt{$package} );
271 if ( exists( $prime{$package} ) ) { # primary package selected
273 if ( $result->{err} ) {
274 # Use the selected primary package, but there are conflicting
275 # errors among multiple alternative packages that need to be
278 "Found conflicting versions for package '$package'\n" .
279 " $prime{$package}{file} ($prime{$package}{version})\n" .
283 } elsif ( defined( $result->{version} ) ) {
284 # There is a primary package selected, and exactly one
285 # alternative package
287 if ( exists( $prime{$package}{version} ) &&
288 defined( $prime{$package}{version} ) ) {
289 # Unless the version of the primary package agrees with the
290 # version of the alternative package, report a conflict
291 if ( $compare_versions->(
292 $prime{$package}{version}, '!=', $result->{version}
297 "Found conflicting versions for package '$package'\n" .
298 " $prime{$package}{file} ($prime{$package}{version})\n" .
299 " $result->{file} ($result->{version})\n"
304 # The prime package selected has no version so, we choose to
305 # use any alternative package that does have a version
306 $prime{$package}{file} = $result->{file};
307 $prime{$package}{version} = $result->{version};
311 # no alt package found with a version, but we have a prime
312 # package so we use it whether it has a version or not
315 } else { # No primary package was selected, use the best alternative
317 if ( $result->{err} ) {
319 "Found conflicting versions for package '$package'\n" .
324 # Despite possible conflicting versions, we choose to record
325 # something rather than nothing
326 $prime{$package}{file} = $result->{file};
327 $prime{$package}{version} = $result->{version}
328 if defined( $result->{version} );
332 # Normalize versions. Can't use exists() here because of bug in YAML::Node.
333 # XXX "bug in YAML::Node" comment seems irrelvant -- dagolden, 2009-05-18
334 for (grep defined $_->{version}, values %prime) {
335 $_->{version} = $normalize_version->( $_->{version} );
346 my $filename = shift;
349 my $handle = delete $props{handle};
350 my( %valid_props, @valid_props );
351 @valid_props = qw( collect_pod inc );
352 @valid_props{@valid_props} = delete( @props{@valid_props} );
353 warn "Unknown properties: @{[keys %props]}\n" if scalar( %props );
357 filename => $filename,
368 my $self = bless(\%data, $class);
371 $self->_parse_fh($handle);
374 $self->_parse_file();
377 unless($self->{module} and length($self->{module})) {
378 my ($v, $d, $f) = File::Spec->splitpath($self->{filename});
381 my @candidates = grep /$f$/, @{$self->{packages}};
382 $self->{module} = shift(@candidates); # punt
385 if(grep /main/, @{$self->{packages}}) {
386 $self->{module} = 'main';
389 $self->{module} = $self->{packages}[0] || '';
394 $self->{version} = $self->{versions}{$self->{module}}
395 if defined( $self->{module} );
401 sub _do_find_module {
403 my $module = shift || croak 'find_module_by_name() requires a package name';
404 my $dirs = shift || \@INC;
406 my $file = File::Spec->catfile(split( /::/, $module));
407 foreach my $dir ( @$dirs ) {
408 my $testfile = File::Spec->catfile($dir, $file);
409 return [ File::Spec->rel2abs( $testfile ), $dir ]
410 if -e $testfile and !-d _; # For stuff like ExtUtils::xsubpp
411 return [ File::Spec->rel2abs( "$testfile.pm" ), $dir ]
412 if -e "$testfile.pm";
418 sub find_module_by_name {
419 my $found = shift()->_do_find_module(@_) or return;
424 sub find_module_dir_by_name {
425 my $found = shift()->_do_find_module(@_) or return;
430 # given a line of perl code, attempt to parse it if it looks like a
431 # $VERSION assignment, returning sigil, full name, & package name
432 sub _parse_version_expression {
436 my( $sig, $var, $pkg );
437 if ( $line =~ /$VERS_REGEXP/o ) {
438 ( $sig, $var, $pkg ) = $2 ? ( $1, $2, $3 ) : ( $4, $5, $6 );
440 $pkg = ($pkg eq '::') ? 'main' : $pkg;
445 return ( $sig, $var, $pkg );
451 my $filename = $self->{filename};
452 my $fh = IO::File->new( $filename )
453 or croak( "Can't open '$filename': $!" );
455 $self->_handle_bom($fh, $filename);
457 $self->_parse_fh($fh);
460 # Look for a UTF-8/UTF-16BE/UTF-16LE BOM at the beginning of the stream.
461 # If there's one, then skip it and set the :encoding layer appropriately.
463 my ($self, $fh, $filename) = @_;
465 my $pos = $fh->getpos;
466 return unless defined $pos;
469 my $count = $fh->read( $buf, length $buf );
470 return unless defined $count and $count >= 2;
473 if ( $buf eq "\x{FE}\x{FF}" ) {
474 $encoding = 'UTF-16BE';
475 } elsif ( $buf eq "\x{FF}\x{FE}" ) {
476 $encoding = 'UTF-16LE';
477 } elsif ( $buf eq "\x{EF}\x{BB}" ) {
479 $count = $fh->read( $buf, length $buf );
480 if ( defined $count and $count >= 1 and $buf eq "\x{BF}" ) {
485 if ( defined $encoding ) {
486 if ( "$]" >= 5.008 ) {
487 # $fh->binmode requires perl 5.10
488 binmode( $fh, ":encoding($encoding)" );
492 or croak( sprintf "Can't reset position to the top of '$filename'" );
499 my ($self, $fh) = @_;
501 my( $in_pod, $seen_end, $need_vers ) = ( 0, 0, 0 );
502 my( @pkgs, %vers, %pod, @pod );
507 while (defined( my $line = <$fh> )) {
513 if ( $line =~ /$PODSECT_REGEXP/o ) {
514 $is_cut = $1 eq 'cut';
518 # Would be nice if we could also check $in_string or something too
519 last if !$in_pod && $line =~ /^__(?:DATA|END)__$/;
523 if ( $line =~ /^=head[1-4]\s+(.+)\s*$/ ) {
525 if ( $self->{collect_pod} && length( $pod_data ) ) {
526 $pod{$pod_sect} = $pod_data;
531 } elsif ( $self->{collect_pod} ) {
532 $pod_data .= "$line\n";
536 } elsif ( $is_cut ) {
538 if ( $self->{collect_pod} && length( $pod_data ) ) {
539 $pod{$pod_sect} = $pod_data;
546 # Skip comments in code
547 next if $line =~ /^\s*#/;
549 # parse $line to see if it's a $VERSION declaration
550 my( $vers_sig, $vers_fullname, $vers_pkg ) =
552 ? $self->_parse_version_expression( $line )
555 if ( $line =~ /$PKG_REGEXP/o ) {
557 push( @pkgs, $pkg ) unless grep( $pkg eq $_, @pkgs );
558 $vers{$pkg} = $2 unless exists( $vers{$pkg} );
559 $need_vers = defined $2 ? 0 : 1;
561 # VERSION defined with full package spec, i.e. $Module::VERSION
562 } elsif ( $vers_fullname && $vers_pkg ) {
563 push( @pkgs, $vers_pkg ) unless grep( $vers_pkg eq $_, @pkgs );
564 $need_vers = 0 if $vers_pkg eq $pkg;
566 unless ( defined $vers{$vers_pkg} && length $vers{$vers_pkg} ) {
568 $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
570 # Warn unless the user is using the "$VERSION = eval
571 # $VERSION" idiom (though there are probably other idioms
572 # that we should watch out for...)
573 warn <<"EOM" unless $line =~ /=\s*eval/;
574 Package '$vers_pkg' already declared with version '$vers{$vers_pkg}',
575 ignoring subsequent declaration on line $line_num.
579 # first non-comment line in undeclared package main is VERSION
580 } elsif ( !exists($vers{main}) && $pkg eq 'main' && $vers_fullname ) {
583 $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
585 push( @pkgs, 'main' );
587 # first non-comment line in undeclared package defines package main
588 } elsif ( !exists($vers{main}) && $pkg eq 'main' && $line =~ /\w+/ ) {
591 push( @pkgs, 'main' );
593 # only keep if this is the first $VERSION seen
594 } elsif ( $vers_fullname && $need_vers ) {
597 $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
600 unless ( defined $vers{$pkg} && length $vers{$pkg} ) {
604 Package '$pkg' already declared with version '$vers{$pkg}'
605 ignoring new version '$v' on line $line_num.
615 if ( $self->{collect_pod} && length($pod_data) ) {
616 $pod{$pod_sect} = $pod_data;
619 $self->{versions} = \%vers;
620 $self->{packages} = \@pkgs;
621 $self->{pod} = \%pod;
622 $self->{pod_headings} = \@pod;
627 sub _evaluate_version_line {
629 my( $sigil, $var, $line ) = @_;
631 # Some of this code came from the ExtUtils:: hierarchy.
633 # We compile into $vsub because 'use version' would cause
634 # compiletime/runtime issues with local()
636 $pn++; # everybody gets their own package
637 my $eval = qq{BEGIN { q# Hide from _packages_inside()
638 #; package Module::Metadata::_version::p$pn;
651 # Try to get the $VERSION
653 # some modules say $VERSION = $Foo::Bar::VERSION, but Foo::Bar isn't
654 # installed, so we need to hunt in ./lib for it
655 if ( $@ =~ /Can't locate/ && -d 'lib' ) {
656 local @INC = ('lib',@INC);
659 warn "Error evaling version line '$eval' in $self->{filename}: $@\n"
661 (ref($vsub) eq 'CODE') or
662 croak "failed to build version sub for $self->{filename}";
663 my $result = eval { $vsub->() };
664 croak "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n"
667 # Upgrade it into a version object
668 my $version = eval { _dwim_version($result) };
670 croak "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n"
671 unless defined $version; # "0" is OK!
677 # Try to DWIM when things fail the lax version test in obvious ways
680 # Best case, it just works
681 sub { return shift },
683 # If we still don't have a version, try stripping any
684 # trailing junk that is prohibited by lax rules
687 $v =~ s{([0-9])[a-z-].*$}{$1}i; # 1.23-alpha or 1.23b
691 # Activestate apparently creates custom versions like '1.23_45_01', which
692 # cause version.pm to think it's an invalid alpha. So check for that
696 my $num_dots = () = $v =~ m{(\.)}g;
697 my $num_unders = () = $v =~ m{(_)}g;
698 my $leading_v = substr($v,0,1) eq 'v';
699 if ( ! $leading_v && $num_dots < 2 && $num_unders > 1 ) {
701 $num_unders = () = $v =~ m{(_)}g;
706 # Worst case, try numifying it like we would have before version objects
709 no warnings 'numeric';
716 my ($result) = shift;
718 return $result if ref($result) eq $V_CLASS;
720 my ($version, $error);
721 for my $f (@version_prep) {
722 $result = $f->($result);
723 $version = eval { $V_CLASS->new($result) };
724 $error ||= $@ if $@; # capture first failure
725 last if defined $version;
728 croak $error unless defined $version;
734 ############################################################
737 sub name { $_[0]->{module} }
739 sub filename { $_[0]->{filename} }
740 sub packages_inside { @{$_[0]->{packages}} }
741 sub pod_inside { @{$_[0]->{pod_headings}} }
742 sub contains_pod { $#{$_[0]->{pod_headings}} }
746 my $mod = shift || $self->{module};
748 if ( defined( $mod ) && length( $mod ) &&
749 exists( $self->{versions}{$mod} ) ) {
750 return $self->{versions}{$mod};
759 if ( defined( $sect ) && length( $sect ) &&
760 exists( $self->{pod}{$sect} ) ) {
761 return $self->{pod}{$sect};
771 Module::Metadata - Gather package and POD information from perl module files
775 use Module::Metadata;
777 # information about a .pm file
778 my $info = Module::Metadata->new_from_file( $file );
779 my $version = $info->version;
781 # CPAN META 'provides' field for .pm files in a directory
782 my $provides = Module::Metadata->provides(
783 dir => 'lib', version => 2
788 This module provides a standard way to gather metadata about a .pm file
789 without executing unsafe code.
797 =item C<< new_from_file($filename, collect_pod => 1) >>
799 Constructs a C<Module::Metadata> object given the path to a file. Returns
800 undef if the filename does not exist.
802 C<collect_pod> is a optional boolean argument that determines whether POD
803 data is collected and stored for reference. POD data is not collected by
804 default. POD headings are always collected.
806 If the file begins by an UTF-8, UTF-16BE or UTF-16LE byte-order mark, then
807 it is skipped before processing, and the content of the file is also decoded
808 appropriately starting from perl 5.8.
810 =item C<< new_from_handle($handle, $filename, collect_pod => 1) >>
812 This works just like C<new_from_file>, except that a handle can be provided
813 as the first argument.
815 Note that there is no validation to confirm that the handle is a handle or
816 something that can act like one. Passing something that isn't a handle will
817 cause a exception when trying to read from it. The C<filename> argument is
818 mandatory or undef will be returned.
820 You are responsible for setting the decoding layers on C<$handle> if
823 =item C<< new_from_module($module, collect_pod => 1, inc => \@dirs) >>
825 Constructs a C<Module::Metadata> object given a module or package name.
826 Returns undef if the module cannot be found.
828 In addition to accepting the C<collect_pod> argument as described above,
829 this method accepts a C<inc> argument which is a reference to an array of
830 directories to search for the module. If none are given, the default is
833 If the file that contains the module begins by an UTF-8, UTF-16BE or
834 UTF-16LE byte-order mark, then it is skipped before processing, and the
835 content of the file is also decoded appropriately starting from perl 5.8.
837 =item C<< find_module_by_name($module, \@dirs) >>
839 Returns the path to a module given the module or package name. A list
840 of directories can be passed in as an optional parameter, otherwise
843 Can be called as either an object or a class method.
845 =item C<< find_module_dir_by_name($module, \@dirs) >>
847 Returns the entry in C<@dirs> (or C<@INC> by default) that contains
848 the module C<$module>. A list of directories can be passed in as an
849 optional parameter, otherwise @INC is searched.
851 Can be called as either an object or a class method.
853 =item C<< provides( %options ) >>
855 This is a convenience wrapper around C<package_versions_from_directory>
856 to generate a CPAN META C<provides> data structure. It takes key/value
857 pairs. Valid option keys include:
861 =item version B<(required)>
863 Specifies which version of the L<CPAN::Meta::Spec> should be used as
864 the format of the C<provides> output. Currently only '1.4' and '2'
865 are supported (and their format is identical). This may change in
866 the future as the definition of C<provides> changes.
868 The C<version> option is required. If it is omitted or if
869 an unsupported version is given, then C<provides> will throw an error.
873 Directory to search recursively for F<.pm> files. May not be specified with
878 Array reference of files to examine. May not be specified with C<dir>.
882 String to prepend to the C<file> field of the resulting output. This defaults
883 to F<lib>, which is the common case for most CPAN distributions with their
884 F<.pm> files in F<lib>. This option ensures the META information has the
885 correct relative path even when the C<dir> or C<files> arguments are
886 absolute or have relative paths from a location other than the distribution
891 For example, given C<dir> of 'lib' and C<prefix> of 'lib', the return value
892 is a hashref of the form:
897 file => 'lib/Package/Name.pm'
899 'OtherPackage::Name' => ...
902 =item C<< package_versions_from_directory($dir, \@files?) >>
904 Scans C<$dir> for .pm files (unless C<@files> is given, in which case looks
905 for those files in C<$dir> - and reads each file for packages and versions,
906 returning a hashref of the form:
911 file => 'Package/Name.pm'
913 'OtherPackage::Name' => ...
916 The C<DB> and C<main> packages are always omitted, as are any "private"
917 packages that have leading underscores in the namespace (e.g.
920 Note that the file path is relative to C<$dir> if that is specified.
921 This B<must not> be used directly for CPAN META C<provides>. See
922 the C<provides> method instead.
924 =item C<< log_info (internal) >>
926 Used internally to perform logging; imported from Log::Contextual if
927 Log::Contextual has already been loaded, otherwise simply calls warn.
931 =head2 Object methods
937 Returns the name of the package represented by this module. If there
938 are more than one packages, it makes a best guess based on the
939 filename. If it's a script (i.e. not a *.pm) the package name is
942 =item C<< version($package) >>
944 Returns the version as defined by the $VERSION variable for the
945 package as returned by the C<name> method if no arguments are
946 given. If given the name of a package it will attempt to return the
947 version of that package if it is specified in the file.
949 =item C<< filename() >>
951 Returns the absolute path to the file.
953 =item C<< packages_inside() >>
955 Returns a list of packages. Note: this is a raw list of packages
956 discovered (or assumed, in the case of C<main>). It is not
957 filtered for C<DB>, C<main> or private packages the way the
958 C<provides> method does.
960 =item C<< pod_inside() >>
962 Returns a list of POD sections.
964 =item C<< contains_pod() >>
966 Returns true if there is any POD in the file.
968 =item C<< pod($section) >>
970 Returns the POD data in the given section.
976 Original code from Module::Build::ModuleInfo by Ken Williams
977 <kwilliams@cpan.org>, Randy W. Sims <RandyS@ThePierianSpring.org>
979 Released as Module::Metadata by Matt S Trout (mst) <mst@shadowcat.co.uk> with
980 assistance from David Golden (xdg) <dagolden@cpan.org>.
982 =head1 COPYRIGHT & LICENSE
984 Original code Copyright (c) 2001-2011 Ken Williams.
985 Additional code Copyright (c) 2010-2011 Matt Trout and David Golden.
988 This library is free software; you can redistribute it and/or
989 modify it under the same terms as Perl itself.