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