diff --git a/perl/bin/instmodsh.bat b/perl/bin/instmodsh.bat index d53bc30..12af32b 100644 --- a/perl/bin/instmodsh.bat +++ b/perl/bin/instmodsh.bat @@ -10,11 +10,8 @@ if %errorlevel% == 9009 echo You do not have Perl in your PATH. if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul goto endofperl @rem '; -#!perl -#line 15 - eval 'exec C:\strawberry\perl\bin\perl.exe -S $0 ${1+"$@"}' - if $running_under_some_shell; #!/usr/bin/perl -w +#line 15 use strict; use IO::File; diff --git a/perl/lib/ExtUtils/Command/MM.pm b/perl/lib/ExtUtils/Command/MM.pm index f9b474d..25fa5f5 100644 --- a/perl/lib/ExtUtils/Command/MM.pm +++ b/perl/lib/ExtUtils/Command/MM.pm @@ -10,7 +10,7 @@ our @ISA = qw(Exporter); our @EXPORT = qw(test_harness pod2man perllocal_install uninstall warn_if_old_packlist); -our $VERSION = '6.56'; +our $VERSION = '6.62'; my $Is_VMS = $^O eq 'VMS'; diff --git a/perl/lib/ExtUtils/Liblist.pm b/perl/lib/ExtUtils/Liblist.pm index ea4dac4..c560cb5 100644 --- a/perl/lib/ExtUtils/Liblist.pm +++ b/perl/lib/ExtUtils/Liblist.pm @@ -2,7 +2,7 @@ package ExtUtils::Liblist; use strict; -our $VERSION = '6.56'; +our $VERSION = '6.62'; use File::Spec; require ExtUtils::Liblist::Kid; diff --git a/perl/lib/ExtUtils/Liblist/Kid.pm b/perl/lib/ExtUtils/Liblist/Kid.pm index b807e97..cc1471f 100644 --- a/perl/lib/ExtUtils/Liblist/Kid.pm +++ b/perl/lib/ExtUtils/Liblist/Kid.pm @@ -6,211 +6,241 @@ package ExtUtils::Liblist::Kid; # $self is not a Makemaker. use 5.006; + # Broken out of MakeMaker from version 4.11 use strict; -our $VERSION = 6.56; +use warnings; +our $VERSION = '6.62'; -use Config; +use ExtUtils::MakeMaker::Config; use Cwd 'cwd'; use File::Basename; use File::Spec; sub ext { - if ($^O eq 'VMS') { return &_vms_ext; } - elsif($^O eq 'MSWin32') { return &_win32_ext; } - else { return &_unix_os2_ext; } + if ( $^O eq 'VMS' ) { return &_vms_ext; } + elsif ( $^O eq 'MSWin32' ) { return &_win32_ext; } + else { return &_unix_os2_ext; } } sub _unix_os2_ext { - my($self,$potential_libs, $verbose, $give_libs) = @_; + my ( $self, $potential_libs, $verbose, $give_libs ) = @_; $verbose ||= 0; - if ($^O =~ 'os2' and $Config{perllibs}) { - # Dynamic libraries are not transitive, so we may need including - # the libraries linked against perl.dll again. + if ( $^O =~ 'os2' and $Config{perllibs} ) { + + # Dynamic libraries are not transitive, so we may need including + # the libraries linked against perl.dll again. - $potential_libs .= " " if $potential_libs; - $potential_libs .= $Config{perllibs}; + $potential_libs .= " " if $potential_libs; + $potential_libs .= $Config{perllibs}; } - return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs; + return ( "", "", "", "", ( $give_libs ? [] : () ) ) unless $potential_libs; warn "Potential libraries are '$potential_libs':\n" if $verbose; - my($so) = $Config{so}; - my($libs) = defined $Config{perllibs} ? $Config{perllibs} : $Config{libs}; + my ( $so ) = $Config{so}; + my ( $libs ) = defined $Config{perllibs} ? $Config{perllibs} : $Config{libs}; my $Config_libext = $Config{lib_ext} || ".a"; - + my $Config_dlext = $Config{dlext}; # compute $extralibs, $bsloadlibs and $ldloadlibs from # $potential_libs # this is a rewrite of Andy Dougherty's extliblist in perl - my(@searchpath); # from "-L/path" entries in $potential_libs - my(@libpath) = split " ", $Config{'libpth'}; - my(@ldloadlibs, @bsloadlibs, @extralibs, @ld_run_path, %ld_run_path_seen); - my(@libs, %libs_seen); - my($fullname, @fullname); - my($pwd) = cwd(); # from Cwd.pm - my($found) = 0; - - foreach my $thislib (split ' ', $potential_libs) { - - # Handle possible linker path arguments. - if ($thislib =~ s/^(-[LR]|-Wl,-R)//){ # save path flag type - my($ptype) = $1; - unless (-d $thislib){ - warn "$ptype$thislib ignored, directory does not exist\n" - if $verbose; - next; - } - my($rtype) = $ptype; - if (($ptype eq '-R') or ($ptype eq '-Wl,-R')) { - if ($Config{'lddlflags'} =~ /-Wl,-R/) { - $rtype = '-Wl,-R'; - } elsif ($Config{'lddlflags'} =~ /-R/) { - $rtype = '-R'; - } - } - unless (File::Spec->file_name_is_absolute($thislib)) { - warn "Warning: $ptype$thislib changed to $ptype$pwd/$thislib\n"; - $thislib = $self->catdir($pwd,$thislib); - } - push(@searchpath, $thislib); - push(@extralibs, "$ptype$thislib"); - push(@ldloadlibs, "$rtype$thislib"); - next; - } - - # Handle possible library arguments. - unless ($thislib =~ s/^-l//){ - warn "Unrecognized argument in LIBS ignored: '$thislib'\n"; - next; - } - - my($found_lib)=0; - foreach my $thispth (@searchpath, @libpath) { - - # Try to find the full name of the library. We need this to - # determine whether it's a dynamically-loadable library or not. - # This tends to be subject to various os-specific quirks. - # For gcc-2.6.2 on linux (March 1995), DLD can not load - # .sa libraries, with the exception of libm.sa, so we - # deliberately skip them. - if (@fullname = - $self->lsdir($thispth,"^\Qlib$thislib.$so.\E[0-9]+")){ - # Take care that libfoo.so.10 wins against libfoo.so.9. - # Compare two libraries to find the most recent version - # number. E.g. if you have libfoo.so.9.0.7 and - # libfoo.so.10.1, first convert all digits into two - # decimal places. Then we'll add ".00" to the shorter - # strings so that we're comparing strings of equal length - # Thus we'll compare libfoo.so.09.07.00 with - # libfoo.so.10.01.00. Some libraries might have letters - # in the version. We don't know what they mean, but will - # try to skip them gracefully -- we'll set any letter to - # '0'. Finally, sort in reverse so we can take the - # first element. - - #TODO: iterate through the directory instead of sorting - - $fullname = "$thispth/" . - (sort { my($ma) = $a; - my($mb) = $b; - $ma =~ tr/A-Za-z/0/s; - $ma =~ s/\b(\d)\b/0$1/g; - $mb =~ tr/A-Za-z/0/s; - $mb =~ s/\b(\d)\b/0$1/g; - while (length($ma) < length($mb)) { $ma .= ".00"; } - while (length($mb) < length($ma)) { $mb .= ".00"; } - # Comparison deliberately backwards - $mb cmp $ma;} @fullname)[0]; - } elsif (-f ($fullname="$thispth/lib$thislib.$so") - && (($Config{'dlsrc'} ne "dl_dld.xs") || ($thislib eq "m"))){ - } elsif (-f ($fullname="$thispth/lib${thislib}_s$Config_libext") - && ($Config{'archname'} !~ /RM\d\d\d-svr4/) - && ($thislib .= "_s") ){ # we must explicitly use _s version - } elsif (-f ($fullname="$thispth/lib$thislib$Config_libext")){ - } elsif (-f ($fullname="$thispth/$thislib$Config_libext")){ - } elsif (-f ($fullname="$thispth/lib$thislib.dll$Config_libext")){ - } elsif (-f ($fullname="$thispth/Slib$thislib$Config_libext")){ - } elsif ($^O eq 'dgux' - && -l ($fullname="$thispth/lib$thislib$Config_libext") - && readlink($fullname) =~ /^elink:/s) { - # Some of DG's libraries look like misconnected symbolic - # links, but development tools can follow them. (They - # look like this: - # - # libm.a -> elink:${SDE_PATH:-/usr}/sde/\ - # ${TARGET_BINARY_INTERFACE:-m88kdgux}/usr/lib/libm.a - # - # , the compilation tools expand the environment variables.) - } else { - warn "$thislib not found in $thispth\n" if $verbose; - next; - } - warn "'-l$thislib' found at $fullname\n" if $verbose; - push @libs, $fullname unless $libs_seen{$fullname}++; - $found++; - $found_lib++; - - # Now update library lists - - # what do we know about this library... - my $is_dyna = ($fullname !~ /\Q$Config_libext\E\z/); - my $in_perl = ($libs =~ /\B-l\Q${thislib}\E\b/s); + my ( @searchpath ); # from "-L/path" entries in $potential_libs + my ( @libpath ) = split " ", $Config{'libpth'}; + my ( @ldloadlibs, @bsloadlibs, @extralibs, @ld_run_path, %ld_run_path_seen ); + my ( @libs, %libs_seen ); + my ( $fullname, @fullname ); + my ( $pwd ) = cwd(); # from Cwd.pm + my ( $found ) = 0; + + foreach my $thislib ( split ' ', $potential_libs ) { + + # Handle possible linker path arguments. + if ( $thislib =~ s/^(-[LR]|-Wl,-R)// ) { # save path flag type + my ( $ptype ) = $1; + unless ( -d $thislib ) { + warn "$ptype$thislib ignored, directory does not exist\n" + if $verbose; + next; + } + my ( $rtype ) = $ptype; + if ( ( $ptype eq '-R' ) or ( $ptype eq '-Wl,-R' ) ) { + if ( $Config{'lddlflags'} =~ /-Wl,-R/ ) { + $rtype = '-Wl,-R'; + } + elsif ( $Config{'lddlflags'} =~ /-R/ ) { + $rtype = '-R'; + } + } + unless ( File::Spec->file_name_is_absolute( $thislib ) ) { + warn "Warning: $ptype$thislib changed to $ptype$pwd/$thislib\n"; + $thislib = $self->catdir( $pwd, $thislib ); + } + push( @searchpath, $thislib ); + push( @extralibs, "$ptype$thislib" ); + push( @ldloadlibs, "$rtype$thislib" ); + next; + } + + # Handle possible library arguments. + unless ( $thislib =~ s/^-l// ) { + warn "Unrecognized argument in LIBS ignored: '$thislib'\n"; + next; + } + + my ( $found_lib ) = 0; + foreach my $thispth ( @searchpath, @libpath ) { + + # Try to find the full name of the library. We need this to + # determine whether it's a dynamically-loadable library or not. + # This tends to be subject to various os-specific quirks. + # For gcc-2.6.2 on linux (March 1995), DLD can not load + # .sa libraries, with the exception of libm.sa, so we + # deliberately skip them. + if ( @fullname = $self->lsdir( $thispth, "^\Qlib$thislib.$so.\E[0-9]+" ) ) { + + # Take care that libfoo.so.10 wins against libfoo.so.9. + # Compare two libraries to find the most recent version + # number. E.g. if you have libfoo.so.9.0.7 and + # libfoo.so.10.1, first convert all digits into two + # decimal places. Then we'll add ".00" to the shorter + # strings so that we're comparing strings of equal length + # Thus we'll compare libfoo.so.09.07.00 with + # libfoo.so.10.01.00. Some libraries might have letters + # in the version. We don't know what they mean, but will + # try to skip them gracefully -- we'll set any letter to + # '0'. Finally, sort in reverse so we can take the + # first element. + + #TODO: iterate through the directory instead of sorting + + $fullname = "$thispth/" . ( + sort { + my ( $ma ) = $a; + my ( $mb ) = $b; + $ma =~ tr/A-Za-z/0/s; + $ma =~ s/\b(\d)\b/0$1/g; + $mb =~ tr/A-Za-z/0/s; + $mb =~ s/\b(\d)\b/0$1/g; + while ( length( $ma ) < length( $mb ) ) { $ma .= ".00"; } + while ( length( $mb ) < length( $ma ) ) { $mb .= ".00"; } + + # Comparison deliberately backwards + $mb cmp $ma; + } @fullname + )[0]; + } + elsif ( -f ( $fullname = "$thispth/lib$thislib.$so" ) + && ( ( $Config{'dlsrc'} ne "dl_dld.xs" ) || ( $thislib eq "m" ) ) ) + { + } + elsif (-f ( $fullname = "$thispth/lib${thislib}_s$Config_libext" ) + && ( $Config{'archname'} !~ /RM\d\d\d-svr4/ ) + && ( $thislib .= "_s" ) ) + { # we must explicitly use _s version + } + elsif ( -f ( $fullname = "$thispth/lib$thislib$Config_libext" ) ) { + } + elsif ( defined( $Config_dlext ) + && -f ( $fullname = "$thispth/lib$thislib.$Config_dlext" ) ) + { + } + elsif ( -f ( $fullname = "$thispth/$thislib$Config_libext" ) ) { + } + elsif ( -f ( $fullname = "$thispth/lib$thislib.dll$Config_libext" ) ) { + } + elsif ( -f ( $fullname = "$thispth/Slib$thislib$Config_libext" ) ) { + } + elsif ($^O eq 'dgux' + && -l ( $fullname = "$thispth/lib$thislib$Config_libext" ) + && readlink( $fullname ) =~ /^elink:/s ) + { + + # Some of DG's libraries look like misconnected symbolic + # links, but development tools can follow them. (They + # look like this: + # + # libm.a -> elink:${SDE_PATH:-/usr}/sde/\ + # ${TARGET_BINARY_INTERFACE:-m88kdgux}/usr/lib/libm.a + # + # , the compilation tools expand the environment variables.) + } + else { + warn "$thislib not found in $thispth\n" if $verbose; + next; + } + warn "'-l$thislib' found at $fullname\n" if $verbose; + push @libs, $fullname unless $libs_seen{$fullname}++; + $found++; + $found_lib++; + + # Now update library lists + + # what do we know about this library... + my $is_dyna = ( $fullname !~ /\Q$Config_libext\E\z/ ); + my $in_perl = ( $libs =~ /\B-l\Q${thislib}\E\b/s ); # include the path to the lib once in the dynamic linker path # but only if it is a dynamic lib and not in Perl itself - my($fullnamedir) = dirname($fullname); + my ( $fullnamedir ) = dirname( $fullname ); push @ld_run_path, $fullnamedir - if $is_dyna && !$in_perl && - !$ld_run_path_seen{$fullnamedir}++; - - # Do not add it into the list if it is already linked in - # with the main perl executable. - # We have to special-case the NeXT, because math and ndbm - # are both in libsys_s - unless ($in_perl || - ($Config{'osname'} eq 'next' && - ($thislib eq 'm' || $thislib eq 'ndbm')) ){ - push(@extralibs, "-l$thislib"); - } - - # We might be able to load this archive file dynamically - if ( ($Config{'dlsrc'} =~ /dl_next/ && $Config{'osvers'} lt '4_0') - || ($Config{'dlsrc'} =~ /dl_dld/) ) - { - # We push -l$thislib instead of $fullname because - # it avoids hardwiring a fixed path into the .bs file. - # Mkbootstrap will automatically add dl_findfile() to - # the .bs file if it sees a name in the -l format. - # USE THIS, when dl_findfile() is fixed: - # push(@bsloadlibs, "-l$thislib"); - # OLD USE WAS while checking results against old_extliblist - push(@bsloadlibs, "$fullname"); - } else { - if ($is_dyna){ + if $is_dyna + && !$in_perl + && !$ld_run_path_seen{$fullnamedir}++; + + # Do not add it into the list if it is already linked in + # with the main perl executable. + # We have to special-case the NeXT, because math and ndbm + # are both in libsys_s + unless ( + $in_perl + || ( $Config{'osname'} eq 'next' + && ( $thislib eq 'm' || $thislib eq 'ndbm' ) ) + ) + { + push( @extralibs, "-l$thislib" ); + } + + # We might be able to load this archive file dynamically + if ( ( $Config{'dlsrc'} =~ /dl_next/ && $Config{'osvers'} lt '4_0' ) + || ( $Config{'dlsrc'} =~ /dl_dld/ ) ) + { + + # We push -l$thislib instead of $fullname because + # it avoids hardwiring a fixed path into the .bs file. + # Mkbootstrap will automatically add dl_findfile() to + # the .bs file if it sees a name in the -l format. + # USE THIS, when dl_findfile() is fixed: + # push(@bsloadlibs, "-l$thislib"); + # OLD USE WAS while checking results against old_extliblist + push( @bsloadlibs, "$fullname" ); + } + else { + if ( $is_dyna ) { + # For SunOS4, do not add in this shared library if # it is already linked in the main perl executable - push(@ldloadlibs, "-l$thislib") - unless ($in_perl and $^O eq 'sunos'); - } else { - push(@ldloadlibs, "-l$thislib"); - } - } - last; # found one here so don't bother looking further - } - warn "Note (probably harmless): " - ."No library found for -l$thislib\n" - unless $found_lib>0; + push( @ldloadlibs, "-l$thislib" ) + unless ( $in_perl and $^O eq 'sunos' ); + } + else { + push( @ldloadlibs, "-l$thislib" ); + } + } + last; # found one here so don't bother looking further + } + warn "Note (probably harmless): " . "No library found for -l$thislib\n" + unless $found_lib > 0; } - unless( $found ) { - return ('','','','', ($give_libs ? \@libs : ())); + unless ( $found ) { + return ( '', '', '', '', ( $give_libs ? \@libs : () ) ); } else { - return ("@extralibs", "@bsloadlibs", "@ldloadlibs", - join(":",@ld_run_path), ($give_libs ? \@libs : ())); + return ( "@extralibs", "@bsloadlibs", "@ldloadlibs", join( ":", @ld_run_path ), ( $give_libs ? \@libs : () ) ); } } @@ -218,329 +248,378 @@ sub _win32_ext { require Text::ParseWords; - my($self, $potential_libs, $verbose, $give_libs) = @_; + my ( $self, $potential_libs, $verbose, $give_libs ) = @_; $verbose ||= 0; # If user did not supply a list, we punt. # (caller should probably use the list in $Config{libs}) - return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs; - - my $cc = $Config{cc}; - my $VC = $cc =~ /^cl/i; - my $BC = $cc =~ /^bcc/i; - my $GC = $cc =~ /^gcc/i; - my $so = $Config{'so'}; - my $libs = $Config{'perllibs'}; - my $libpth = $Config{'libpth'}; - my $libext = $Config{'lib_ext'} || ".lib"; - my(@libs, %libs_seen); - - if ($libs and $potential_libs !~ /:nodefault/i) { - # If Config.pm defines a set of default libs, we always - # tack them on to the user-supplied list, unless the user - # specified :nodefault - - $potential_libs .= " " if $potential_libs; - $potential_libs .= $libs; - } - warn "Potential libraries are '$potential_libs':\n" if $verbose; + return ( "", "", "", "", ( $give_libs ? [] : () ) ) unless $potential_libs; - # normalize to forward slashes - $libpth =~ s,\\,/,g; - $potential_libs =~ s,\\,/,g; + # TODO: make this use MM_Win32.pm's compiler detection + my %libs_seen; + my @extralibs; + my $cc = $Config{cc} || ''; + my $VC = $cc =~ /\bcl\b/i; + my $GC = $cc =~ /\bgcc\b/i; - # compute $extralibs from $potential_libs + my $libext = _win32_lib_extensions(); + my @searchpath = ( '' ); # from "-L/path" entries in $potential_libs + my @libpath = _win32_default_search_paths( $VC, $GC ); + my $pwd = cwd(); # from Cwd.pm + my $search = 1; - my @searchpath; # from "-L/path" in $potential_libs - my @libpath = Text::ParseWords::quotewords('\s+', 0, $libpth); - my @extralibs; - my $pwd = cwd(); # from Cwd.pm - my $lib = ''; - my $found = 0; - my $search = 1; - my($fullname); + # compute @extralibs from $potential_libs + my @lib_search_list = _win32_make_lib_search_list( $potential_libs, $verbose ); + for ( @lib_search_list ) { - # add "$Config{installarchlib}/CORE" to default search path - push @libpath, "$Config{installarchlib}/CORE"; + my $thislib = $_; - if ($VC and exists $ENV{LIB} and $ENV{LIB}) { - push @libpath, split /;/, $ENV{LIB}; - } + # see if entry is a flag + if ( /^:\w+$/ ) { + $search = 0 if lc eq ':nosearch'; + $search = 1 if lc eq ':search'; + _debug( "Ignoring unknown flag '$thislib'\n", $verbose ) if !/^:(no)?(search|default)$/i; + next; + } + + # if searching is disabled, do compiler-specific translations + unless ( $search ) { + s/^-l(.+)$/$1.lib/ unless $GC; + s/^-L/-libpath:/ if $VC; + push( @extralibs, $_ ); + next; + } - foreach (Text::ParseWords::quotewords('\s+', 0, $potential_libs)){ + # handle possible linker path arguments + if ( s/^-L// and not -d ) { + _debug( "$thislib ignored, directory does not exist\n", $verbose ); + next; + } + elsif ( -d ) { + unless ( File::Spec->file_name_is_absolute( $_ ) ) { + warn "Warning: '$thislib' changed to '-L$pwd/$_'\n"; + $_ = $self->catdir( $pwd, $_ ); + } + push( @searchpath, $_ ); + next; + } - my $thislib = $_; + my @paths = ( @searchpath, @libpath ); + my ( $fullname, $path ) = _win32_search_file( $thislib, $libext, \@paths, $verbose, $GC ); - # see if entry is a flag - if (/^:\w+$/) { - $search = 0 if lc eq ':nosearch'; - $search = 1 if lc eq ':search'; - warn "Ignoring unknown flag '$thislib'\n" - if $verbose and !/^:(no)?(search|default)$/i; - next; - } - - # if searching is disabled, do compiler-specific translations - unless ($search) { - s/^-l(.+)$/$1.lib/ unless $GC; - s/^-L/-libpath:/ if $VC; - push(@extralibs, $_); - $found++; - next; - } - - # handle possible linker path arguments - if (s/^-L// and not -d) { - warn "$thislib ignored, directory does not exist\n" - if $verbose; - next; - } - elsif (-d) { - unless (File::Spec->file_name_is_absolute($_)) { - warn "Warning: '$thislib' changed to '-L$pwd/$_'\n"; - $_ = $self->catdir($pwd,$_); - } - push(@searchpath, $_); - next; - } - - # handle possible library arguments - if (s/^-l// and $GC and !/^lib/i) { - $_ = "lib$_"; - } - $_ .= $libext if !/\Q$libext\E$/i; - - my $secondpass = 0; - LOOKAGAIN: - - # look for the file itself - if (-f) { - warn "'$thislib' found as '$_'\n" if $verbose; - $found++; - push(@extralibs, $_); - next; - } - - my $found_lib = 0; - foreach my $thispth (@searchpath, @libpath){ - unless (-f ($fullname="$thispth\\$_")) { - warn "'$thislib' not found as '$fullname'\n" if $verbose; - next; - } - warn "'$thislib' found as '$fullname'\n" if $verbose; - $found++; - $found_lib++; - push(@extralibs, $fullname); - push @libs, $fullname unless $libs_seen{$fullname}++; - last; - } - - # do another pass with (or without) leading 'lib' if they used -l - if (!$found_lib and $thislib =~ /^-l/ and !$secondpass++) { - if ($GC) { - goto LOOKAGAIN if s/^lib//i; - } - elsif (!/^lib/i) { - $_ = "lib$_"; - goto LOOKAGAIN; - } - } - - # give up - warn "Note (probably harmless): " - ."No library found for $thislib\n" - unless $found_lib>0; + if ( !$fullname ) { + warn "Note (probably harmless): No library found for $thislib\n"; + next; + } + _debug( "'$thislib' found as '$fullname'\n", $verbose ); + push( @extralibs, $fullname ); + $libs_seen{$fullname} = 1 if $path; # why is this a special case? } - return ('','','','', ($give_libs ? \@libs : ())) unless $found; + my @libs = keys %libs_seen; + + return ( '', '', '', '', ( $give_libs ? \@libs : () ) ) unless @extralibs; # make sure paths with spaces are properly quoted - @extralibs = map { (/\s/ && !/^".*"$/) ? qq["$_"] : $_ } @extralibs; - @libs = map { (/\s/ && !/^".*"$/) ? qq["$_"] : $_ } @libs; - $lib = join(' ',@extralibs); + @extralibs = map { /\s/ ? qq["$_"] : $_ } @extralibs; + @libs = map { /\s/ ? qq["$_"] : $_ } @libs; + + my $lib = join( ' ', @extralibs ); # normalize back to backward slashes (to help braindead tools) # XXX this may break equally braindead GNU tools that don't understand # backslashes, either. Seems like one can't win here. Cursed be CP/M. $lib =~ s,/,\\,g; - warn "Result: $lib\n" if $verbose; - wantarray ? ($lib, '', $lib, '', ($give_libs ? \@libs : ())) : $lib; + _debug( "Result: $lib\n", $verbose ); + wantarray ? ( $lib, '', $lib, '', ( $give_libs ? \@libs : () ) ) : $lib; } +sub _win32_make_lib_search_list { + my ( $potential_libs, $verbose ) = @_; -sub _vms_ext { - my($self, $potential_libs, $verbose, $give_libs) = @_; - $verbose ||= 0; - - my(@crtls,$crtlstr); - @crtls = ( ($Config{'ldflags'} =~ m-/Debug-i ? $Config{'dbgprefix'} : '') - . 'PerlShr/Share' ); - push(@crtls, grep { not /\(/ } split /\s+/, $Config{'perllibs'}); - push(@crtls, grep { not /\(/ } split /\s+/, $Config{'libc'}); - # In general, we pass through the basic libraries from %Config unchanged. - # The one exception is that if we're building in the Perl source tree, and - # a library spec could be resolved via a logical name, we go to some trouble - # to insure that the copy in the local tree is used, rather than one to - # which a system-wide logical may point. - if ($self->{PERL_SRC}) { - my($locspec,$type); - foreach my $lib (@crtls) { - if (($locspec,$type) = $lib =~ m{^([\w\$-]+)(/\w+)?} and $locspec =~ /perl/i) { - if (lc $type eq '/share') { $locspec .= $Config{'exe_ext'}; } - elsif (lc $type eq '/library') { $locspec .= $Config{'lib_ext'}; } - else { $locspec .= $Config{'obj_ext'}; } - $locspec = $self->catfile($self->{PERL_SRC},$locspec); - $lib = "$locspec$type" if -e $locspec; - } - } - } - $crtlstr = @crtls ? join(' ',@crtls) : ''; - - unless ($potential_libs) { - warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose; - return ('', '', $crtlstr, '', ($give_libs ? [] : ())); - } - - my(%found,@fndlibs,$ldlib); - my $cwd = cwd(); - my($so,$lib_ext,$obj_ext) = @Config{'so','lib_ext','obj_ext'}; - # List of common Unix library names and their VMS equivalents - # (VMS equivalent of '' indicates that the library is automatically - # searched by the linker, and should be skipped here.) - my(@flibs, %libs_seen); - my %libmap = ( 'm' => '', 'f77' => '', 'F77' => '', 'V77' => '', 'c' => '', - 'malloc' => '', 'crypt' => '', 'resolv' => '', 'c_s' => '', - 'socket' => '', 'X11' => 'DECW$XLIBSHR', - 'Xt' => 'DECW$XTSHR', 'Xm' => 'DECW$XMLIBSHR', - 'Xmu' => 'DECW$XMULIBSHR'); - if ($Config{'vms_cc_type'} ne 'decc') { $libmap{'curses'} = 'VAXCCURSE'; } - - warn "Potential libraries are '$potential_libs'\n" if $verbose; - - # First, sort out directories and library names in the input - my(@dirs, @libs); - foreach my $lib (split ' ',$potential_libs) { - push(@dirs,$1), next if $lib =~ /^-L(.*)/; - push(@dirs,$lib), next if $lib =~ /[:>\]]$/; - push(@dirs,$lib), next if -d $lib; - push(@libs,$1), next if $lib =~ /^-l(.*)/; - push(@libs,$lib); - } - push(@dirs,split(' ',$Config{'libpth'})); - - # Now make sure we've got VMS-syntax absolute directory specs - # (We don't, however, check whether someone's hidden a relative - # path in a logical name.) - foreach my $dir (@dirs) { - unless (-d $dir) { - warn "Skipping nonexistent Directory $dir\n" if $verbose > 1; - $dir = ''; - next; - } - warn "Resolving directory $dir\n" if $verbose; - if (File::Spec->file_name_is_absolute($dir)) { - $dir = $self->fixpath($dir,1); - } - else { - $dir = $self->catdir($cwd,$dir); + # If Config.pm defines a set of default libs, we always + # tack them on to the user-supplied list, unless the user + # specified :nodefault + my $libs = $Config{'perllibs'}; + $potential_libs = join( ' ', $potential_libs, $libs ) if $libs and $potential_libs !~ /:nodefault/i; + _debug( "Potential libraries are '$potential_libs':\n", $verbose ); + + $potential_libs =~ s,\\,/,g; # normalize to forward slashes + + my @list = Text::ParseWords::quotewords( '\s+', 0, $potential_libs ); + + return @list; +} + +sub _win32_default_search_paths { + my ( $VC, $GC ) = @_; + + my $libpth = $Config{'libpth'} || ''; + $libpth =~ s,\\,/,g; # normalize to forward slashes + + my @libpath = Text::ParseWords::quotewords( '\s+', 0, $libpth ); + push @libpath, "$Config{installarchlib}/CORE"; # add "$Config{installarchlib}/CORE" to default search path + + push @libpath, split /;/, $ENV{LIB} if $VC and $ENV{LIB}; + push @libpath, split /;/, $ENV{LIBRARY_PATH} if $GC and $ENV{LIBRARY_PATH}; + + return @libpath; +} + +sub _win32_search_file { + my ( $thislib, $libext, $paths, $verbose, $GC ) = @_; + + my @file_list = _win32_build_file_list( $thislib, $GC, $libext ); + + for my $lib_file ( @file_list ) { + for my $path ( @{$paths} ) { + my $fullname = $lib_file; + $fullname = "$path\\$fullname" if $path; + + return ( $fullname, $path ) if -f $fullname; + + _debug( "'$thislib' not found as '$fullname'\n", $verbose ); + } } - } - @dirs = grep { length($_) } @dirs; - unshift(@dirs,''); # Check each $lib without additions first - - LIB: foreach my $lib (@libs) { - if (exists $libmap{$lib}) { - next unless length $libmap{$lib}; - $lib = $libmap{$lib}; + + return; +} + +sub _win32_build_file_list { + my ( $lib, $GC, $extensions ) = @_; + + my @pre_fixed = _win32_build_prefixed_list( $lib, $GC ); + return map _win32_attach_extensions( $_, $extensions ), @pre_fixed; +} + +sub _win32_build_prefixed_list { + my ( $lib, $GC ) = @_; + + return $lib if $lib !~ s/^-l//; + return $lib if $lib =~ /^lib/ and !$GC; + + ( my $no_prefix = $lib ) =~ s/^lib//i; + $lib = "lib$lib" if $no_prefix eq $lib; + + return ( $lib, $no_prefix ) if $GC; + return ( $no_prefix, $lib ); +} + +sub _win32_attach_extensions { + my ( $lib, $extensions ) = @_; + return map _win32_try_attach_extension( $lib, $_ ), @{$extensions}; +} + +sub _win32_try_attach_extension { + my ( $lib, $extension ) = @_; + + return $lib if $lib =~ /\Q$extension\E$/i; + return "$lib$extension"; +} + +sub _win32_lib_extensions { + my %extensions; + $extensions{ $Config{'lib_ext'} } = 1 if $Config{'lib_ext'}; + $extensions{".lib"} = 1; + return [ keys %extensions ]; +} + +sub _debug { + my ( $message, $verbose ) = @_; + return if !$verbose; + warn $message; + return; +} + +sub _vms_ext { + my ( $self, $potential_libs, $verbose, $give_libs ) = @_; + $verbose ||= 0; + + my ( @crtls, $crtlstr ); + @crtls = ( ( $Config{'ldflags'} =~ m-/Debug-i ? $Config{'dbgprefix'} : '' ) . 'PerlShr/Share' ); + push( @crtls, grep { not /\(/ } split /\s+/, $Config{'perllibs'} ); + push( @crtls, grep { not /\(/ } split /\s+/, $Config{'libc'} ); + + # In general, we pass through the basic libraries from %Config unchanged. + # The one exception is that if we're building in the Perl source tree, and + # a library spec could be resolved via a logical name, we go to some trouble + # to insure that the copy in the local tree is used, rather than one to + # which a system-wide logical may point. + if ( $self->{PERL_SRC} ) { + my ( $locspec, $type ); + foreach my $lib ( @crtls ) { + if ( ( $locspec, $type ) = $lib =~ m{^([\w\$-]+)(/\w+)?} and $locspec =~ /perl/i ) { + if ( lc $type eq '/share' ) { $locspec .= $Config{'exe_ext'}; } + elsif ( lc $type eq '/library' ) { $locspec .= $Config{'lib_ext'}; } + else { $locspec .= $Config{'obj_ext'}; } + $locspec = $self->catfile( $self->{PERL_SRC}, $locspec ); + $lib = "$locspec$type" if -e $locspec; + } + } } + $crtlstr = @crtls ? join( ' ', @crtls ) : ''; - my(@variants,$cand); - my($ctype) = ''; + unless ( $potential_libs ) { + warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose; + return ( '', '', $crtlstr, '', ( $give_libs ? [] : () ) ); + } - # If we don't have a file type, consider it a possibly abbreviated name and - # check for common variants. We try these first to grab libraries before - # a like-named executable image (e.g. -lperl resolves to perlshr.exe - # before perl.exe). - if ($lib !~ /\.[^:>\]]*$/) { - push(@variants,"${lib}shr","${lib}rtl","${lib}lib"); - push(@variants,"lib$lib") if $lib !~ /[:>\]]/; + my ( %found, @fndlibs, $ldlib ); + my $cwd = cwd(); + my ( $so, $lib_ext, $obj_ext ) = @Config{ 'so', 'lib_ext', 'obj_ext' }; + + # List of common Unix library names and their VMS equivalents + # (VMS equivalent of '' indicates that the library is automatically + # searched by the linker, and should be skipped here.) + my ( @flibs, %libs_seen ); + my %libmap = ( + 'm' => '', + 'f77' => '', + 'F77' => '', + 'V77' => '', + 'c' => '', + 'malloc' => '', + 'crypt' => '', + 'resolv' => '', + 'c_s' => '', + 'socket' => '', + 'X11' => 'DECW$XLIBSHR', + 'Xt' => 'DECW$XTSHR', + 'Xm' => 'DECW$XMLIBSHR', + 'Xmu' => 'DECW$XMULIBSHR' + ); + if ( $Config{'vms_cc_type'} ne 'decc' ) { $libmap{'curses'} = 'VAXCCURSE'; } + + warn "Potential libraries are '$potential_libs'\n" if $verbose; + + # First, sort out directories and library names in the input + my ( @dirs, @libs ); + foreach my $lib ( split ' ', $potential_libs ) { + push( @dirs, $1 ), next if $lib =~ /^-L(.*)/; + push( @dirs, $lib ), next if $lib =~ /[:>\]]$/; + push( @dirs, $lib ), next if -d $lib; + push( @libs, $1 ), next if $lib =~ /^-l(.*)/; + push( @libs, $lib ); } - push(@variants,$lib); - warn "Looking for $lib\n" if $verbose; - foreach my $variant (@variants) { - my($fullname, $name); - - foreach my $dir (@dirs) { - my($type); - - $name = "$dir$variant"; - warn "\tChecking $name\n" if $verbose > 2; - $fullname = VMS::Filespec::rmsexpand($name); - if (defined $fullname and -f $fullname) { - # It's got its own suffix, so we'll have to figure out the type - if ($fullname =~ /(?:$so|exe)$/i) { $type = 'SHR'; } - elsif ($fullname =~ /(?:$lib_ext|olb)$/i) { $type = 'OLB'; } - elsif ($fullname =~ /(?:$obj_ext|obj)$/i) { - warn "Note (probably harmless): " - ."Plain object file $fullname found in library list\n"; - $type = 'OBJ'; - } - else { - warn "Note (probably harmless): " - ."Unknown library type for $fullname; assuming shared\n"; - $type = 'SHR'; - } + push( @dirs, split( ' ', $Config{'libpth'} ) ); + + # Now make sure we've got VMS-syntax absolute directory specs + # (We don't, however, check whether someone's hidden a relative + # path in a logical name.) + foreach my $dir ( @dirs ) { + unless ( -d $dir ) { + warn "Skipping nonexistent Directory $dir\n" if $verbose > 1; + $dir = ''; + next; } - elsif (-f ($fullname = VMS::Filespec::rmsexpand($name,$so)) or - -f ($fullname = VMS::Filespec::rmsexpand($name,'.exe'))) { - $type = 'SHR'; - $name = $fullname unless $fullname =~ /exe;?\d*$/i; + warn "Resolving directory $dir\n" if $verbose; + if ( File::Spec->file_name_is_absolute( $dir ) ) { + $dir = $self->fixpath( $dir, 1 ); } - elsif (not length($ctype) and # If we've got a lib already, - # don't bother - ( -f ($fullname = VMS::Filespec::rmsexpand($name,$lib_ext)) or - -f ($fullname = VMS::Filespec::rmsexpand($name,'.olb')))) { - $type = 'OLB'; - $name = $fullname unless $fullname =~ /olb;?\d*$/i; + else { + $dir = $self->catdir( $cwd, $dir ); } - elsif (not length($ctype) and # If we've got a lib already, - # don't bother - ( -f ($fullname = VMS::Filespec::rmsexpand($name,$obj_ext)) or - -f ($fullname = VMS::Filespec::rmsexpand($name,'.obj')))) { - warn "Note (probably harmless): " - ."Plain object file $fullname found in library list\n"; - $type = 'OBJ'; - $name = $fullname unless $fullname =~ /obj;?\d*$/i; + } + @dirs = grep { length( $_ ) } @dirs; + unshift( @dirs, '' ); # Check each $lib without additions first + + LIB: foreach my $lib ( @libs ) { + if ( exists $libmap{$lib} ) { + next unless length $libmap{$lib}; + $lib = $libmap{$lib}; } - if (defined $type) { - $ctype = $type; $cand = $name; - last if $ctype eq 'SHR'; + + my ( @variants, $cand ); + my ( $ctype ) = ''; + + # If we don't have a file type, consider it a possibly abbreviated name and + # check for common variants. We try these first to grab libraries before + # a like-named executable image (e.g. -lperl resolves to perlshr.exe + # before perl.exe). + if ( $lib !~ /\.[^:>\]]*$/ ) { + push( @variants, "${lib}shr", "${lib}rtl", "${lib}lib" ); + push( @variants, "lib$lib" ) if $lib !~ /[:>\]]/; + } + push( @variants, $lib ); + warn "Looking for $lib\n" if $verbose; + foreach my $variant ( @variants ) { + my ( $fullname, $name ); + + foreach my $dir ( @dirs ) { + my ( $type ); + + $name = "$dir$variant"; + warn "\tChecking $name\n" if $verbose > 2; + $fullname = VMS::Filespec::rmsexpand( $name ); + if ( defined $fullname and -f $fullname ) { + + # It's got its own suffix, so we'll have to figure out the type + if ( $fullname =~ /(?:$so|exe)$/i ) { $type = 'SHR'; } + elsif ( $fullname =~ /(?:$lib_ext|olb)$/i ) { $type = 'OLB'; } + elsif ( $fullname =~ /(?:$obj_ext|obj)$/i ) { + warn "Note (probably harmless): " . "Plain object file $fullname found in library list\n"; + $type = 'OBJ'; + } + else { + warn "Note (probably harmless): " . "Unknown library type for $fullname; assuming shared\n"; + $type = 'SHR'; + } + } + elsif (-f ( $fullname = VMS::Filespec::rmsexpand( $name, $so ) ) + or -f ( $fullname = VMS::Filespec::rmsexpand( $name, '.exe' ) ) ) + { + $type = 'SHR'; + $name = $fullname unless $fullname =~ /exe;?\d*$/i; + } + elsif ( + not length( $ctype ) and # If we've got a lib already, + # don't bother + ( -f ( $fullname = VMS::Filespec::rmsexpand( $name, $lib_ext ) ) or -f ( $fullname = VMS::Filespec::rmsexpand( $name, '.olb' ) ) ) + ) + { + $type = 'OLB'; + $name = $fullname unless $fullname =~ /olb;?\d*$/i; + } + elsif ( + not length( $ctype ) and # If we've got a lib already, + # don't bother + ( -f ( $fullname = VMS::Filespec::rmsexpand( $name, $obj_ext ) ) or -f ( $fullname = VMS::Filespec::rmsexpand( $name, '.obj' ) ) ) + ) + { + warn "Note (probably harmless): " . "Plain object file $fullname found in library list\n"; + $type = 'OBJ'; + $name = $fullname unless $fullname =~ /obj;?\d*$/i; + } + if ( defined $type ) { + $ctype = $type; + $cand = $name; + last if $ctype eq 'SHR'; + } + } + if ( $ctype ) { + + # This has to precede any other CRTLs, so just make it first + if ( $cand eq 'VAXCCURSE' ) { unshift @{ $found{$ctype} }, $cand; } + else { push @{ $found{$ctype} }, $cand; } + warn "\tFound as $cand (really $fullname), type $ctype\n" + if $verbose > 1; + push @flibs, $name unless $libs_seen{$fullname}++; + next LIB; + } } - } - if ($ctype) { - # This has to precede any other CRTLs, so just make it first - if ($cand eq 'VAXCCURSE') { unshift @{$found{$ctype}}, $cand; } - else { push @{$found{$ctype}}, $cand; } - warn "\tFound as $cand (really $fullname), type $ctype\n" - if $verbose > 1; - push @flibs, $name unless $libs_seen{$fullname}++; - next LIB; - } + warn "Note (probably harmless): " . "No library found for $lib\n"; } - warn "Note (probably harmless): " - ."No library found for $lib\n"; - } - - push @fndlibs, @{$found{OBJ}} if exists $found{OBJ}; - push @fndlibs, map { "$_/Library" } @{$found{OLB}} if exists $found{OLB}; - push @fndlibs, map { "$_/Share" } @{$found{SHR}} if exists $found{SHR}; - my $lib = join(' ',@fndlibs); - - $ldlib = $crtlstr ? "$lib $crtlstr" : $lib; - warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose; - wantarray ? ($lib, '', $ldlib, '', ($give_libs ? \@flibs : ())) : $lib; + + push @fndlibs, @{ $found{OBJ} } if exists $found{OBJ}; + push @fndlibs, map { "$_/Library" } @{ $found{OLB} } if exists $found{OLB}; + push @fndlibs, map { "$_/Share" } @{ $found{SHR} } if exists $found{SHR}; + my $lib = join( ' ', @fndlibs ); + + $ldlib = $crtlstr ? "$lib $crtlstr" : $lib; + warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose; + wantarray ? ( $lib, '', $ldlib, '', ( $give_libs ? \@flibs : () ) ) : $lib; } 1; diff --git a/perl/lib/ExtUtils/MM.pm b/perl/lib/ExtUtils/MM.pm index eac5f48..2fe3b19 100644 --- a/perl/lib/ExtUtils/MM.pm +++ b/perl/lib/ExtUtils/MM.pm @@ -3,7 +3,7 @@ package ExtUtils::MM; use strict; use ExtUtils::MakeMaker::Config; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::Liblist; require ExtUtils::MakeMaker; diff --git a/perl/lib/ExtUtils/MM_AIX.pm b/perl/lib/ExtUtils/MM_AIX.pm index 5179be4..6d82786 100644 --- a/perl/lib/ExtUtils/MM_AIX.pm +++ b/perl/lib/ExtUtils/MM_AIX.pm @@ -1,7 +1,7 @@ package ExtUtils::MM_AIX; use strict; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::MM_Unix; our @ISA = qw(ExtUtils::MM_Unix); diff --git a/perl/lib/ExtUtils/MM_Any.pm b/perl/lib/ExtUtils/MM_Any.pm index 4905aeb..eab8892 100644 --- a/perl/lib/ExtUtils/MM_Any.pm +++ b/perl/lib/ExtUtils/MM_Any.pm @@ -1,7 +1,7 @@ package ExtUtils::MM_Any; use strict; -our $VERSION = '6.56'; +our $VERSION = '6.62'; use Carp; use File::Spec; @@ -487,7 +487,7 @@ clean :: clean_subdirs } push(@files, qw[$(MAKE_APERL_FILE) - perlmain.c tmon.out mon.out so_locations + MYMETA.json MYMETA.yml perlmain.c tmon.out mon.out so_locations blibdirs.ts pm_to_blib pm_to_blib.ts *$(OBJ_EXT) *$(LIB_EXT) perl.exe perl perl$(EXE_EXT) $(BOOTSTRAP) $(BASEEXT).bso @@ -728,6 +728,13 @@ CMD return $manify; } +sub _has_cpan_meta { + return eval { + require CPAN::Meta; + CPAN::Meta->VERSION(2.112150); + 1; + }; +} =head3 metafile_target @@ -743,28 +750,111 @@ possible. sub metafile_target { my $self = shift; - - return <<'MAKE_FRAG' if $self->{NO_META}; + return <<'MAKE_FRAG' if $self->{NO_META} or ! _has_cpan_meta(); metafile : $(NOECHO) $(NOOP) MAKE_FRAG - my @metadata = $self->metafile_data( + my %metadata = $self->metafile_data( $self->{META_ADD} || {}, $self->{META_MERGE} || {}, ); - my $meta = $self->metafile_file(@metadata); - my @write_meta = $self->echo($meta, 'META_new.yml'); + + _fix_metadata_before_conversion( \%metadata ); + + # paper over validation issues, but still complain, necessary because + # there's no guarantee that the above will fix ALL errors + my $meta = eval { CPAN::Meta->create( \%metadata, { lazy_validation => 1 } ) }; + warn $@ if $@ and + $@ !~ /encountered CODE.*, but JSON can only represent references to arrays or hashes/; + + # use the original metadata straight if the conversion failed + # or if it can't be stringified. + if( !$meta || + !eval { $meta->as_string( { version => "1.4" } ) } || + !eval { $meta->as_string } + ) + { + $meta = bless \%metadata, 'CPAN::Meta'; + } + + my @write_metayml = $self->echo( + $meta->as_string({version => "1.4"}), 'META_new.yml' + ); + my @write_metajson = $self->echo( + $meta->as_string(), 'META_new.json' + ); - return sprintf <<'MAKE_FRAG', join("\n\t", @write_meta); + my $metayml = join("\n\t", @write_metayml); + my $metajson = join("\n\t", @write_metajson); + return sprintf <<'MAKE_FRAG', $metayml, $metajson; metafile : create_distdir $(NOECHO) $(ECHO) Generating META.yml %s -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml + $(NOECHO) $(ECHO) Generating META.json + %s + -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json MAKE_FRAG } +=begin private + +=head3 _fix_metadata_before_conversion + + _fix_metadata_before_conversion( \%metadata ); + +Fixes errors in the metadata before it's handed off to CPAN::Meta for +conversion. This hopefully results in something that can be used further +on, no guarantee is made though. + +=end private + +=cut + +sub _fix_metadata_before_conversion { + my ( $metadata ) = @_; + + # we should never be called unless this already passed but + # prefer to be defensive in case somebody else calls this + + return unless _has_cpan_meta; + + my $bad_version = $metadata->{version} && + !CPAN::Meta::Validator->new->version( 'version', $metadata->{version} ); + + # just delete all invalid versions + if( $bad_version ) { + warn "Can't parse version '$metadata->{version}'\n"; + $metadata->{version} = ''; + } + + my $validator = CPAN::Meta::Validator->new( $metadata ); + return if $validator->is_valid; + + # fix non-camelcase custom resource keys (only other trick we know) + for my $error ( $validator->errors ) { + my ( $key ) = ( $error =~ /Custom resource '(.*)' must be in CamelCase./ ); + next if !$key; + + # first try to remove all non-alphabetic chars + ( my $new_key = $key ) =~ s/[^_a-zA-Z]//g; + + # if that doesn't work, uppercase first one + $new_key = ucfirst $new_key if !$validator->custom_1( $new_key ); + + # copy to new key if that worked + $metadata->{resources}{$new_key} = $metadata->{resources}{$key} + if $validator->custom_1( $new_key ); + + # and delete old one in any case + delete $metadata->{resources}{$key}; + } + + return; +} + =begin private @@ -816,57 +906,16 @@ sub metafile_data { my $self = shift; my($meta_add, $meta_merge) = @_; - # The order in which standard meta keys should be written. - my @meta_order = qw( - name - version - abstract - author - license - distribution_type - - configure_requires - build_requires - requires - - resources - - provides - no_index - - generated_by - meta-spec - ); - - # Check the original args so we can tell between the user setting it - # to an empty hash and it just being initialized. - my $configure_requires; - if( $self->{ARGS}{CONFIGURE_REQUIRES} ) { - $configure_requires = $self->{CONFIGURE_REQUIRES}; - } else { - $configure_requires = { - 'ExtUtils::MakeMaker' => 0, - }; - } - my $build_requires; - if( $self->{ARGS}{BUILD_REQUIRES} ) { - $build_requires = $self->{BUILD_REQUIRES}; - } else { - $build_requires = { - 'ExtUtils::MakeMaker' => 0, - }; - } - my %meta = ( + # required name => $self->{DISTNAME}, - version => $self->{VERSION}, - abstract => $self->{ABSTRACT}, + version => _normalize_version($self->{VERSION}), + abstract => $self->{ABSTRACT} || 'unknown', license => $self->{LICENSE} || 'unknown', - distribution_type => $self->{PM} ? 'module' : 'script', - - configure_requires => $configure_requires, + dynamic_config => 1, - build_requires => $build_requires, + # optional + distribution_type => $self->{PM} ? 'module' : 'script', no_index => { directory => [qw(t inc)] @@ -880,10 +929,20 @@ sub metafile_data { ); # The author key is required and it takes a list. - $meta{author} = defined $self->{AUTHOR} ? [$self->{AUTHOR}] : []; + $meta{author} = defined $self->{AUTHOR} ? $self->{AUTHOR} : []; + + # Check the original args so we can tell between the user setting it + # to an empty hash and it just being initialized. + if( $self->{ARGS}{CONFIGURE_REQUIRES} ) { + $meta{configure_requires} + = _normalize_prereqs($self->{CONFIGURE_REQUIRES}); + } else { + $meta{configure_requires} = { + 'ExtUtils::MakeMaker' => 0, + }; + } - $meta{requires} = $self->{PREREQ_PM} if defined $self->{PREREQ_PM}; - $meta{requires}{perl} = $self->{MIN_PERL_VERSION} if $self->{MIN_PERL_VERSION}; + %meta = $self->_add_requirements_to_meta( %meta ); while( my($key, $val) = each %$meta_add ) { $meta{$key} = $val; @@ -893,24 +952,62 @@ sub metafile_data { $self->_hash_merge(\%meta, $key, $val); } - my @meta_pairs; + return %meta; +} - # Put the standard keys first in the proper order. - for my $key (@meta_order) { - next unless exists $meta{$key}; - push @meta_pairs, $key, delete $meta{$key}; - } +=begin private + +=cut + +sub _add_requirements_to_meta { + my ( $self, %meta ) = @_; - # Then tack everything else onto the end, alpha sorted. - for my $key (sort {lc $a cmp lc $b} keys %meta) { - push @meta_pairs, $key, $meta{$key}; + # Check the original args so we can tell between the user setting it + # to an empty hash and it just being initialized. + + if( $self->{ARGS}{BUILD_REQUIRES} ) { + $meta{build_requires} = _normalize_prereqs($self->{BUILD_REQUIRES}); + } else { + $meta{build_requires} = { + 'ExtUtils::MakeMaker' => 0, + }; } - return @meta_pairs + $meta{requires} = _normalize_prereqs($self->{PREREQ_PM}) + if defined $self->{PREREQ_PM}; + $meta{requires}{perl} = _normalize_version($self->{MIN_PERL_VERSION}) + if $self->{MIN_PERL_VERSION}; + + return %meta; } -=begin private +sub _normalize_prereqs { + my ($hash) = @_; + my %prereqs; + while ( my ($k,$v) = each %$hash ) { + $prereqs{$k} = _normalize_version($v); + } + return \%prereqs; +} + +# Adapted from Module::Build::Base +sub _normalize_version { + my ($version) = @_; + $version = 0 unless defined $version; + + if ( ref $version eq 'version' ) { # version objects + $version = $version->is_qv ? $version->normal : $version->stringify; + } + elsif ( $version =~ /^[^v][^.]*\.[^.]+\./ ) { # no leading v, multiple dots + # normalize string tuples without "v": "1.2.3" -> "v1.2.3" + $version = "v$version"; + } + else { + # leave alone + } + return $version; +} =head3 _dump_hash @@ -984,7 +1081,7 @@ sub _dump_hash { ); if (exists $customs->{$key}) { my %k_custom = %{$customs->{$key}}; - foreach my $k qw(key_sort max_key_length customs) { + foreach my $k (qw(key_sort max_key_length customs)) { $k_options{$k} = $k_custom{$k} if exists $k_custom{$k}; } } @@ -1069,22 +1166,121 @@ distdir. sub distmeta_target { my $self = shift; - my $add_meta = $self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']); -eval { maniadd({q{META.yml} => q{Module meta-data (added by MakeMaker)}}) } + my @add_meta = ( + $self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']), +exit unless -e q{META.yml}; +eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) } or print "Could not add META.yml to MANIFEST: $${'@'}\n" CODE + $self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']) +exit unless -f q{META.json}; +eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) } + or print "Could not add META.json to MANIFEST: $${'@'}\n" +CODE + ); - my $add_meta_to_distdir = $self->cd('$(DISTVNAME)', $add_meta); + my @add_meta_to_distdir = map { $self->cd('$(DISTVNAME)', $_) } @add_meta; - return sprintf <<'MAKE', $add_meta_to_distdir; + return sprintf <<'MAKE', @add_meta_to_distdir; distmeta : create_distdir metafile $(NOECHO) %s + $(NOECHO) %s MAKE } +=head3 mymeta + + my $mymeta = $mm->mymeta; + +Generate MYMETA information as a hash either from an existing META.yml +or from internal data. + +=cut + +sub mymeta { + my $self = shift; + my $file = shift || ''; # for testing + + my $mymeta = $self->_mymeta_from_meta($file); + + unless ( $mymeta ) { + my @metadata = $self->metafile_data( + $self->{META_ADD} || {}, + $self->{META_MERGE} || {}, + ); + $mymeta = {@metadata}; + } + + # Overwrite the non-configure dependency hashes + + $mymeta = { $self->_add_requirements_to_meta( %$mymeta ) }; + + $mymeta->{dynamic_config} = 0; + + return $mymeta; +} + + +sub _mymeta_from_meta { + my $self = shift; + my $metafile = shift || ''; # for testing + + return unless _has_cpan_meta(); + + my $meta; + for my $file ( $metafile, "META.json", "META.yml" ) { + next unless -e $file; + eval { + $meta = CPAN::Meta->load_file($file)->as_struct( {version => "1.4"} ); + }; + last if $meta; + } + return undef unless $meta; + + # META.yml before 6.25_01 cannot be trusted. META.yml lived in the source directory. + # There was a good chance the author accidentally uploaded a stale META.yml if they + # rolled their own tarball rather than using "make dist". + if ($meta->{generated_by} && + $meta->{generated_by} =~ /ExtUtils::MakeMaker version ([\d\._]+)/) { + my $eummv = do { local $^W = 0; $1+0; }; + if ($eummv < 6.2501) { + return undef; + } + } + + return $meta; +} + +=head3 write_mymeta + + $self->write_mymeta( $mymeta ); + +Write MYMETA information to MYMETA.yml. + +This will probably be refactored into a more generic YAML dumping method. + +=cut + +sub write_mymeta { + my $self = shift; + my $mymeta = shift; + + return unless _has_cpan_meta(); + + _fix_metadata_before_conversion( $mymeta ); + + # this can still blow up + # not sure if i should just eval this and skip file creation if it + # blows up + my $meta_obj = CPAN::Meta->new( $mymeta, { lazy_validation => 1 } ); + $meta_obj->save( 'MYMETA.json' ); + $meta_obj->save( 'MYMETA.yml', { version => "1.4" } ); + return 1; +} + =head3 realclean (o) Defines the realclean target. @@ -1100,7 +1296,7 @@ sub realclean { # Special exception for the perl core where INST_* is not in blib. # This cleans up the files built from the ext/ directory (all XS). if( $self->{PERL_CORE} ) { - push @dirs, qw($(INST_AUTODIR) $(INST_ARCHAUTODIR)); + push @dirs, qw($(INST_AUTODIR) $(INST_ARCHAUTODIR)); push @files, values %{$self->{PM}}; } @@ -1305,7 +1501,7 @@ sub init_INST { # perl has been built and installed. Setting INST_LIB allows # you to build directly into, say $Config{privlibexp}. unless ($self->{INST_LIB}){ - if ($self->{PERL_CORE}) { + if ($self->{PERL_CORE}) { if (defined $Cross::platform) { $self->{INST_LIB} = $self->{INST_ARCHLIB} = $self->catdir($self->{PERL_LIB},"..","xlib", @@ -1314,9 +1510,9 @@ sub init_INST { else { $self->{INST_LIB} = $self->{INST_ARCHLIB} = $self->{PERL_LIB}; } - } else { - $self->{INST_LIB} = $self->catdir($Curdir,"blib","lib"); - } + } else { + $self->{INST_LIB} = $self->catdir($Curdir,"blib","lib"); + } } my @parentdir = split(/::/, $self->{PARENT_NAME}); diff --git a/perl/lib/ExtUtils/MM_BeOS.pm b/perl/lib/ExtUtils/MM_BeOS.pm index 0b7c8db..5dc3d9d 100644 --- a/perl/lib/ExtUtils/MM_BeOS.pm +++ b/perl/lib/ExtUtils/MM_BeOS.pm @@ -26,7 +26,7 @@ require ExtUtils::MM_Any; require ExtUtils::MM_Unix; our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix ); -our $VERSION = '6.56'; +our $VERSION = '6.62'; =item os_flavor diff --git a/perl/lib/ExtUtils/MM_Cygwin.pm b/perl/lib/ExtUtils/MM_Cygwin.pm index 394fbc6..a549459 100644 --- a/perl/lib/ExtUtils/MM_Cygwin.pm +++ b/perl/lib/ExtUtils/MM_Cygwin.pm @@ -9,7 +9,7 @@ require ExtUtils::MM_Unix; require ExtUtils::MM_Win32; our @ISA = qw( ExtUtils::MM_Unix ); -our $VERSION = '6.56'; +our $VERSION = '6.62'; =head1 NAME @@ -116,6 +116,39 @@ sub maybe_command { return $self->SUPER::maybe_command($file); } +=item dynamic_lib + +Use the default to produce the *.dll's. +But for new archdir dll's use the same rebase address if the old exists. + +=cut + +sub dynamic_lib { + my($self, %attribs) = @_; + my $s = ExtUtils::MM_Unix::dynamic_lib($self, %attribs); + my $ori = "$self->{INSTALLARCHLIB}/auto/$self->{FULLEXT}/$self->{BASEEXT}.$self->{DLEXT}"; + if (-e $ori) { + my $imagebase = `/bin/objdump -p $ori | /bin/grep ImageBase | /bin/cut -c12-`; + chomp $imagebase; + if ($imagebase gt "40000000") { + my $LDDLFLAGS = $self->{LDDLFLAGS}; + $LDDLFLAGS =~ s/-Wl,--enable-auto-image-base/-Wl,--image-base=0x$imagebase/; + $s =~ s/ \$\(LDDLFLAGS\) / $LDDLFLAGS /m; + } + } + $s; +} + +=item all_target + +Build man pages, too + +=cut + +sub all_target { + ExtUtils::MM_Unix::all_target(shift); +} + =back =cut diff --git a/perl/lib/ExtUtils/MM_DOS.pm b/perl/lib/ExtUtils/MM_DOS.pm index fc0a794..43834cc 100644 --- a/perl/lib/ExtUtils/MM_DOS.pm +++ b/perl/lib/ExtUtils/MM_DOS.pm @@ -2,7 +2,7 @@ package ExtUtils::MM_DOS; use strict; -our $VERSION = 6.56; +our $VERSION = '6.62'; require ExtUtils::MM_Any; require ExtUtils::MM_Unix; diff --git a/perl/lib/ExtUtils/MM_Darwin.pm b/perl/lib/ExtUtils/MM_Darwin.pm index 1cb87c7..f347097 100644 --- a/perl/lib/ExtUtils/MM_Darwin.pm +++ b/perl/lib/ExtUtils/MM_Darwin.pm @@ -7,7 +7,7 @@ BEGIN { our @ISA = qw( ExtUtils::MM_Unix ); } -our $VERSION = '6.56'; +our $VERSION = '6.62'; =head1 NAME diff --git a/perl/lib/ExtUtils/MM_MacOS.pm b/perl/lib/ExtUtils/MM_MacOS.pm index cfc8205..5aeab50 100644 --- a/perl/lib/ExtUtils/MM_MacOS.pm +++ b/perl/lib/ExtUtils/MM_MacOS.pm @@ -2,7 +2,7 @@ package ExtUtils::MM_MacOS; use strict; -our $VERSION = 6.56; +our $VERSION = '6.62'; sub new { die <<'UNSUPPORTED'; diff --git a/perl/lib/ExtUtils/MM_NW5.pm b/perl/lib/ExtUtils/MM_NW5.pm index 0c8f6c0..281d666 100644 --- a/perl/lib/ExtUtils/MM_NW5.pm +++ b/perl/lib/ExtUtils/MM_NW5.pm @@ -22,7 +22,7 @@ use strict; use ExtUtils::MakeMaker::Config; use File::Basename; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::MM_Win32; our @ISA = qw(ExtUtils::MM_Win32); diff --git a/perl/lib/ExtUtils/MM_OS2.pm b/perl/lib/ExtUtils/MM_OS2.pm index 680502b..c922b28 100644 --- a/perl/lib/ExtUtils/MM_OS2.pm +++ b/perl/lib/ExtUtils/MM_OS2.pm @@ -5,7 +5,7 @@ use strict; use ExtUtils::MakeMaker qw(neatvalue); use File::Spec; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::MM_Any; require ExtUtils::MM_Unix; diff --git a/perl/lib/ExtUtils/MM_QNX.pm b/perl/lib/ExtUtils/MM_QNX.pm index f78d5e8..a19dc09 100644 --- a/perl/lib/ExtUtils/MM_QNX.pm +++ b/perl/lib/ExtUtils/MM_QNX.pm @@ -1,7 +1,7 @@ package ExtUtils::MM_QNX; use strict; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::MM_Unix; our @ISA = qw(ExtUtils::MM_Unix); diff --git a/perl/lib/ExtUtils/MM_UWIN.pm b/perl/lib/ExtUtils/MM_UWIN.pm index 5adc46e..ef14a67 100644 --- a/perl/lib/ExtUtils/MM_UWIN.pm +++ b/perl/lib/ExtUtils/MM_UWIN.pm @@ -1,7 +1,7 @@ package ExtUtils::MM_UWIN; use strict; -our $VERSION = 6.56; +our $VERSION = '6.62'; require ExtUtils::MM_Unix; our @ISA = qw(ExtUtils::MM_Unix); diff --git a/perl/lib/ExtUtils/MM_Unix.pm b/perl/lib/ExtUtils/MM_Unix.pm index 239d6df..764da8c 100644 --- a/perl/lib/ExtUtils/MM_Unix.pm +++ b/perl/lib/ExtUtils/MM_Unix.pm @@ -15,7 +15,8 @@ use ExtUtils::MakeMaker qw($Verbose neatvalue); # If we make $VERSION an our variable parse_version() breaks use vars qw($VERSION); -$VERSION = '6.56'; +$VERSION = '6.62'; +$VERSION = eval $VERSION; require ExtUtils::MM_Any; our @ISA = qw(ExtUtils::MM_Any); @@ -1079,7 +1080,6 @@ Inserts the sharpbang or equivalent magic number to a set of @files. sub fixin { # stolen from the pink Camel book, more or less my ( $self, @files ) = @_; - my ($does_shbang) = $Config{'sharpbang'} =~ /^\s*\#\!/; for my $file (@files) { my $file_new = "$file.new"; my $file_bak = "$file.bak"; @@ -1088,58 +1088,9 @@ sub fixin { # stolen from the pink Camel book, more or less local $/ = "\n"; chomp( my $line = <$fixin> ); next unless $line =~ s/^\s*\#!\s*//; # Not a shbang file. - # Now figure out the interpreter name. - my ( $cmd, $arg ) = split ' ', $line, 2; - $cmd =~ s!^.*/!!; - - # Now look (in reverse) for interpreter in absolute PATH (unless perl). - my $interpreter; - if ( $cmd =~ m{^perl(?:\z|[^a-z])} ) { - if ( $Config{startperl} =~ m,^\#!.*/perl, ) { - $interpreter = $Config{startperl}; - $interpreter =~ s,^\#!,,; - } - else { - $interpreter = $Config{perlpath}; - } - } - else { - my (@absdirs) - = reverse grep { $self->file_name_is_absolute($_) } $self->path; - $interpreter = ''; - - foreach my $dir (@absdirs) { - if ( $self->maybe_command($cmd) ) { - warn "Ignoring $interpreter in $file\n" - if $Verbose && $interpreter; - $interpreter = $self->catfile( $dir, $cmd ); - } - } - } - - # Figure out how to invoke interpreter on this machine. - my ($shb) = ""; - if ($interpreter) { - print STDOUT "Changing sharpbang in $file to $interpreter" - if $Verbose; - - # this is probably value-free on DOSISH platforms - if ($does_shbang) { - $shb .= "$Config{'sharpbang'}$interpreter"; - $shb .= ' ' . $arg if defined $arg; - $shb .= "\n"; - } - $shb .= qq{ -eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}' - if 0; # not running under some shell -} unless $Is{Win32}; # this won't work on win32, so don't - } - else { - warn "Can't find $cmd in PATH, $file unchanged" - if $Verbose; - next; - } + my $shb = $self->_fixin_replace_shebang( $file, $line ); + next unless defined $shb; open( my $fixout, ">", "$file_new" ) or do { warn "Can't create new $file: $!\n"; @@ -1189,6 +1140,63 @@ sub _rename { return rename($old, $new); } +sub _fixin_replace_shebang { + my ( $self, $file, $line ) = @_; + + # Now figure out the interpreter name. + my ( $cmd, $arg ) = split ' ', $line, 2; + $cmd =~ s!^.*/!!; + + # Now look (in reverse) for interpreter in absolute PATH (unless perl). + my $interpreter; + if ( $cmd =~ m{^perl(?:\z|[^a-z])} ) { + if ( $Config{startperl} =~ m,^\#!.*/perl, ) { + $interpreter = $Config{startperl}; + $interpreter =~ s,^\#!,,; + } + else { + $interpreter = $Config{perlpath}; + } + } + else { + my (@absdirs) + = reverse grep { $self->file_name_is_absolute($_) } $self->path; + $interpreter = ''; + + foreach my $dir (@absdirs) { + if ( $self->maybe_command($cmd) ) { + warn "Ignoring $interpreter in $file\n" + if $Verbose && $interpreter; + $interpreter = $self->catfile( $dir, $cmd ); + } + } + } + + # Figure out how to invoke interpreter on this machine. + + my ($does_shbang) = $Config{'sharpbang'} =~ /^\s*\#\!/; + my ($shb) = ""; + if ($interpreter) { + print STDOUT "Changing sharpbang in $file to $interpreter" + if $Verbose; + # this is probably value-free on DOSISH platforms + if ($does_shbang) { + $shb .= "$Config{'sharpbang'}$interpreter"; + $shb .= ' ' . $arg if defined $arg; + $shb .= "\n"; + } + $shb .= qq{ +eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}' + if 0; # not running under some shell +} unless $Is{Win32}; # this won't work on win32, so don't + } + else { + warn "Can't find $cmd in PATH, $file unchanged" + if $Verbose; + return undef; + } + return $shb +} =item force (o) @@ -2593,7 +2601,7 @@ sub parse_abstract { $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod; next if !$inpod; chop; - next unless /^($package\s-\s)(.*)/; + next unless /^($package(?:\.pm)? \s+ -+ \s+)(.*)/x; $result = $2; last; } @@ -2634,7 +2642,7 @@ sub parse_version { $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod; next if $inpod || /^\s*#/; chop; - next if /^\s*(if|unless)/; + next if /^\s*(if|unless|elsif)/; if ( m{^ \s* package \s+ \w[\w\:\']* \s+ (v?[0-9._]+) \s* ; }x ) { local $^W = 0; $result = $1; @@ -2754,7 +2762,6 @@ PERL_HDRS = \ $(PERL_INC)/INTERN.h \ $(PERL_INC)/XSUB.h \ $(PERL_INC)/av.h \ - $(PERL_INC)/cc_runtime.h \ $(PERL_INC)/config.h \ $(PERL_INC)/cop.h \ $(PERL_INC)/cv.h \ @@ -2884,7 +2891,7 @@ sub ppd { $abstract =~ s//>/g; - my $author = $self->{AUTHOR} || ''; + my $author = join(', ',@{$self->{AUTHOR} || []}); $author =~ s//>/g; diff --git a/perl/lib/ExtUtils/MM_VMS.pm b/perl/lib/ExtUtils/MM_VMS.pm index 2066d03..43b8a11 100644 --- a/perl/lib/ExtUtils/MM_VMS.pm +++ b/perl/lib/ExtUtils/MM_VMS.pm @@ -15,7 +15,7 @@ BEGIN { use File::Basename; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::MM_Any; require ExtUtils::MM_Unix; @@ -248,6 +248,23 @@ sub find_perl { 0; # false and not empty } +=item _fixin_replace_shebang (override) + +Helper routine for MM->fixin(), overridden because there's no such thing as an +actual shebang line that will be intepreted by the shell, so we just prepend +$Config{startperl} and preserve the shebang line argument for any switches it +may contain. + +=cut + +sub _fixin_replace_shebang { + my ( $self, $file, $line ) = @_; + + my ( undef, $arg ) = split ' ', $line, 2; + + return $Config{startperl} . "\n" . $Config{sharpbang} . "perl $arg\n"; +} + =item maybe_command (override) Follows VMS naming conventions for executable files. @@ -1067,14 +1084,14 @@ $(INST_STATIC) : $(OBJECT) $(MYEXTLIB) =item extra_clean_files Clean up some OS specific files. Plus the temp file used to shorten -a lot of commands. +a lot of commands. And the name mangler database. =cut sub extra_clean_files { return qw( *.Map *.Dmp *.Lis *.cpp *.$(DLEXT) *.Opt $(BASEEXT).bso - .MM_Tmp + .MM_Tmp cxx_repository ); } @@ -1265,7 +1282,7 @@ sub perldepend { push @m, ' $(OBJECT) : $(PERL_INC)EXTERN.h, $(PERL_INC)INTERN.h, $(PERL_INC)XSUB.h -$(OBJECT) : $(PERL_INC)av.h, $(PERL_INC)cc_runtime.h, $(PERL_INC)config.h +$(OBJECT) : $(PERL_INC)av.h, $(PERL_INC)config.h $(OBJECT) : $(PERL_INC)cop.h, $(PERL_INC)cv.h, $(PERL_INC)embed.h $(OBJECT) : $(PERL_INC)embedvar.h, $(PERL_INC)form.h $(OBJECT) : $(PERL_INC)gv.h, $(PERL_INC)handy.h, $(PERL_INC)hv.h diff --git a/perl/lib/ExtUtils/MM_VOS.pm b/perl/lib/ExtUtils/MM_VOS.pm index 1814a1d..d3eee98 100644 --- a/perl/lib/ExtUtils/MM_VOS.pm +++ b/perl/lib/ExtUtils/MM_VOS.pm @@ -1,7 +1,7 @@ package ExtUtils::MM_VOS; use strict; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::MM_Unix; our @ISA = qw(ExtUtils::MM_Unix); diff --git a/perl/lib/ExtUtils/MM_Win32.pm b/perl/lib/ExtUtils/MM_Win32.pm index 19e462d..1b9a388 100644 --- a/perl/lib/ExtUtils/MM_Win32.pm +++ b/perl/lib/ExtUtils/MM_Win32.pm @@ -27,13 +27,21 @@ use ExtUtils::MakeMaker qw( neatvalue ); require ExtUtils::MM_Any; require ExtUtils::MM_Unix; our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix ); -our $VERSION = '6.56'; +our $VERSION = '6.62'; $ENV{EMXSHELL} = 'sh'; # to run `commands` -my $BORLAND = $Config{'cc'} =~ /^bcc/i ? 1 : 0; -my $GCC = $Config{'cc'} =~ /\bgcc$/i ? 1 : 0; -my $DLLTOOL = $Config{'dlltool'} || 'dlltool'; +my ( $BORLAND, $GCC, $DLLTOOL ) = _identify_compiler_environment( \%Config ); + +sub _identify_compiler_environment { + my ( $config ) = @_; + + my $BORLAND = $config->{cc} =~ /^bcc/i ? 1 : 0; + my $GCC = $config->{cc} =~ /\bgcc\b/i ? 1 : 0; + my $DLLTOOL = $config->{dlltool} || 'dlltool'; + + return ( $BORLAND, $GCC, $DLLTOOL ); +} =head2 Overridden methods @@ -195,6 +203,8 @@ sub init_platform { my($self) = shift; $self->{MM_Win32_VERSION} = $VERSION; + + return; } sub platform_constants { @@ -211,6 +221,36 @@ sub platform_constants { } +=item constants + +Add MAXLINELENGTH for dmake before all the constants are output. + +=cut + +sub constants { + my $self = shift; + + my $make_text = $self->SUPER::constants; + return $make_text unless $self->is_make_type('dmake'); + + # dmake won't read any single "line" (even those with escaped newlines) + # larger than a certain size which can be as small as 8k. PM_TO_BLIB + # on large modules like DateTime::TimeZone can create lines over 32k. + # So we'll crank it up to a WHOPPING 64k. + # + # This has to come here before all the constants and not in + # platform_constants which is after constants. + my $size = $self->{MAXLINELENGTH} || 64 * 1024; + my $prefix = qq{ +# Get dmake to read long commands like PM_TO_BLIB +MAXLINELENGTH = $size + +}; + + return $prefix . $make_text; +} + + =item special_targets Add .USESHELL target for dmake. @@ -289,17 +329,6 @@ sub dynamic_lib { my($ldfrom) = '$(LDFROM)'; my(@m); -# one thing for GCC/Mingw32: -# we try to overcome non-relocateable-DLL problems by generating -# a (hopefully unique) image-base from the dll's name -# -- BKS, 10-19-1999 - if ($GCC) { - my $dllname = $self->{BASEEXT} . "." . $self->{DLEXT}; - $dllname =~ /(....)(.{0,4})/; - my $baseaddr = unpack("n", $1 ^ $2); - $otherldflags .= sprintf("-Wl,--image-base,0x%x0000 ", $baseaddr); - } - push(@m,' # This section creates the dynamically loadable $(INST_DYNAMIC) # from $(OBJECT) and possibly $(MYEXTLIB). @@ -458,20 +487,28 @@ sub oneliner { sub quote_literal { my($self, $text) = @_; - # I don't know if this is correct, but it seems to work on - # Win98's command.com - $text =~ s{"}{\\"}g; - - # dmake eats '{' inside double quotes and leaves alone { outside double - # quotes; however it transforms {{ into { either inside and outside double - # quotes. It also translates }} into }. The escaping below is not - # 100% correct. + # See: http://www.autohotkey.net/~deleyd/parameters/parameters.htm#CPP + + # Apply the Microsoft C/C++ parsing rules + $text =~ s{\\\\"}{\\\\\\\\\\"}g; # \\" -> \\\\\" + $text =~ s{(? \\\" + $text =~ s{(? \" + $text = qq{"$text"} if $text =~ /[ \t]/; + + # Apply the Command Prompt parsing rules (cmd.exe) + my @text = split /("[^"]*")/, $text; + # We should also escape parentheses, but it breaks one-liners containing + # $(MACRO)s in makefiles. + s{([<>|&^@!])}{^$1}g foreach grep { !/^"[^"]*"$/ } @text; + $text = join('', @text); + + # dmake expands {{ to { and }} to }. if( $self->is_make_type('dmake') ) { $text =~ s/{/{{/g; - $text =~ s/}}/}}}/g; + $text =~ s/}/}}/g; } - return qq{"$text"}; + return $text; } diff --git a/perl/lib/ExtUtils/MM_Win95.pm b/perl/lib/ExtUtils/MM_Win95.pm index c471476..8b835fd 100644 --- a/perl/lib/ExtUtils/MM_Win95.pm +++ b/perl/lib/ExtUtils/MM_Win95.pm @@ -2,7 +2,7 @@ package ExtUtils::MM_Win95; use strict; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require ExtUtils::MM_Win32; our @ISA = qw(ExtUtils::MM_Win32); diff --git a/perl/lib/ExtUtils/MY.pm b/perl/lib/ExtUtils/MY.pm index bed177d..f34289e 100644 --- a/perl/lib/ExtUtils/MY.pm +++ b/perl/lib/ExtUtils/MY.pm @@ -3,7 +3,7 @@ package ExtUtils::MY; use strict; require ExtUtils::MM; -our $VERSION = 6.56; +our $VERSION = '6.62'; our @ISA = qw(ExtUtils::MM); { diff --git a/perl/lib/ExtUtils/MakeMaker.pm b/perl/lib/ExtUtils/MakeMaker.pm index 4422b68..2aadf98 100644 --- a/perl/lib/ExtUtils/MakeMaker.pm +++ b/perl/lib/ExtUtils/MakeMaker.pm @@ -7,7 +7,7 @@ BEGIN {require 5.006;} require Exporter; use ExtUtils::MakeMaker::Config; -use Carp (); +use Carp; use File::Path; our $Verbose = 0; # exported @@ -18,7 +18,8 @@ our @Overridable; my @Prepend_parent; my %Recognized_Att_Keys; -our $VERSION = '6.56'; +our $VERSION = '6.62'; +$VERSION = eval $VERSION; # Emulate something resembling CVS $Revision$ (our $Revision = $VERSION) =~ s{_}{}; @@ -47,11 +48,13 @@ require ExtUtils::MY; # XXX pre-5.8 versions of ExtUtils::Embed expect sub WriteMakefile { - Carp::croak "WriteMakefile: Need even number of args" if @_ % 2; + croak "WriteMakefile: Need even number of args" if @_ % 2; require ExtUtils::MY; my %att = @_; + _convert_compat_attrs(\%att); + _verify_att(\%att); my $mm = MM->new(\%att); @@ -66,6 +69,7 @@ sub WriteMakefile { # scalar. my %Att_Sigs; my %Special_Sigs = ( + AUTHOR => 'ARRAY', C => 'ARRAY', CONFIG => 'ARRAY', CONFIGURE => 'CODE', @@ -111,6 +115,19 @@ my %Special_Sigs = ( @Att_Sigs{keys %Recognized_Att_Keys} = ('') x keys %Recognized_Att_Keys; @Att_Sigs{keys %Special_Sigs} = values %Special_Sigs; +sub _convert_compat_attrs { #result of running several times should be same + my($att) = @_; + if (exists $att->{AUTHOR}) { + if ($att->{AUTHOR}) { + if (!ref($att->{AUTHOR})) { + my $t = $att->{AUTHOR}; + $att->{AUTHOR} = [$t]; + } + } else { + $att->{AUTHOR} = []; + } + } +} sub _verify_att { my($att) = @_; @@ -160,7 +177,7 @@ sub _format_att { sub prompt ($;$) { ## no critic my($mess, $def) = @_; - Carp::confess("prompt function called without an argument") + confess("prompt function called without an argument") unless defined $mess; my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ; @@ -208,7 +225,7 @@ sub eval_in_subdirs { sub eval_in_x { my($self,$dir) = @_; - chdir $dir or Carp::carp("Couldn't change to directory $dir: $!"); + chdir $dir or carp("Couldn't change to directory $dir: $!"); { package main; @@ -257,8 +274,8 @@ sub full_setup { INC INCLUDE_EXT LDFROM LIB LIBPERL_A LIBS LICENSE LINKTYPE MAKE MAKEAPERL MAKEFILE MAKEFILE_OLD MAN1PODS MAN3PODS MAP_TARGET META_ADD META_MERGE MIN_PERL_VERSION BUILD_REQUIRES CONFIGURE_REQUIRES - MYEXTLIB NAME NEEDS_LINKING NOECHO NO_META NORECURS NO_VC OBJECT OPTIMIZE - PERL_MALLOC_OK PERL PERLMAINCC PERLRUN PERLRUNINST PERL_CORE + MYEXTLIB NAME NEEDS_LINKING NOECHO NO_META NO_MYMETA NORECURS NO_VC OBJECT + OPTIMIZE PERL_MALLOC_OK PERL PERLMAINCC PERLRUN PERLRUNINST PERL_CORE PERL_SRC PERM_DIR PERM_RW PERM_RWX PL_FILES PM PM_FILTER PMLIBDIRS PMLIBPARENTDIRS POLLUTE PPM_INSTALL_EXEC PPM_INSTALL_SCRIPT PREREQ_FATAL PREREQ_PM PREREQ_PRINT PRINT_PREREQ @@ -385,6 +402,8 @@ sub new { my($class,$self) = @_; my($key); + _convert_compat_attrs($self) if defined $self && $self; + # Store the original args passed to WriteMakefile() foreach my $k (keys %$self) { $self->{ARGS}{$k} = $self->{$k}; @@ -392,13 +411,17 @@ sub new { $self = {} unless defined $self; - $self->{PREREQ_PM} ||= {}; - $self->{BUILD_REQUIRES} ||= {}; - # Temporarily bless it into MM so it can be used as an # object. It will be blessed into a temp package later. bless $self, "MM"; + # Cleanup all the module requirement bits + for my $key (qw(PREREQ_PM BUILD_REQUIRES CONFIGURE_REQUIRES)) { + $self->{$key} ||= {}; + $self->clean_versions( $key ); + } + + if ("@ARGV" =~ /\bPREREQ_PRINT\b/) { $self->_PREREQ_PRINT; } @@ -409,7 +432,7 @@ sub new { } print STDOUT "MakeMaker (v$VERSION)\n" if $Verbose; - if (-f "MANIFEST" && ! -f "Makefile"){ + if (-f "MANIFEST" && ! -f "Makefile" && ! $ENV{PERL_CORE}){ check_manifest(); } @@ -430,7 +453,7 @@ sub new { }; if (!$perl_version_ok) { if (!defined $perl_version_ok) { - warn <<'END'; + die <<'END'; Warning: MIN_PERL_VERSION is not in a recognized format. Recommended is a quoted numerical value like '5.005' or '5.008001'. END @@ -467,14 +490,16 @@ END if (!$installed_file) { warn sprintf "Warning: prerequisite %s %s not found.\n", $prereq, $required_version - unless $self->{PREREQ_FATAL}; + unless $self->{PREREQ_FATAL} + or $ENV{PERL_CORE}; $unsatisfied{$prereq} = 'not installed'; } elsif ($pr_version < $required_version ){ warn sprintf "Warning: prerequisite %s %s not found. We have %s.\n", $prereq, $required_version, ($pr_version || 'unknown version') - unless $self->{PREREQ_FATAL}; + unless $self->{PREREQ_FATAL} + or $ENV{PERL_CORE}; $unsatisfied{$prereq} = $required_version ? $required_version : 'unknown version' ; } @@ -494,15 +519,16 @@ END if (defined $self->{CONFIGURE}) { if (ref $self->{CONFIGURE} eq 'CODE') { %configure_att = %{&{$self->{CONFIGURE}}}; + _convert_compat_attrs(\%configure_att); $self = { %$self, %configure_att }; } else { - Carp::croak "Attribute 'CONFIGURE' to WriteMakefile() not a code reference\n"; + croak "Attribute 'CONFIGURE' to WriteMakefile() not a code reference\n"; } } # This is for old Makefiles written pre 5.00, will go away if ( Carp::longmess("") =~ /runsubdirpl/s ){ - Carp::carp("WARNING: Please rerun 'perl Makefile.PL' to regenerate your Makefiles\n"); + carp("WARNING: Please rerun 'perl Makefile.PL' to regenerate your Makefiles\n"); } my $newclass = ++$PACKNAME; @@ -673,11 +699,11 @@ END } sub WriteEmptyMakefile { - Carp::croak "WriteEmptyMakefile: Need an even number of args" if @_ % 2; + croak "WriteEmptyMakefile: Need an even number of args" if @_ % 2; my %att = @_; my $self = MM->new(\%att); - + my $new = $self->{MAKEFILE}; my $old = $self->{MAKEFILE_OLD}; if (-f $old) { @@ -998,16 +1024,24 @@ sub flush { or die "Unable to open MakeMaker.tmp: $!"; for my $chunk (@{$self->{RESULT}}) { - print $fh "$chunk\n"; + print $fh "$chunk\n" + or die "Can't write to MakeMaker.tmp: $!"; } - close $fh; + close $fh + or die "Can't write to MakeMaker.tmp: $!"; _rename("MakeMaker.tmp", $finalname) or warn "rename MakeMaker.tmp => $finalname: $!"; chmod 0644, $finalname unless $Is_VMS; - my %keep = map { ($_ => 1) } qw(NEEDS_LINKING HAS_LINK_CODE); + unless ($self->{NO_MYMETA}) { + # Write MYMETA.yml to communicate metadata up to the CPAN clients + if ( $self->write_mymeta( $self->mymeta ) ) {; + print STDOUT "Writing MYMETA.yml and MYMETA.json\n"; + } + } + my %keep = map { ($_ => 1) } qw(NEEDS_LINKING HAS_LINK_CODE); if ($self->{PARENT} && !$self->{_KEEP_AFTER_FLUSH}) { foreach (keys %$self) { # safe memory delete $self->{$_} unless $keep{$_}; @@ -1017,7 +1051,6 @@ sub flush { system("$Config::Config{eunicefix} $finalname") unless $Config::Config{eunicefix} eq ":"; } - # This is a rename for OS's where the target must be unlinked first. sub _rename { my($src, $dest) = @_; @@ -1078,6 +1111,22 @@ sub neatvalue { return "{ ".join(', ',@m)." }"; } +# Look for weird version numbers, warn about them and set them to 0 +# before CPAN::Meta chokes. +sub clean_versions { + my($self, $key) = @_; + + my $reqs = $self->{$key}; + for my $module (keys %$reqs) { + my $version = $reqs->{$module}; + + if( !defined $version or $version !~ /^[\d_\.]+$/ ) { + carp "Unparsable version '$version' for prerequisite $module"; + $reqs->{$module} = 0; + } + } +} + sub selfdocument { my($self) = @_; my(@m); @@ -1465,8 +1514,9 @@ the first line in the "=head1 NAME" section. $2 becomes the abstract. =item AUTHOR -String containing name (and email address) of package author(s). Is used -in PPD (Perl Package Description) files for PPM (Perl Package Manager). +Array of strings containing name (and email address) of package author(s). +Is used in CPAN Meta files (META.yml or META.json) and PPD +(Perl Package Description) files for PPM (Perl Package Manager). =item BINARY_LOCATION @@ -1483,7 +1533,8 @@ located in the C directory relative to the PPD itself. A hash of modules that are needed to build your module but not run it. -This will go into the C field of your F. +This will go into the C field of your CPAN Meta file. +(F or F). The format is the same as PREREQ_PM. @@ -1530,7 +1581,8 @@ be determined by some evaluation method. A hash of modules that are required to run Makefile.PL itself, but not to run your distribution. -This will go into the C field of your F. +This will go into the C field of your CPAN Meta file +(F or F) Defaults to C<<< { "ExtUtils::MakeMaker" => 0 } >>> @@ -1937,10 +1989,11 @@ may hold a name for that binary. Defaults to perl =item META_MERGE -A hashrefs of items to add to the F. +A hashrefs of items to add to the CPAN Meta file (F or +F). They differ in how they behave if they have the same key as the -default metadata. META_ADD will override the default value with it's +default metadata. META_ADD will override the default value with its own. META_MERGE will merge its value with the default. Unless you want to override the defaults, prefer META_MERGE so as to @@ -1986,7 +2039,14 @@ Boolean. Attribute to inhibit descending into subdirectories. =item NO_META When true, suppresses the generation and addition to the MANIFEST of -the META.yml module meta-data file during 'make distdir'. +the META.yml and META.json module meta-data files during 'make distdir'. + +Defaults to false. + +=item NO_MYMETA + +When true, suppresses the generation of MYMETA.yml and MYMETA.json module +meta-data files during 'perl Makefile.PL'. Defaults to false. @@ -2225,18 +2285,17 @@ will C instead of simply informing the user of the missing dependencies. It is I rare to have to use C. Its use by module authors is I and should never be used lightly. + Module installation tools have ways of resolving umet dependencies but to do that they need a F. Using C breaks this. That's bad. -The only situation where it is appropriate is when you have -dependencies that are indispensible to actually I a -F. For example, MakeMaker's F needs L. -If its not available it cannot write the F. +Assuming you have good test coverage, your tests should fail with +missing dependencies informing the user more strongly that something +is wrong. You can write a F test which will simply +check that your code compiles and stop "make test" prematurely if it +doesn't. See L for more details. -Note: see L for a shortcut for stopping tests early -if you are missing dependencies and are afraid that users might -use your module with an incomplete environment. =item PREREQ_PM @@ -2244,7 +2303,8 @@ A hash of modules that are needed to run your module. The keys are the module names ie. Test::More, and the minimum version is the value. If the required version number is 0 any version will do. -This will go into the C field of your F. +This will go into the C field of your CPAN Meta file +(F or F). PREREQ_PM => { # Require Test::More at least 0.47 @@ -2609,8 +2669,8 @@ Copies all the files that are in the MANIFEST file to a newly created directory with the name C<$(DISTNAME)-$(VERSION)>. If that directory exists, it will be removed first. -Additionally, it will create a META.yml module meta-data file in the -distdir and add this to the distdir's MANIFEST. You can shut this +Additionally, it will create META.yml and META.json module meta-data file +in the distdir and add this to the distdir's MANIFEST. You can shut this behavior off with the NO_META flag. =item make disttest @@ -2684,26 +2744,37 @@ An example: ); -=head2 Module Meta-Data +=head2 Module Meta-Data (META and MYMETA) Long plaguing users of MakeMaker based modules has been the problem of getting basic information about the module out of the sources I running the F and doing a bunch of messy -heuristics on the resulting F. To this end a simple module -meta-data file has been introduced, F. - -F is a YAML document (see http://www.yaml.org) containing -basic information about the module (name, version, prerequisites...) -in an easy to read format. The format is developed and defined by the -Module::Build developers (see -http://module-build.sourceforge.net/META-spec.html) - -MakeMaker will automatically generate a F file for you and -add it to your F as part of the 'distdir' target (and thus -the 'dist' target). This is intended to seamlessly and rapidly -populate CPAN with module meta-data. If you wish to shut this feature -off, set the C C flag to true. - +heuristics on the resulting F. Over the years, it has become +standard to keep this information in one or more CPAN Meta files +distributed with each distribution. + +The original format of CPAN Meta files was L and the corresponding +file was called F. In 2010, version 2 of the L +was released, which mandates JSON format for the metadata in order to +overcome certain compatibility issues between YAML serializers and to +avoid breaking older clients unable to handle a new version of the spec. +The L library is now standard for accessing old and new-style +Meta files. + +If L is installed, MakeMaker will automatically generate +F and F files for you and add them to your F as +part of the 'distdir' target (and thus the 'dist' target). This is intended to +seamlessly and rapidly populate CPAN with module meta-data. If you wish to +shut this feature off, set the C C flag to true. + +At the 2008 QA Hackathon in Oslo, Perl module toolchain maintainers agrees +to use the CPAN Meta format to communicate post-configuration requirements +between toolchain components. These files, F and F, +are generated when F generates a F (if L +is installed). Clients like L or L will read this +files to see what prerequisites must be fulfilled before building or testing +the distribution. If you with to shut this feature off, set the C +C flag to true. =head2 Disabling an extension @@ -2780,6 +2851,8 @@ not normally available. L and L are both modules to help you setup your distribution. +L and L explain CPAN Meta files in detail. + =head1 AUTHORS Andy Dougherty C, Andreas KEnig @@ -2796,6 +2869,8 @@ generated Makefile along with your report. For more up-to-date information, see L. +Repository available at L. + =head1 LICENSE This program is free software; you can redistribute it and/or diff --git a/perl/lib/ExtUtils/MakeMaker/Config.pm b/perl/lib/ExtUtils/MakeMaker/Config.pm index 38b60af..c9035b1 100644 --- a/perl/lib/ExtUtils/MakeMaker/Config.pm +++ b/perl/lib/ExtUtils/MakeMaker/Config.pm @@ -2,7 +2,7 @@ package ExtUtils::MakeMaker::Config; use strict; -our $VERSION = '6.56'; +our $VERSION = '6.62'; use Config (); diff --git a/perl/lib/ExtUtils/MakeMaker/FAQ.pod b/perl/lib/ExtUtils/MakeMaker/FAQ.pod index d33f82e..ff75639 100644 --- a/perl/lib/ExtUtils/MakeMaker/FAQ.pod +++ b/perl/lib/ExtUtils/MakeMaker/FAQ.pod @@ -1,6 +1,6 @@ package ExtUtils::MakeMaker::FAQ; -our $VERSION = '1.12'; +our $VERSION = '6.62'; 1; __END__ @@ -241,7 +241,7 @@ do that. Use at your own risk. Have fun blowing holes in your foot. use File::Spec; use File::Find; use ExtUtils::Manifest qw(maniread); - + my %manifest = map {( $_ => 1 )} grep { File::Spec->canonpath($_) } keys %{ maniread() }; @@ -250,14 +250,14 @@ do that. Use at your own risk. Have fun blowing holes in your foot. print "No files found in MANIFEST. Stopping.\n"; exit; } - + find({ wanted => sub { my $path = File::Spec->canonpath($_); - + return unless -f $path; return if exists $manifest{ $path }; - + print "unlink $path\n"; unlink $path; }, @@ -267,6 +267,10 @@ do that. Use at your own risk. Have fun blowing holes in your foot. ); +=item Which tar should I use on Windows? + +We recommend ptar from Archive::Tar not older that 1.66 with '-C' option. + =item Which zip should I use on Windows for '[nd]make zipdist'? We recommend InfoZIP: L diff --git a/perl/lib/ExtUtils/MakeMaker/Tutorial.pod b/perl/lib/ExtUtils/MakeMaker/Tutorial.pod index 8ad7264..f7944b9 100644 --- a/perl/lib/ExtUtils/MakeMaker/Tutorial.pod +++ b/perl/lib/ExtUtils/MakeMaker/Tutorial.pod @@ -1,6 +1,6 @@ package ExtUtils::MakeMaker::Tutorial; -our $VERSION = 0.02; +our $VERSION = 6.62; =head1 NAME diff --git a/perl/lib/ExtUtils/Mkbootstrap.pm b/perl/lib/ExtUtils/Mkbootstrap.pm index 707466a..d2fcd6b 100644 --- a/perl/lib/ExtUtils/Mkbootstrap.pm +++ b/perl/lib/ExtUtils/Mkbootstrap.pm @@ -3,7 +3,7 @@ package ExtUtils::Mkbootstrap; # There's just too much Dynaloader incest here to turn on strict vars. use strict 'refs'; -our $VERSION = '6.56'; +our $VERSION = '6.62'; require Exporter; our @ISA = ('Exporter'); diff --git a/perl/lib/ExtUtils/Mksymlists.pm b/perl/lib/ExtUtils/Mksymlists.pm index 962c67f..e80c971 100644 --- a/perl/lib/ExtUtils/Mksymlists.pm +++ b/perl/lib/ExtUtils/Mksymlists.pm @@ -10,7 +10,7 @@ use Config; our @ISA = qw(Exporter); our @EXPORT = qw(&Mksymlists); -our $VERSION = '6.56'; +our $VERSION = '6.62'; sub Mksymlists { my(%spec) = @_; diff --git a/perl/lib/ExtUtils/testlib.pm b/perl/lib/ExtUtils/testlib.pm index fe01beb..51b55e9 100644 --- a/perl/lib/ExtUtils/testlib.pm +++ b/perl/lib/ExtUtils/testlib.pm @@ -3,7 +3,7 @@ package ExtUtils::testlib; use strict; use warnings; -our $VERSION = 6.56; +our $VERSION = '6.62'; use Cwd; use File::Spec; diff --git a/perl/lib/perllocal.pod b/perl/lib/perllocal.pod index 4139620..fae70ec 100644 --- a/perl/lib/perllocal.pod +++ b/perl/lib/perllocal.pod @@ -7544,3 +7544,25 @@ C =back +=head2 Tue Jan 31 17:47:18 2012: C L + +=over 4 + +=item * + +C + +=item * + +C + +=item * + +C + +=item * + +C + +=back + diff --git a/perl/vendor/lib/CPAN/Meta.pm b/perl/vendor/lib/CPAN/Meta.pm deleted file mode 100644 index 138aee3..0000000 --- a/perl/vendor/lib/CPAN/Meta.pm +++ /dev/null @@ -1,700 +0,0 @@ -use 5.006; -use strict; -use warnings; -package CPAN::Meta; -BEGIN { - $CPAN::Meta::VERSION = '2.110930'; -} -# ABSTRACT: the distribution metadata for a CPAN dist - - -use Carp qw(carp croak); -use CPAN::Meta::Feature; -use CPAN::Meta::Prereqs; -use CPAN::Meta::Converter; -use CPAN::Meta::Validator; -use Parse::CPAN::Meta 1.4400 (); - -sub _dclone { - my $ref = shift; - my $backend = Parse::CPAN::Meta->json_backend(); - return $backend->new->decode( - $backend->new->convert_blessed->encode($ref) - ); -} - - -BEGIN { - my @STRING_READERS = qw( - abstract - description - dynamic_config - generated_by - name - release_status - version - ); - - no strict 'refs'; - for my $attr (@STRING_READERS) { - *$attr = sub { $_[0]{ $attr } }; - } -} - - -BEGIN { - my @LIST_READERS = qw( - author - keywords - license - ); - - no strict 'refs'; - for my $attr (@LIST_READERS) { - *$attr = sub { - my $value = $_[0]{ $attr }; - croak "$attr must be called in list context" - unless wantarray; - return @{ _dclone($value) } if ref $value; - return $value; - }; - } -} - -sub authors { $_[0]->author } -sub licenses { $_[0]->license } - - -BEGIN { - my @MAP_READERS = qw( - meta-spec - resources - provides - no_index - - prereqs - optional_features - ); - - no strict 'refs'; - for my $attr (@MAP_READERS) { - (my $subname = $attr) =~ s/-/_/; - *$subname = sub { - my $value = $_[0]{ $attr }; - return _dclone($value) if $value; - return {}; - }; - } -} - - -sub custom_keys { - return grep { /^x_/i } keys %{$_[0]}; -} - -sub custom { - my ($self, $attr) = @_; - my $value = $self->{$attr}; - return _dclone($value) if ref $value; - return $value; -} - - -sub _new { - my ($class, $struct, $options) = @_; - my $self; - - if ( $options->{lazy_validation} ) { - # try to convert to a valid structure; if succeeds, then return it - my $cmc = CPAN::Meta::Converter->new( $struct ); - $self = $cmc->convert( version => 2 ); # valid or dies - return bless $self, $class; - } - else { - # validate original struct - my $cmv = CPAN::Meta::Validator->new( $struct ); - unless ( $cmv->is_valid) { - die "Invalid metadata structure. Errors: " - . join(", ", $cmv->errors) . "\n"; - } - } - - # up-convert older spec versions - my $version = $struct->{'meta-spec'}{version} || '1.0'; - if ( $version == 2 ) { - $self = $struct; - } - else { - my $cmc = CPAN::Meta::Converter->new( $struct ); - $self = $cmc->convert( version => 2 ); - } - - return bless $self, $class; -} - -sub new { - my ($class, $struct, $options) = @_; - my $self = eval { $class->_new($struct, $options) }; - croak($@) if $@; - return $self; -} - - -sub create { - my ($class, $struct, $options) = @_; - my $version = __PACKAGE__->VERSION || 2; - $struct->{generated_by} ||= __PACKAGE__ . " version $version" ; - $struct->{'meta-spec'}{version} ||= int($version); - my $self = eval { $class->_new($struct, $options) }; - croak ($@) if $@; - return $self; -} - - -sub load_file { - my ($class, $file, $options) = @_; - $options->{lazy_validation} = 1 unless exists $options->{lazy_validation}; - - croak "load_file() requires a valid, readable filename" - unless -r $file; - - my $self; - eval { - my $struct = Parse::CPAN::Meta->load_file( $file ); - $self = $class->_new($struct, $options); - }; - croak($@) if $@; - return $self; -} - - -sub load_yaml_string { - my ($class, $yaml, $options) = @_; - $options->{lazy_validation} = 1 unless exists $options->{lazy_validation}; - - my $self; - eval { - my ($struct) = Parse::CPAN::Meta->load_yaml_string( $yaml ); - $self = $class->_new($struct, $options); - }; - croak($@) if $@; - return $self; -} - - -sub load_json_string { - my ($class, $json, $options) = @_; - $options->{lazy_validation} = 1 unless exists $options->{lazy_validation}; - - my $self; - eval { - my $struct = Parse::CPAN::Meta->load_json_string( $json ); - $self = $class->_new($struct, $options); - }; - croak($@) if $@; - return $self; -} - - -sub save { - my ($self, $file, $options) = @_; - - my $version = $options->{version} || '2'; - my $layer = $] ge '5.008001' ? ':utf8' : ''; - - if ( $version ge '2' ) { - carp "'$file' should end in '.json'" - unless $file =~ m{\.json$}; - } - else { - carp "'$file' should end in '.yml'" - unless $file =~ m{\.yml$}; - } - - my $data = $self->as_string( $options ); - open my $fh, ">$layer", $file - or die "Error opening '$file' for writing: $!\n"; - - print {$fh} $data; - close $fh - or die "Error closing '$file': $!\n"; - - return 1; -} - - -sub meta_spec_version { - my ($self) = @_; - return $self->meta_spec->{version}; -} - - -sub effective_prereqs { - my ($self, $features) = @_; - $features ||= []; - - my $prereq = CPAN::Meta::Prereqs->new($self->prereqs); - - return $prereq unless @$features; - - my @other = map {; $self->feature($_)->prereqs } @$features; - - return $prereq->with_merged_prereqs(\@other); -} - - -sub should_index_file { - my ($self, $filename) = @_; - - for my $no_index_file (@{ $self->no_index->{file} || [] }) { - return if $filename eq $no_index_file; - } - - for my $no_index_dir (@{ $self->no_index->{directory} }) { - $no_index_dir =~ s{$}{/} unless $no_index_dir =~ m{/\z}; - return if index($filename, $no_index_dir) == 0; - } - - return 1; -} - - -sub should_index_package { - my ($self, $package) = @_; - - for my $no_index_pkg (@{ $self->no_index->{package} || [] }) { - return if $package eq $no_index_pkg; - } - - for my $no_index_ns (@{ $self->no_index->{namespace} }) { - return if index($package, "${no_index_ns}::") == 0; - } - - return 1; -} - - -sub features { - my ($self) = @_; - - my $opt_f = $self->optional_features; - my @features = map {; CPAN::Meta::Feature->new($_ => $opt_f->{ $_ }) } - keys %$opt_f; - - return @features; -} - - -sub feature { - my ($self, $ident) = @_; - - croak "no feature named $ident" - unless my $f = $self->optional_features->{ $ident }; - - return CPAN::Meta::Feature->new($ident, $f); -} - - -sub as_struct { - my ($self, $options) = @_; - my $struct = _dclone($self); - if ( $options->{version} ) { - my $cmc = CPAN::Meta::Converter->new( $struct ); - $struct = $cmc->convert( version => $options->{version} ); - } - return $struct; -} - - -sub as_string { - my ($self, $options) = @_; - - my $version = $options->{version} || '2'; - - my $struct; - if ( $self->meta_spec_version ne $version ) { - my $cmc = CPAN::Meta::Converter->new( $self->as_struct ); - $struct = $cmc->convert( version => $version ); - } - else { - $struct = $self->as_struct; - } - - my ($data, $backend); - if ( $version ge '2' ) { - $backend = Parse::CPAN::Meta->json_backend(); - $data = $backend->new->pretty->canonical->encode($struct); - } - else { - $backend = Parse::CPAN::Meta->yaml_backend(); - $data = eval { no strict 'refs'; &{"$backend\::Dump"}($struct) }; - if ( $@ ) { - croak $backend->can('errstr') ? $backend->errstr : $@ - } - } - - return $data; -} - -# Used by JSON::PP, etc. for "convert_blessed" -sub TO_JSON { - return { %{ $_[0] } }; -} - -1; - - - -=pod - -=head1 NAME - -CPAN::Meta - the distribution metadata for a CPAN dist - -=head1 VERSION - -version 2.110930 - -=head1 SYNOPSIS - - my $meta = CPAN::Meta->load_file('META.json'); - - printf "testing requirements for %s version %s\n", - $meta->name, - $meta->version; - - my $prereqs = $meta->requirements_for('configure'); - - for my $module ($prereqs->required_modules) { - my $version = get_local_version($module); - - die "missing required module $module" unless defined $version; - die "version for $module not in range" - unless $prereqs->accepts_module($module, $version); - } - -=head1 DESCRIPTION - -Software distributions released to the CPAN include a F or, for -older distributions, F, which describes the distribution, its -contents, and the requirements for building and installing the distribution. -The data structure stored in the F file is described in -L. - -CPAN::Meta provides a simple class to represent this distribution metadata (or -I), along with some helpful methods for interrogating that data. - -The documentation below is only for the methods of the CPAN::Meta object. For -information on the meaning of individual fields, consult the spec. - -=head1 METHODS - -=head2 new - - my $meta = CPAN::Meta->new($distmeta_struct, \%options); - -Returns a valid CPAN::Meta object or dies if the supplied metadata hash -reference fails to validate. Older-format metadata will be up-converted to -version 2 if they validate against the original stated specification. - -It takes an optional hashref of options. Valid options include: - -=over - -=item * - -lazy_validation -- if true, new will attempt to convert the given metadata -to version 2 before attempting to validate it. This means than any -fixable errors will be handled by CPAN::Meta::Converter before validation. -(Note that this might result in invalid optional data being silently -dropped.) The default is false. - -=back - -=head2 create - - my $meta = CPAN::Meta->create($distmeta_struct, \%options); - -This is same as C, except that C and C fields -will be generated if not provided. This means the metadata structure is -assumed to otherwise follow the latest L. - -=head2 load_file - - my $meta = CPAN::Meta->load_file($distmeta_file, \%options); - -Given a pathname to a file containing metadata, this deserializes the file -according to its file suffix and constructs a new C object, just -like C. It will die if the deserialized version fails to validate -against its stated specification version. - -It takes the same options as C but C defaults to -true. - -=head2 load_yaml_string - - my $meta = CPAN::Meta->load_yaml_string($yaml, \%options); - -This method returns a new CPAN::Meta object using the first document in the -given YAML string. In other respects it is identical to C. - -=head2 load_json_string - - my $meta = CPAN::Meta->load_json_string($json, \%options); - -This method returns a new CPAN::Meta object using the structure represented by -the given JSON string. In other respects it is identical to C. - -=head2 save - - $meta->save($distmeta_file, \%options); - -Serializes the object as JSON and writes it to the given file. The only valid -option is C, which defaults to '2'. On Perl 5.8.1 or later, the file -is saved with UTF-8 encoding. - -For C 2 (or higher), the filename should end in '.json'. L -is the default JSON backend. Using another JSON backend requires L 2.5 or -later and you must set the C<$ENV{PERL_JSON_BACKEND}> to a supported alternate -backend like L. - -For C less than 2, the filename should end in '.yml'. -L is used to generate an older metadata structure, which -is serialized to YAML. CPAN::Meta::YAML is the default YAML backend. You may -set the C<$ENV{PERL_YAML_BACKEND}> to a supported alternative backend, though -this is not recommended due to subtle incompatibilities between YAML parsers on -CPAN. - -=head2 meta_spec_version - -This method returns the version part of the C entry in the distmeta -structure. It is equivalent to: - - $meta->meta_spec->{version}; - -=head2 effective_prereqs - - my $prereqs = $meta->effective_prereqs; - - my $prereqs = $meta->effective_prereqs( \@feature_identifiers ); - -This method returns a L object describing all the -prereqs for the distribution. If an arrayref of feature identifiers is given, -the prereqs for the identified features are merged together with the -distribution's core prereqs before the CPAN::Meta::Prereqs object is returned. - -=head2 should_index_file - - ... if $meta->should_index_file( $filename ); - -This method returns true if the given file should be indexed. It decides this -by checking the C and C keys in the C property of -the distmeta structure. - -C<$filename> should be given in unix format. - -=head2 should_index_package - - ... if $meta->should_index_package( $package ); - -This method returns true if the given package should be indexed. It decides -this by checking the C and C keys in the C -property of the distmeta structure. - -=head2 features - - my @feature_objects = $meta->features; - -This method returns a list of L objects, one for each -optional feature described by the distribution's metadata. - -=head2 feature - - my $feature_object = $meta->feature( $identifier ); - -This method returns a L object for the optional feature -with the given identifier. If no feature with that identifier exists, an -exception will be raised. - -=head2 as_struct - - my $copy = $meta->as_struct( \%options ); - -This method returns a deep copy of the object's metadata as an unblessed has -reference. It takes an optional hashref of options. If the hashref contains -a C argument, the copied metadata will be converted to the version -of the specification and returned. For example: - - my $old_spec = $meta->as_struct( {version => "1.4"} ); - -=head2 as_string - - my $string = $meta->as_string( \%options ); - -This method returns a serialized copy of the object's metadata as a character -string. (The strings are B UTF-8 encoded.) It takes an optional hashref -of options. If the hashref contains a C argument, the copied metadata -will be converted to the version of the specification and returned. For -example: - - my $string = $meta->as_struct( {version => "1.4"} ); - -For C greater than or equal to 2, the string will be serialized as -JSON. For C less than 2, the string will be serialized as YAML. In -both cases, the same rules are followed as in the C method for choosing -a serialization backend. - -=head1 STRING DATA - -The following methods return a single value, which is the value for the -corresponding entry in the distmeta structure. Values should be either undef -or strings. - -=over 4 - -=item * - -abstract - -=item * - -description - -=item * - -dynamic_config - -=item * - -generated_by - -=item * - -name - -=item * - -release_status - -=item * - -version - -=back - -=head1 LIST DATA - -These methods return lists of string values, which might be represented in the -distmeta structure as arrayrefs or scalars: - -=over 4 - -=item * - -authors - -=item * - -keywords - -=item * - -licenses - -=back - -The C and C methods may also be called as C and -C, respectively, to match the field name in the distmeta structure. - -=head1 MAP DATA - -These readers return hashrefs of arbitrary unblessed data structures, each -described more fully in the specification: - -=over 4 - -=item * - -meta_spec - -=item * - -resources - -=item * - -provides - -=item * - -no_index - -=item * - -prereqs - -=item * - -optional_features - -=back - -=head1 CUSTOM DATA - -A list of custom keys are available from the C method and -particular keys may be retrieved with the C method. - - say $meta->custom($_) for $meta->custom_keys; - -If a custom key refers to a data structure, a deep clone is returned. - -=head1 BUGS - -Please report any bugs or feature using the CPAN Request Tracker. -Bugs can be submitted through the web interface at -L - -When submitting a bug or request, please include a test-file or a patch to an -existing test-file that illustrates the bug or desired feature. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=back - -=head1 AUTHORS - -=over 4 - -=item * - -David Golden - -=item * - -Ricardo Signes - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 2010 by David Golden and Ricardo Signes. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - - -__END__ - - diff --git a/perl/vendor/lib/CPAN/Meta/Converter.pm b/perl/vendor/lib/CPAN/Meta/Converter.pm deleted file mode 100644 index 311a93d..0000000 --- a/perl/vendor/lib/CPAN/Meta/Converter.pm +++ /dev/null @@ -1,1376 +0,0 @@ -use 5.006; -use strict; -use warnings; -package CPAN::Meta::Converter; -BEGIN { - $CPAN::Meta::Converter::VERSION = '2.110930'; -} -# ABSTRACT: Convert CPAN distribution metadata structures - - -use CPAN::Meta::Validator; -use version 0.82 (); -use Parse::CPAN::Meta 1.4400 (); - -sub _dclone { - my $ref = shift; - my $backend = Parse::CPAN::Meta->json_backend(); - return $backend->new->decode( - $backend->new->convert_blessed->encode($ref) - ); -} - -my %known_specs = ( - '2' => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec', - '1.4' => 'http://module-build.sourceforge.net/META-spec-v1.4.html', - '1.3' => 'http://module-build.sourceforge.net/META-spec-v1.3.html', - '1.2' => 'http://module-build.sourceforge.net/META-spec-v1.2.html', - '1.1' => 'http://module-build.sourceforge.net/META-spec-v1.1.html', - '1.0' => 'http://module-build.sourceforge.net/META-spec-v1.0.html' -); - -my @spec_list = sort { $a <=> $b } keys %known_specs; -my ($LOWEST, $HIGHEST) = @spec_list[0,-1]; - -#--------------------------------------------------------------------------# -# converters -# -# called as $converter->($element, $field_name, $full_meta, $to_version) -# -# defined return value used for field -# undef return value means field is skipped -#--------------------------------------------------------------------------# - -sub _keep { $_[0] } - -sub _keep_or_one { defined($_[0]) ? $_[0] : 1 } - -sub _keep_or_zero { defined($_[0]) ? $_[0] : 0 } - -sub _keep_or_unknown { defined($_[0]) && length($_[0]) ? $_[0] : "unknown" } - -sub _generated_by { - my $gen = shift; - my $sig = __PACKAGE__ . " version " . (__PACKAGE__->VERSION || ""); - - return $sig unless defined $gen and length $gen; - return $gen if $gen =~ /(, )\Q$sig/; - return "$gen, $sig"; -} - -sub _listify { ! defined $_[0] ? undef : ref $_[0] eq 'ARRAY' ? $_[0] : [$_[0]] } - -sub _prefix_custom { - my $key = shift; - $key =~ s/^(?!x_) # Unless it already starts with x_ - (?:x-?)? # Remove leading x- or x (if present) - /x_/ix; # and prepend x_ - return $key; -} - -sub _ucfirst_custom { - my $key = shift; - $key = ucfirst $key unless $key =~ /[A-Z]/; - return $key; -} - -sub _change_meta_spec { - my ($element, undef, undef, $version) = @_; - $element->{version} = $version; - $element->{url} = $known_specs{$version}; - return $element; -} - -my @valid_licenses_1 = ( - 'perl', - 'gpl', - 'apache', - 'artistic', - 'artistic_2', - 'lgpl', - 'bsd', - 'gpl', - 'mit', - 'mozilla', - 'open_source', - 'unrestricted', - 'restrictive', - 'unknown', -); - -my %license_map_1 = ( - ( map { $_ => $_ } @valid_licenses_1 ), - artistic2 => 'artistic_2', -); - -sub _license_1 { - my ($element) = @_; - return 'unknown' unless defined $element; - if ( $license_map_1{lc $element} ) { - return $license_map_1{lc $element}; - } - return 'unknown'; -} - -my @valid_licenses_2 = qw( - agpl_3 - apache_1_1 - apache_2_0 - artistic_1 - artistic_2 - bsd - freebsd - gfdl_1_2 - gfdl_1_3 - gpl_1 - gpl_2 - gpl_3 - lgpl_2_1 - lgpl_3_0 - mit - mozilla_1_0 - mozilla_1_1 - openssl - perl_5 - qpl_1_0 - ssleay - sun - zlib - open_source - restricted - unrestricted - unknown -); - -# The "old" values were defined by Module::Build, and were often vague. I have -# made the decisions below based on reading Module::Build::API and how clearly -# it specifies the version of the license. -my %license_map_2 = ( - (map { $_ => $_ } @valid_licenses_2), - apache => 'apache_2_0', # clearly stated as 2.0 - artistic => 'artistic_1', # clearly stated as 1 - artistic2 => 'artistic_2', # clearly stated as 2 - gpl => 'open_source', # we don't know which GPL; punt - lgpl => 'open_source', # we don't know which LGPL; punt - mozilla => 'open_source', # we don't know which MPL; punt - perl => 'perl_5', # clearly Perl 5 - restrictive => 'restricted', -); - -sub _license_2 { - my ($element) = @_; - return [ 'unknown' ] unless defined $element; - $element = [ $element ] unless ref $element eq 'ARRAY'; - my @new_list; - for my $lic ( @$element ) { - next unless defined $lic; - if ( my $new = $license_map_2{lc $lic} ) { - push @new_list, $new; - } - } - return @new_list ? \@new_list : [ 'unknown' ]; -} - -my %license_downgrade_map = qw( - agpl_3 open_source - apache_1_1 apache - apache_2_0 apache - artistic_1 artistic - artistic_2 artistic_2 - bsd bsd - freebsd open_source - gfdl_1_2 open_source - gfdl_1_3 open_source - gpl_1 gpl - gpl_2 gpl - gpl_3 gpl - lgpl_2_1 lgpl - lgpl_3_0 lgpl - mit mit - mozilla_1_0 mozilla - mozilla_1_1 mozilla - openssl open_source - perl_5 perl - qpl_1_0 open_source - ssleay open_source - sun open_source - zlib open_source - open_source open_source - restricted restrictive - unrestricted unrestricted - unknown unknown -); - -sub _downgrade_license { - my ($element) = @_; - if ( ! defined $element ) { - return "unknown"; - } - elsif( ref $element eq 'ARRAY' ) { - if ( @$element == 1 ) { - return $license_downgrade_map{$element->[0]} || "unknown"; - } - } - elsif ( ! ref $element ) { - return $license_downgrade_map{$element} || "unknown"; - } - return "unknown"; -} - -my $no_index_spec_1_2 = { - 'file' => \&_listify, - 'dir' => \&_listify, - 'package' => \&_listify, - 'namespace' => \&_listify, -}; - -my $no_index_spec_1_3 = { - 'file' => \&_listify, - 'directory' => \&_listify, - 'package' => \&_listify, - 'namespace' => \&_listify, -}; - -my $no_index_spec_2 = { - 'file' => \&_listify, - 'directory' => \&_listify, - 'package' => \&_listify, - 'namespace' => \&_listify, - ':custom' => \&_prefix_custom, -}; - -sub _no_index_1_2 { - my (undef, undef, $meta) = @_; - my $no_index = $meta->{no_index} || $meta->{private}; - return unless $no_index; - - # cleanup wrong format - if ( ! ref $no_index ) { - my $item = $no_index; - $no_index = { dir => [ $item ], file => [ $item ] }; - } - elsif ( ref $no_index eq 'ARRAY' ) { - my $list = $no_index; - $no_index = { dir => [ @$list ], file => [ @$list ] }; - } - - # common mistake: files -> file - if ( exists $no_index->{files} ) { - $no_index->{file} = delete $no_index->{file}; - } - # common mistake: modules -> module - if ( exists $no_index->{modules} ) { - $no_index->{module} = delete $no_index->{module}; - } - return _convert($no_index, $no_index_spec_1_2); -} - -sub _no_index_directory { - my ($element, $key, $meta, $version) = @_; - return unless $element; - - # cleanup wrong format - if ( ! ref $element ) { - my $item = $element; - $element = { directory => [ $item ], file => [ $item ] }; - } - elsif ( ref $element eq 'ARRAY' ) { - my $list = $element; - $element = { directory => [ @$list ], file => [ @$list ] }; - } - - if ( exists $element->{dir} ) { - $element->{directory} = delete $element->{dir}; - } - # common mistake: files -> file - if ( exists $element->{files} ) { - $element->{file} = delete $element->{file}; - } - # common mistake: modules -> module - if ( exists $element->{modules} ) { - $element->{module} = delete $element->{module}; - } - my $spec = $version == 2 ? $no_index_spec_2 : $no_index_spec_1_3; - return _convert($element, $spec); -} - -sub _is_module_name { - my $mod = shift; - return unless defined $mod && length $mod; - return $mod =~ m{^[A-Za-z][A-Za-z0-9_]*(?:::[A-Za-z0-9_]+)*$}; -} - -sub _clean_version { - my ($element, $key, $meta, $to_version) = @_; - return 0 if ! defined $element; - - $element =~ s{^\s*}{}; - $element =~ s{\s*$}{}; - $element =~ s{^\.}{0.}; - - return 0 if ! length $element; - return 0 if ( $element eq 'undef' || $element eq '' ); - - if ( my $v = eval { version->new($element) } ) { - return $v->is_qv ? $v->normal : $element; - } - else { - return 0; - } -} - -sub _version_map { - my ($element) = @_; - return undef unless defined $element; - if ( ref $element eq 'HASH' ) { - my $new_map = {}; - for my $k ( keys %$element ) { - next unless _is_module_name($k); - my $value = $element->{$k}; - if ( ! ( defined $value && length $value ) ) { - $new_map->{$k} = 0; - } - elsif ( $value eq 'undef' || $value eq '' ) { - $new_map->{$k} = 0; - } - elsif ( _is_module_name( $value ) ) { # some weird, old META have this - $new_map->{$k} = 0; - $new_map->{$value} = 0; - } - else { - $new_map->{$k} = _clean_version($value); - } - } - return $new_map; - } - elsif ( ref $element eq 'ARRAY' ) { - my $hashref = { map { $_ => 0 } @$element }; - return _version_map($hashref); # cleanup any weird stuff - } - elsif ( ref $element eq '' && length $element ) { - return { $element => 0 } - } - return; -} - -sub _prereqs_from_1 { - my (undef, undef, $meta) = @_; - my $prereqs = {}; - for my $phase ( qw/build configure/ ) { - my $key = "${phase}_requires"; - $prereqs->{$phase}{requires} = _version_map($meta->{$key}) - if $meta->{$key}; - } - for my $rel ( qw/requires recommends conflicts/ ) { - $prereqs->{runtime}{$rel} = _version_map($meta->{$rel}) - if $meta->{$rel}; - } - return $prereqs; -} - -my $prereqs_spec = { - configure => \&_prereqs_rel, - build => \&_prereqs_rel, - test => \&_prereqs_rel, - runtime => \&_prereqs_rel, - develop => \&_prereqs_rel, - ':custom' => \&_prefix_custom, -}; - -my $relation_spec = { - requires => \&_version_map, - recommends => \&_version_map, - suggests => \&_version_map, - conflicts => \&_version_map, - ':custom' => \&_prefix_custom, -}; - -sub _cleanup_prereqs { - my ($prereqs, $key, $meta, $to_version) = @_; - return unless $prereqs && ref $prereqs eq 'HASH'; - return _convert( $prereqs, $prereqs_spec, $to_version ); -} - -sub _prereqs_rel { - my ($relation, $key, $meta, $to_version) = @_; - return unless $relation && ref $relation eq 'HASH'; - return _convert( $relation, $relation_spec, $to_version ); -} - - -BEGIN { - my @old_prereqs = qw( - requires - configure_requires - recommends - conflicts - ); - - for ( @old_prereqs ) { - my $sub = "_get_$_"; - my ($phase,$type) = split qr/_/, $_; - if ( ! defined $type ) { - $type = $phase; - $phase = 'runtime'; - } - no strict 'refs'; - *{$sub} = sub { _extract_prereqs($_[2]->{prereqs},$phase,$type) }; - } -} - -sub _get_build_requires { - my ($data, $key, $meta) = @_; - - my $test_h = _extract_prereqs($_[2]->{prereqs}, qw(test requires)) || {}; - my $build_h = _extract_prereqs($_[2]->{prereqs}, qw(build requires)) || {}; - - require Version::Requirements; - my $test_req = Version::Requirements->from_string_hash($test_h); - my $build_req = Version::Requirements->from_string_hash($build_h); - - $test_req->add_requirements($build_req)->as_string_hash; -} - -sub _extract_prereqs { - my ($prereqs, $phase, $type) = @_; - return unless ref $prereqs eq 'HASH'; - return $prereqs->{$phase}{$type}; -} - -sub _downgrade_optional_features { - my (undef, undef, $meta) = @_; - return undef unless exists $meta->{optional_features}; - my $origin = $meta->{optional_features}; - my $features = {}; - for my $name ( keys %$origin ) { - $features->{$name} = { - description => $origin->{$name}{description}, - requires => _extract_prereqs($origin->{$name}{prereqs},'runtime','requires'), - configure_requires => _extract_prereqs($origin->{$name}{prereqs},'runtime','configure_requires'), - build_requires => _extract_prereqs($origin->{$name}{prereqs},'runtime','build_requires'), - recommends => _extract_prereqs($origin->{$name}{prereqs},'runtime','recommends'), - conflicts => _extract_prereqs($origin->{$name}{prereqs},'runtime','conflicts'), - }; - for my $k (keys %{$features->{$name}} ) { - delete $features->{$name}{$k} unless defined $features->{$name}{$k}; - } - } - return $features; -} - -sub _upgrade_optional_features { - my (undef, undef, $meta) = @_; - return undef unless exists $meta->{optional_features}; - my $origin = $meta->{optional_features}; - my $features = {}; - for my $name ( keys %$origin ) { - $features->{$name} = { - description => $origin->{$name}{description}, - prereqs => _prereqs_from_1(undef, undef, $origin->{$name}), - }; - delete $features->{$name}{prereqs}{configure}; - } - return $features; -} - -my $optional_features_2_spec = { - description => \&_keep, - prereqs => \&_cleanup_prereqs, - ':custom' => \&_prefix_custom, -}; - -sub _feature_2 { - my ($element, $key, $meta, $to_version) = @_; - return unless $element && ref $element eq 'HASH'; - _convert( $element, $optional_features_2_spec, $to_version ); -} - -sub _cleanup_optional_features_2 { - my ($element, $key, $meta, $to_version) = @_; - return unless $element && ref $element eq 'HASH'; - my $new_data = {}; - for my $k ( keys %$element ) { - $new_data->{$k} = _feature_2( $element->{$k}, $k, $meta, $to_version ); - } - return unless keys %$new_data; - return $new_data; -} - -sub _optional_features_1_4 { - my ($element) = @_; - return unless $element; - $element = _optional_features_as_map($element); - for my $name ( keys %$element ) { - for my $drop ( qw/requires_packages requires_os excluded_os/ ) { - delete $element->{$name}{$drop}; - } - } - return $element; -} - -sub _optional_features_as_map { - my ($element) = @_; - return unless $element; - if ( ref $element eq 'ARRAY' ) { - my %map; - for my $feature ( @$element ) { - my (@parts) = %$feature; - $map{$parts[0]} = $parts[1]; - } - $element = \%map; - } - return $element; -} - -sub _is_urlish { defined $_[0] && $_[0] =~ m{\A[-+.a-z0-9]+:.+}i } - -sub _url_or_drop { - my ($element) = @_; - return $element if _is_urlish($element); - return; -} - -sub _url_list { - my ($element) = @_; - return unless $element; - $element = _listify( $element ); - $element = [ grep { _is_urlish($_) } @$element ]; - return unless @$element; - return $element; -} - -sub _author_list { - my ($element) = @_; - return [ 'unknown' ] unless $element; - $element = _listify( $element ); - $element = [ map { defined $_ && length $_ ? $_ : 'unknown' } @$element ]; - return [ 'unknown' ] unless @$element; - return $element; -} - -my $resource2_upgrade = { - license => sub { return _is_urlish($_[0]) ? _listify( $_[0] ) : undef }, - homepage => \&_url_or_drop, - bugtracker => sub { - my ($item) = @_; - return unless $item; - if ( $item =~ m{^mailto:(.*)$} ) { return { mailto => $1 } } - elsif( _is_urlish($item) ) { return { web => $item } } - else { return undef } - }, - repository => sub { return _is_urlish($_[0]) ? { url => $_[0] } : undef }, - ':custom' => \&_prefix_custom, -}; - -sub _upgrade_resources_2 { - my (undef, undef, $meta, $version) = @_; - return undef unless exists $meta->{resources}; - return _convert($meta->{resources}, $resource2_upgrade); -} - -my $bugtracker2_spec = { - web => \&_url_or_drop, - mailto => \&_keep, - ':custom' => \&_prefix_custom, -}; - -sub _repo_type { - my ($element, $key, $meta, $to_version) = @_; - return $element if defined $element; - return unless exists $meta->{url}; - my $repo_url = $meta->{url}; - for my $type ( qw/git svn/ ) { - return $type if $repo_url =~ m{\A$type}; - } - return; -} - -my $repository2_spec = { - web => \&_url_or_drop, - url => \&_url_or_drop, - type => \&_repo_type, - ':custom' => \&_prefix_custom, -}; - -my $resources2_cleanup = { - license => \&_url_list, - homepage => \&_url_or_drop, - bugtracker => sub { ref $_[0] ? _convert( $_[0], $bugtracker2_spec ) : undef }, - repository => sub { my $data = shift; ref $data ? _convert( $data, $repository2_spec ) : undef }, - ':custom' => \&_prefix_custom, -}; - -sub _cleanup_resources_2 { - my ($resources, $key, $meta, $to_version) = @_; - return undef unless $resources && ref $resources eq 'HASH'; - return _convert($resources, $resources2_cleanup, $to_version); -} - -my $resource1_spec = { - license => \&_url_or_drop, - homepage => \&_url_or_drop, - bugtracker => \&_url_or_drop, - repository => \&_url_or_drop, - ':custom' => \&_keep, -}; - -sub _resources_1_3 { - my (undef, undef, $meta, $version) = @_; - return undef unless exists $meta->{resources}; - return _convert($meta->{resources}, $resource1_spec); -} - -*_resources_1_4 = *_resources_1_3; - -sub _resources_1_2 { - my (undef, undef, $meta) = @_; - my $resources = $meta->{resources} || {}; - if ( $meta->{license_url} && ! $resources->{license} ) { - $resources->{license} = $meta->license_url - if _is_urlish($meta->{license_url}); - } - return undef unless keys %$resources; - return _convert($resources, $resource1_spec); -} - -my $resource_downgrade_spec = { - license => sub { return ref $_[0] ? $_[0]->[0] : $_[0] }, - homepage => \&_url_or_drop, - bugtracker => sub { return $_[0]->{web} }, - repository => sub { return $_[0]->{url} || $_[0]->{web} }, - ':custom' => \&_ucfirst_custom, -}; - -sub _downgrade_resources { - my (undef, undef, $meta, $version) = @_; - return undef unless exists $meta->{resources}; - return _convert($meta->{resources}, $resource_downgrade_spec); -} - -sub _release_status { - my ($element, undef, $meta) = @_; - return $element if $element && $element =~ m{\A(?:stable|testing|unstable)\z}; - return _release_status_from_version(undef, undef, $meta); -} - -sub _release_status_from_version { - my (undef, undef, $meta) = @_; - my $version = $meta->{version} || ''; - return ( $version =~ /_/ ) ? 'testing' : 'stable'; -} - -my $provides_spec = { - file => \&_keep, - version => \&_clean_version, -}; - -my $provides_spec_2 = { - file => \&_keep, - version => \&_clean_version, - ':custom' => \&_prefix_custom, -}; - -sub _provides { - my ($element, $key, $meta, $to_version) = @_; - return unless defined $element && ref $element eq 'HASH'; - my $spec = $to_version == 2 ? $provides_spec_2 : $provides_spec; - my $new_data = {}; - for my $k ( keys %$element ) { - $new_data->{$k} = _convert($element->{$k}, $spec, $to_version); - } - return $new_data; -} - -sub _convert { - my ($data, $spec, $to_version) = @_; - - my $new_data = {}; - for my $key ( keys %$spec ) { - next if $key eq ':custom' || $key eq ':drop'; - next unless my $fcn = $spec->{$key}; - die "spec for '$key' is not a coderef" - unless ref $fcn && ref $fcn eq 'CODE'; - my $new_value = $fcn->($data->{$key}, $key, $data, $to_version); - $new_data->{$key} = $new_value if defined $new_value; - } - - my $drop_list = $spec->{':drop'}; - my $customizer = $spec->{':custom'} || \&_keep; - - for my $key ( keys %$data ) { - next if $drop_list && grep { $key eq $_ } @$drop_list; - next if exists $spec->{$key}; # we handled it - $new_data->{ $customizer->($key) } = $data->{$key}; - } - - return $new_data; -} - -#--------------------------------------------------------------------------# -# define converters for each conversion -#--------------------------------------------------------------------------# - -# each converts from prior version -# special ":custom" field is used for keys not recognized in spec -my %up_convert = ( - '2-from-1.4' => { - # PRIOR MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_2, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # CHANGED TO MANDATORY - 'dynamic_config' => \&_keep_or_one, - # ADDED MANDATORY - 'release_status' => \&_release_status_from_version, - # PRIOR OPTIONAL - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_upgrade_optional_features, - 'provides' => \&_provides, - 'resources' => \&_upgrade_resources_2, - # ADDED OPTIONAL - 'description' => \&_keep, - 'prereqs' => \&_prereqs_from_1, - - # drop these deprecated fields, but only after we convert - ':drop' => [ qw( - build_requires - configure_requires - conflicts - distribution_type - license_url - private - recommends - requires - ) ], - - # other random keys need x_ prefixing - ':custom' => \&_prefix_custom, - }, - '1.4-from-1.3' => { - # PRIOR MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_optional_features_1_4, - 'provides' => \&_provides, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - 'resources' => \&_resources_1_4, - # ADDED OPTIONAL - 'configure_requires' => \&_keep, - - # drop these deprecated fields, but only after we convert - ':drop' => [ qw( - license_url - private - )], - - # other random keys are OK if already valid - ':custom' => \&_keep - }, - '1.3-from-1.2' => { - # PRIOR MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_optional_features_as_map, - 'provides' => \&_provides, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - 'resources' => \&_resources_1_3, - - # drop these deprecated fields, but only after we convert - ':drop' => [ qw( - license_url - private - )], - - # other random keys are OK if already valid - ':custom' => \&_keep - }, - '1.2-from-1.1' => { - # PRIOR MANDATORY - 'version' => \&_keep, - # CHANGED TO MANDATORY - 'license' => \&_license_1, - 'name' => \&_keep, - 'generated_by' => \&_generated_by, - # ADDED MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'meta-spec' => \&_change_meta_spec, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - # ADDED OPTIONAL - 'keywords' => \&_keep, - 'no_index' => \&_no_index_1_2, - 'optional_features' => \&_optional_features_as_map, - 'provides' => \&_provides, - 'resources' => \&_resources_1_2, - - # drop these deprecated fields, but only after we convert - ':drop' => [ qw( - license_url - private - )], - - # other random keys are OK if already valid - ':custom' => \&_keep - }, - '1.1-from-1.0' => { - # CHANGED TO MANDATORY - 'version' => \&_keep, - # IMPLIED MANDATORY - 'name' => \&_keep, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - # ADDED OPTIONAL - 'license_url' => \&_url_or_drop, - 'private' => \&_keep, - - # other random keys are OK if already valid - ':custom' => \&_keep - }, -); - -my %down_convert = ( - '1.4-from-2' => { - # MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_downgrade_license, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # OPTIONAL - 'build_requires' => \&_get_build_requires, - 'configure_requires' => \&_get_configure_requires, - 'conflicts' => \&_get_conflicts, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_downgrade_optional_features, - 'provides' => \&_provides, - 'recommends' => \&_get_recommends, - 'requires' => \&_get_requires, - 'resources' => \&_downgrade_resources, - - # drop these unsupported fields (after conversion) - ':drop' => [ qw( - description - prereqs - release_status - )], - - # custom keys will be left unchanged - ':custom' => \&_keep - }, - '1.3-from-1.4' => { - # MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_optional_features_as_map, - 'provides' => \&_provides, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - 'resources' => \&_resources_1_3, - - # drop these unsupported fields, but only after we convert - ':drop' => [ qw( - configure_requires - )], - - # other random keys are OK if already valid - ':custom' => \&_keep, - }, - '1.2-from-1.3' => { - # MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'keywords' => \&_keep, - 'no_index' => \&_no_index_1_2, - 'optional_features' => \&_optional_features_as_map, - 'provides' => \&_provides, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - 'resources' => \&_resources_1_3, - - # other random keys are OK if already valid - ':custom' => \&_keep, - }, - '1.1-from-1.2' => { - # MANDATORY - 'version' => \&_keep, - # IMPLIED MANDATORY - 'name' => \&_keep, - 'meta-spec' => \&_change_meta_spec, - # OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'private' => \&_keep, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - - # drop unsupported fields - ':drop' => [ qw( - abstract - author - provides - no_index - keywords - resources - )], - - # other random keys are OK if already valid - ':custom' => \&_keep, - }, - '1.0-from-1.1' => { - # IMPLIED MANDATORY - 'name' => \&_keep, - 'meta-spec' => \&_change_meta_spec, - 'version' => \&_keep, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - - # other random keys are OK if already valid - ':custom' => \&_keep, - }, -); - -my %cleanup = ( - '2' => { - # PRIOR MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_2, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # CHANGED TO MANDATORY - 'dynamic_config' => \&_keep_or_one, - # ADDED MANDATORY - 'release_status' => \&_release_status, - # PRIOR OPTIONAL - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_cleanup_optional_features_2, - 'provides' => \&_provides, - 'resources' => \&_cleanup_resources_2, - # ADDED OPTIONAL - 'description' => \&_keep, - 'prereqs' => \&_cleanup_prereqs, - - # drop these deprecated fields, but only after we convert - ':drop' => [ qw( - build_requires - configure_requires - conflicts - distribution_type - license_url - private - recommends - requires - ) ], - - # other random keys need x_ prefixing - ':custom' => \&_prefix_custom, - }, - '1.4' => { - # PRIOR MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_optional_features_1_4, - 'provides' => \&_provides, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - 'resources' => \&_resources_1_4, - # ADDED OPTIONAL - 'configure_requires' => \&_keep, - - # other random keys are OK if already valid - ':custom' => \&_keep - }, - '1.3' => { - # PRIOR MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'meta-spec' => \&_change_meta_spec, - 'name' => \&_keep, - 'version' => \&_keep, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'keywords' => \&_keep, - 'no_index' => \&_no_index_directory, - 'optional_features' => \&_optional_features_as_map, - 'provides' => \&_provides, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - 'resources' => \&_resources_1_3, - - # other random keys are OK if already valid - ':custom' => \&_keep - }, - '1.2' => { - # PRIOR MANDATORY - 'version' => \&_keep, - # CHANGED TO MANDATORY - 'license' => \&_license_1, - 'name' => \&_keep, - 'generated_by' => \&_generated_by, - # ADDED MANDATORY - 'abstract' => \&_keep_or_unknown, - 'author' => \&_author_list, - 'meta-spec' => \&_change_meta_spec, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - # ADDED OPTIONAL - 'keywords' => \&_keep, - 'no_index' => \&_no_index_1_2, - 'optional_features' => \&_optional_features_as_map, - 'provides' => \&_provides, - 'resources' => \&_resources_1_2, - - # other random keys are OK if already valid - ':custom' => \&_keep - }, - '1.1' => { - # CHANGED TO MANDATORY - 'version' => \&_keep, - # IMPLIED MANDATORY - 'name' => \&_keep, - 'meta-spec' => \&_change_meta_spec, - # PRIOR OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - # ADDED OPTIONAL - 'license_url' => \&_url_or_drop, - 'private' => \&_keep, - - # other random keys are OK if already valid - ':custom' => \&_keep - }, - '1.0' => { - # IMPLIED MANDATORY - 'name' => \&_keep, - 'meta-spec' => \&_change_meta_spec, - 'version' => \&_keep, - # IMPLIED OPTIONAL - 'build_requires' => \&_version_map, - 'conflicts' => \&_version_map, - 'distribution_type' => \&_keep, - 'dynamic_config' => \&_keep_or_one, - 'generated_by' => \&_generated_by, - 'license' => \&_license_1, - 'recommends' => \&_version_map, - 'requires' => \&_version_map, - - # other random keys are OK if already valid - ':custom' => \&_keep, - }, -); - -#--------------------------------------------------------------------------# -# Code -#--------------------------------------------------------------------------# - - -sub new { - my ($class,$data) = @_; - - # create an attributes hash - my $self = { - 'data' => $data, - 'spec' => $data->{'meta-spec'}{'version'} || "1.0", - }; - - # create the object - return bless $self, $class; -} - - -sub convert { - my ($self, %args) = @_; - my $args = { %args }; - - my $new_version = $args->{version} || $HIGHEST; - - my ($old_version) = $self->{spec}; - my $converted = _dclone($self->{data}); - - if ( $old_version == $new_version ) { - $converted = _convert( $converted, $cleanup{$old_version}, $old_version ); - my $cmv = CPAN::Meta::Validator->new( $converted ); - unless ( $cmv->is_valid ) { - my $errs = join("\n", $cmv->errors); - die "Failed to clean-up $old_version metadata. Errors:\n$errs\n"; - } - return $converted; - } - elsif ( $old_version > $new_version ) { - my @vers = sort { $b <=> $a } keys %known_specs; - for my $i ( 0 .. $#vers-1 ) { - next if $vers[$i] > $old_version; - last if $vers[$i+1] < $new_version; - my $spec_string = "$vers[$i+1]-from-$vers[$i]"; - $converted = _convert( $converted, $down_convert{$spec_string}, $vers[$i+1] ); - my $cmv = CPAN::Meta::Validator->new( $converted ); - unless ( $cmv->is_valid ) { - my $errs = join("\n", $cmv->errors); - die "Failed to downconvert metadata to $vers[$i+1]. Errors:\n$errs\n"; - } - } - return $converted; - } - else { - my @vers = sort { $a <=> $b } keys %known_specs; - for my $i ( 0 .. $#vers-1 ) { - next if $vers[$i] < $old_version; - last if $vers[$i+1] > $new_version; - my $spec_string = "$vers[$i+1]-from-$vers[$i]"; - $converted = _convert( $converted, $up_convert{$spec_string}, $vers[$i+1] ); - my $cmv = CPAN::Meta::Validator->new( $converted ); - unless ( $cmv->is_valid ) { - my $errs = join("\n", $cmv->errors); - die "Failed to upconvert metadata to $vers[$i+1]. Errors:\n$errs\n"; - } - } - return $converted; - } -} - -1; - - - -=pod - -=head1 NAME - -CPAN::Meta::Converter - Convert CPAN distribution metadata structures - -=head1 VERSION - -version 2.110930 - -=head1 SYNOPSIS - - my $struct = decode_json_file('META.json'); - - my $cmc = CPAN::Meta::Converter->new( $struct ); - - my $new_struct = $cmc->convert( version => "2" ); - -=head1 DESCRIPTION - -This module converts CPAN Meta structures from one form to another. The -primary use is to convert older structures to the most modern version of -the specification, but other transformations may be implemented in the -future as needed. (E.g. stripping all custom fields or stripping all -optional fields.) - -=head1 METHODS - -=head2 new - - my $cmc = CPAN::Meta::Converter->new( $struct ); - -The constructor should be passed a valid metadata structure but invalid -structures are accepted. If no meta-spec version is provided, version 1.0 will -be assumed. - -=head2 convert - - my $new_struct = $cmc->convert( version => "2" ); - -Returns a new hash reference with the metadata converted to a different form. -C will die if any conversion/standardization still results in an -invalid structure. - -Valid parameters include: - -=over - -=item * - -C -- Indicates the desired specification version (e.g. "1.0", "1.1" ... "1.4", "2"). -Defaults to the latest version of the CPAN Meta Spec. - -=back - -Conversion proceeds through each version in turn. For example, a version 1.2 -structure might be converted to 1.3 then 1.4 then finally to version 2. The -conversion process attempts to clean-up simple errors and standardize data. -For example, if C is given as a scalar, it will converted to an array -reference containing the item. (Converting a structure to its own version will -also clean-up and standardize.) - -When data are cleaned and standardized, missing or invalid fields will be -replaced with sensible defaults when possible. This may be lossy or imprecise. -For example, some badly structured META.yml files on CPAN have prerequisite -modules listed as both keys and values: - - requires => { 'Foo::Bar' => 'Bam::Baz' } - -These would be split and each converted to a prerequisite with a minimum -version of zero. - -When some mandatory fields are missing or invalid, the conversion will attempt -to provide a sensible default or will fill them with a value of 'unknown'. For -example a missing or unrecognized C field will result in a C -field of 'unknown'. Fields that may get an 'unknown' include: - -=over 4 - -=item * - -abstract - -=item * - -author - -=item * - -license - -=back - -=head1 BUGS - -Please report any bugs or feature using the CPAN Request Tracker. -Bugs can be submitted through the web interface at -L - -When submitting a bug or request, please include a test-file or a patch to an -existing test-file that illustrates the bug or desired feature. - -=head1 AUTHORS - -=over 4 - -=item * - -David Golden - -=item * - -Ricardo Signes - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 2010 by David Golden and Ricardo Signes. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - - -__END__ - - diff --git a/perl/vendor/lib/CPAN/Meta/Feature.pm b/perl/vendor/lib/CPAN/Meta/Feature.pm deleted file mode 100644 index d8258dc..0000000 --- a/perl/vendor/lib/CPAN/Meta/Feature.pm +++ /dev/null @@ -1,116 +0,0 @@ -use 5.006; -use strict; -use warnings; -package CPAN::Meta::Feature; -BEGIN { - $CPAN::Meta::Feature::VERSION = '2.110930'; -} -# ABSTRACT: an optional feature provided by a CPAN distribution - -use CPAN::Meta::Prereqs; - - -sub new { - my ($class, $identifier, $spec) = @_; - - my %guts = ( - identifier => $identifier, - description => $spec->{description}, - prereqs => CPAN::Meta::Prereqs->new($spec->{prereqs}), - ); - - bless \%guts => $class; -} - - -sub identifier { $_[0]{identifier} } - - -sub description { $_[0]{description} } - - -sub prereqs { $_[0]{prereqs} } - -1; - - - -=pod - -=head1 NAME - -CPAN::Meta::Feature - an optional feature provided by a CPAN distribution - -=head1 VERSION - -version 2.110930 - -=head1 DESCRIPTION - -A CPAN::Meta::Feature object describes an optional feature offered by a CPAN -distribution and specified in the distribution's F (or F) -file. - -For the most part, this class will only be used when operating on the result of -the C or C methods on a L object. - -=head1 METHODS - -=head2 new - - my $feature = CPAN::Meta::Feature->new( $identifier => \%spec ); - -This returns a new Feature object. The C<%spec> argument to the constructor -should be the same as the value of the C entry in the -distmeta. It must contain entries for C and C. - -=head2 identifier - -This method returns the feature's identifier. - -=head2 description - -This method returns the feature's long description. - -=head2 prereqs - -This method returns the feature's prerequisites as a L -object. - -=head1 BUGS - -Please report any bugs or feature using the CPAN Request Tracker. -Bugs can be submitted through the web interface at -L - -When submitting a bug or request, please include a test-file or a patch to an -existing test-file that illustrates the bug or desired feature. - -=head1 AUTHORS - -=over 4 - -=item * - -David Golden - -=item * - -Ricardo Signes - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 2010 by David Golden and Ricardo Signes. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - - -__END__ - - - diff --git a/perl/vendor/lib/CPAN/Meta/History.pm b/perl/vendor/lib/CPAN/Meta/History.pm deleted file mode 100644 index 9ccbfd4..0000000 --- a/perl/vendor/lib/CPAN/Meta/History.pm +++ /dev/null @@ -1,315 +0,0 @@ -# vi:tw=72 -use 5.006; -use strict; -use warnings; -package CPAN::Meta::History; -BEGIN { - $CPAN::Meta::History::VERSION = '2.110930'; -} -# ABSTRACT: history of CPAN Meta Spec changes -1; - - - -__END__ -=pod - -=head1 NAME - -CPAN::Meta::History - history of CPAN Meta Spec changes - -=head1 VERSION - -version 2.110930 - -=head1 DESCRIPTION - -The CPAN Meta Spec has gone through several iterations. It was -originally written in HTML and later revised into POD (though published -in HTML generated from the POD). Fields were added, removed or changed, -sometimes by design and sometimes to reflect real-world usage after the -fact. - -This document reconstructs the history of the CPAN Meta Spec based on -change logs, repository commit messages and the published HTML files. -In some cases, particularly prior to version 1.2, the exact version -when certain fields were introduced or changed is inconsistent between -sources. When in doubt, the published HTML files for versions 1.0 to -1.4 as they existed when version 2 was developed are used as the -definitive source. - -Starting with version 2, the specification document is part of the -CPAN-Meta distribution and will be published on CPAN as -L. - -Going forward, specification version numbers will be integers and -decimal portions will correspond to a release date for the CPAN::Meta -library. - -=head1 HISTORY - -=head2 Version 2 - -April 2010 - -=over - -=item * - -Revised spec examples as perl data structures rather than YAML - -=item * - -Switched to JSON serialization from YAML - -=item * - -Specified allowed version number formats - -=item * - -Replaced 'requires', 'build_requires', 'configure_requires', -'recommends' and 'conflicts' with new 'prereqs' data structure divided -by I (configure, build, test, runtime, etc.) and I -(requires, recommends, suggests, conflicts) - -=item * - -Added support for 'develop' phase for requirements for maintaining -a list of authoring tools - -=item * - -Changed 'license' to a list and revised the set of valid licenses - -=item * - -Made 'dynamic_config' mandatory to reduce confusion - -=item * - -Changed 'resources' subkey 'repository' to a hash that clarifies -repository type, url for browsing and url for checkout - -=item * - -Changed 'resources' subkey 'bugtracker' to a hash for either web -or mailto resource - -=item * - -Changed specification of 'optional_features': - -=over - -=item * - -Added formal specification and usage guide instead of just example - -=item * - -Changed to use new prereqs data structure instead of individual keys - -=back - -=item * - -Clarified intended use of 'author' as generalized contact list - -=item * - -Added 'release_status' field to indicate stable, testing or unstable -status to provide hints to indexers - -=item * - -Added 'description' field for a longer description of the distribution - -=item * - -Formalized use of "x_" or "X_" for all custom keys not listed in the -official spec - -=back - -=head2 Version 1.4 - -June 2008 - -=over - -=item * - -Noted explicit support for 'perl' in prerequisites - -=item * - -Added 'configure_requires' prerequisite type - -=item * - -Changed 'optional_features' - -=over - -=item * - -Example corrected to show map of maps instead of list of maps -(though descriptive text said 'map' even in v1.3) - -=item * - -Removed 'requires_packages', 'requires_os' and 'excluded_os' -as valid subkeys - -=back - -=back - -=head2 Version 1.3 - -November 2006 - -=over - -=item * - -Clarified that all prerequisites take version range specifications - -=item * - -Added 'no_index' subkey 'directory' and removed 'dir' to match actual -usage in the wild - -=item * - -Added a 'repository' subkey to 'resources' - -=back - -=head2 Version 1.2 - -August 2005 - -=over - -=item * - -Re-wrote and restructured spec in POD syntax - -=item * - -Changed 'name' to be mandatory - -=item * - -Changed 'generated_by' to be mandatory - -=item * - -Changed 'license' to be mandatory - -=item * - -Added required 'abstract' field - -=item * - -Added required 'author' field - -=item * - -Added required 'meta-spec' field to define 'version' (and 'url') of the -CPAN Meta Spec used for metadata - -=item * - -Added 'provides' field - -=item * - -Added 'no_index' field and deprecated 'private' field. 'no_index' -subkeys include 'file', 'dir', 'package' and 'namespace' - -=item * - -Added 'keywords' field - -=item * - -Added 'resources' field with subkeys 'homepage', 'license', and -'bugtracker' - -=item * - -Added 'optional_features' field as an alterate under 'recommends'. -Includes 'description', 'requires', 'build_requires', 'conflicts', -'requires_packages', 'requires_os' and 'excluded_os' as valid subkeys - -=item * - -Removed 'license_uri' field - -=back - -=head2 Version 1.1 - -May 2003 - -=over - -=item * - -Changed 'version' to be mandatory - -=item * - -Added 'private' field - -=item * - -Added 'license_uri' field - -=back - -=head2 Version 1.0 - -March 2003 - -=over - -=item * - -Original release (in HTML format only) - -=item * - -Included 'name', 'version', 'license', 'distribution_type', 'requires', -'recommends', 'build_requires', 'conflicts', 'dynamic_config', -'generated_by' - -=back - -=head1 AUTHORS - -=over 4 - -=item * - -David Golden - -=item * - -Ricardo Signes - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 2010 by David Golden and Ricardo Signes. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - diff --git a/perl/vendor/lib/CPAN/Meta/Prereqs.pm b/perl/vendor/lib/CPAN/Meta/Prereqs.pm deleted file mode 100644 index 29a2e5a..0000000 --- a/perl/vendor/lib/CPAN/Meta/Prereqs.pm +++ /dev/null @@ -1,277 +0,0 @@ -use 5.006; -use strict; -use warnings; -package CPAN::Meta::Prereqs; -BEGIN { - $CPAN::Meta::Prereqs::VERSION = '2.110930'; -} -# ABSTRACT: a set of distribution prerequisites by phase and type - - -use Carp qw(confess); -use Scalar::Util qw(blessed); -use Version::Requirements 0.101020; # finalize - - -sub __legal_phases { qw(configure build test runtime develop) } -sub __legal_types { qw(requires recommends suggests conflicts) } - -# expect a prereq spec from META.json -- rjbs, 2010-04-11 -sub new { - my ($class, $prereq_spec) = @_; - $prereq_spec ||= {}; - - my %is_legal_phase = map {; $_ => 1 } $class->__legal_phases; - my %is_legal_type = map {; $_ => 1 } $class->__legal_types; - - my %guts; - PHASE: for my $phase (keys %$prereq_spec) { - next PHASE unless $phase =~ /\Ax_/i or $is_legal_phase{$phase}; - - my $phase_spec = $prereq_spec->{ $phase }; - next PHASE unless keys %$phase_spec; - - TYPE: for my $type (keys %$phase_spec) { - next TYPE unless $type =~ /\Ax_/i or $is_legal_type{$type}; - - my $spec = $phase_spec->{ $type }; - - next TYPE unless keys %$spec; - - $guts{prereqs}{$phase}{$type} = Version::Requirements->from_string_hash( - $spec - ); - } - } - - return bless \%guts => $class; -} - - -sub requirements_for { - my ($self, $phase, $type) = @_; - - confess "requirements_for called without phase" unless defined $phase; - confess "requirements_for called without type" unless defined $type; - - unless ($phase =~ /\Ax_/i or grep { $phase eq $_ } $self->__legal_phases) { - confess "requested requirements for unknown phase: $phase"; - } - - unless ($type =~ /\Ax_/i or grep { $type eq $_ } $self->__legal_types) { - confess "requested requirements for unknown type: $type"; - } - - my $req = ($self->{prereqs}{$phase}{$type} ||= Version::Requirements->new); - - $req->finalize if $self->is_finalized; - - return $req; -} - - -sub with_merged_prereqs { - my ($self, $other) = @_; - - my @other = blessed($other) ? $other : @$other; - - my @prereq_objs = ($self, @other); - - my %new_arg; - - for my $phase ($self->__legal_phases) { - for my $type ($self->__legal_types) { - my $req = Version::Requirements->new; - - for my $prereq (@prereq_objs) { - my $this_req = $prereq->requirements_for($phase, $type); - next unless $this_req->required_modules; - - $req->add_requirements($this_req); - } - - next unless $req->required_modules; - - $new_arg{ $phase }{ $type } = $req->as_string_hash; - } - } - - return (ref $self)->new(\%new_arg); -} - - -sub as_string_hash { - my ($self) = @_; - - my %hash; - - for my $phase ($self->__legal_phases) { - for my $type ($self->__legal_types) { - my $req = $self->requirements_for($phase, $type); - next unless $req->required_modules; - - $hash{ $phase }{ $type } = $req->as_string_hash; - } - } - - return \%hash; -} - - -sub is_finalized { $_[0]{finalized} } - - -sub finalize { - my ($self) = @_; - - $self->{finalized} = 1; - - for my $phase (keys %{ $self->{prereqs} }) { - $_->finalize for values %{ $self->{prereqs}{$phase} }; - } -} - - -sub clone { - my ($self) = @_; - - my $clone = (ref $self)->new( $self->as_string_hash ); -} - -1; - - - -=pod - -=head1 NAME - -CPAN::Meta::Prereqs - a set of distribution prerequisites by phase and type - -=head1 VERSION - -version 2.110930 - -=head1 DESCRIPTION - -A CPAN::Meta::Prereqs object represents the prerequisites for a CPAN -distribution or one of its optional features. Each set of prereqs is -organized by phase and type, as described in L. - -=head1 METHODS - -=head2 new - - my $prereq = CPAN::Meta::Prereqs->new( \%prereq_spec ); - -This method returns a new set of Prereqs. The input should look like the -contents of the C field described in L, meaning -something more or less like this: - - my $prereq = CPAN::Meta::Prereqs->new({ - runtime => { - requires => { - 'Some::Module' => '1.234', - ..., - }, - ..., - }, - ..., - }); - -You can also construct an empty set of prereqs with: - - my $prereqs = CPAN::Meta::Prereqs->new; - -This empty set of prereqs is useful for accumulating new prereqs before finally -dumping the whole set into a structure or string. - -=head2 requirements_for - - my $requirements = $prereqs->requirements_for( $phase, $type ); - -This method returns a L object for the given phase/type -combination. If no prerequisites are registered for that combination, a new -Version::Requirements object will be returned, and it may be added to as -needed. - -If C<$phase> or C<$type> are undefined or otherwise invalid, an exception will -be raised. - -=head2 with_merged_prereqs - - my $new_prereqs = $prereqs->with_merged_prereqs( $other_prereqs ); - - my $new_prereqs = $prereqs->with_merged_prereqs( \@other_prereqs ); - -This method returns a new CPAN::Meta::Prereqs objects in which all the -other prerequisites given are merged into the current set. This is primarily -provided for combining a distribution's core prereqs with the prereqs of one of -its optional features. - -The new prereqs object has no ties to the originals, and altering it further -will not alter them. - -=head2 as_string_hash - -This method returns a hashref containing structures suitable for dumping into a -distmeta data structure. It is made up of hashes and strings, only; there will -be no Prereqs, Version::Requirements, or C objects inside it. - -=head2 is_finalized - -This method returns true if the set of prereqs has been marked "finalized," and -cannot be altered. - -=head2 finalize - -Calling C on a Prereqs object will close it for further modification. -Attempting to make any changes that would actually alter the prereqs will -result in an exception being thrown. - -=head2 clone - - my $cloned_prereqs = $prereqs->clone; - -This method returns a Prereqs object that is identical to the original object, -but can be altered without affecting the original object. Finalization does -not survive cloning, meaning that you may clone a finalized set of prereqs and -then modify the clone. - -=head1 BUGS - -Please report any bugs or feature using the CPAN Request Tracker. -Bugs can be submitted through the web interface at -L - -When submitting a bug or request, please include a test-file or a patch to an -existing test-file that illustrates the bug or desired feature. - -=head1 AUTHORS - -=over 4 - -=item * - -David Golden - -=item * - -Ricardo Signes - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 2010 by David Golden and Ricardo Signes. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - - -__END__ - - - diff --git a/perl/vendor/lib/CPAN/Meta/Spec.pm b/perl/vendor/lib/CPAN/Meta/Spec.pm deleted file mode 100644 index b32fdac..0000000 --- a/perl/vendor/lib/CPAN/Meta/Spec.pm +++ /dev/null @@ -1,1146 +0,0 @@ -# vi:tw=72 -use 5.006; -use strict; -use warnings; -package CPAN::Meta::Spec; -BEGIN { - $CPAN::Meta::Spec::VERSION = '2.110930'; -} -# ABSTRACT: specification for CPAN distribution metadata -1; - - - -__END__ -=pod - -=head1 NAME - -CPAN::Meta::Spec - specification for CPAN distribution metadata - -=head1 VERSION - -version 2.110930 - -=head1 SYNOPSIS - - my $distmeta = { - name => 'Module-Build', - abstract => 'Build and install Perl modules', - description => "Module::Build is a system for " - . "building, testing, and installing Perl modules. " - . "It is meant to ... blah blah blah ...", - version => '0.36', - release_status => 'stable', - author => [ - 'Ken Williams ', - 'Module-Build List ', # additional contact - ], - license => [ 'perl_5' ], - prereqs => { - runtime => { - requires => { - 'perl' => '5.006', - 'ExtUtils::Install' => '0', - 'File::Basename' => '0', - 'File::Compare' => '0', - 'IO::File' => '0', - }, - recommends => { - 'Archive::Tar' => '1.00', - 'ExtUtils::Install' => '0.3', - 'ExtUtils::ParseXS' => '2.02', - }, - }, - build => { - requires => { - 'Test::More' => '0', - }, - } - }, - resources => { - license => ['http://dev.perl.org/licenses/'], - }, - optional_features => { - domination => { - description => 'Take over the world', - prereqs => { - develop => { requires => { 'Genius::Evil' => '1.234' } }, - runtime => { requires => { 'Machine::Weather' => '2.0' } }, - }, - }, - }, - dynamic_config => 1, - keywords => [ qw/ toolchain cpan dual-life / ], - 'meta-spec' => { - version => '2', - url => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec', - }, - generated_by => 'Module::Build version 0.36', - }; - -=head1 DESCRIPTION - -This document describes version 2 of the CPAN distribution metadata -specification, also known as the "CPAN Meta Spec". - -Revisions of this specification for typo corrections and prose -clarifications may be issued as CPAN::Meta::Spec 2.I. These -revisions will never change semantics or add or remove specified -behavior. - -Distribution metadata describe important properties of Perl -distributions. Distribution building tools like Module::Build, -Module::Install, ExtUtils::MakeMaker or Dist::Zilla should create a -metadata file in accordance with this specification and include it with -the distribution for use by automated tools that index, examine, package -or install Perl distributions. - -=head1 TERMINOLOGY - -=over 4 - -=item distribution - -This is the primary object described by the metadata. In the context of -this document it usually refers to a collection of modules, scripts, -and/or documents that are distributed together for other developers to -use. Examples of distributions are C, C, -or C. - -=item module - -This refers to a reusable library of code contained in a single file. -Modules usually contain one or more packages and are often referred -to by the name of a primary package that can be mapped to the file -name. For example, one might refer to C instead of -F - -=item package - -This refers to a namespace declared with the Perl C statement. -In Perl, packages often have a version number property given by the -C<$VERSION> variable in the namespace. - -=item consumer - -This refers to code that reads a metadata file, deserializes it into a -data structure in memory, or interprets a data structure of metadata -elements. - -=item producer - -This refers to code that constructs a metadata data structure, -serializes into a bytestream and/or writes it to disk. - -=item must, should, may, etc. - -These terms are interpreted as described in IETF RFC 2119. - -=back - -=head1 DATA TYPES - -Fields in the L section describe data elements, each of -which has an associated data type as described herein. There are four -primitive types: Boolean, String, List and Map. Other types are -subtypes of primitives and define compound data structures or define -constraints on the values of a data element. - -=head2 Boolean - -A I is used to provide a true or false value. It B be -represented as a defined value. - -=head2 String - -A I is data element containing a non-zero length sequence of -Unicode characters, such as an ordinary Perl scalar that is not a -reference. - -=head2 List - -A I is an ordered collection of zero or more data elements. -Elements of a List may be of mixed types. - -Producers B represent List elements using a data structure which -unambiguously indicates that multiple values are possible, such as a -reference to a Perl array (an "arrayref"). - -Consumers expecting a List B consider a String as equivalent to a -List of length 1. - -=head2 Map - -A I is an unordered collection of zero or more data elements -("values"), indexed by associated String elements ("keys"). The Map's -value elements may be of mixed types. - -=head2 License String - -A I is a subtype of String with a restricted set of -values. Valid values are described in detail in the description of -the L field. - -=head2 URL - -I is a subtype of String containing a Uniform Resource Locator or -Identifier. [ This type is called URL and not URI for historical reasons. ] - -=head2 Version - -A I is a subtype of String containing a value that describes -the version number of packages or distributions. Restrictions on format -are described in detail in the L section. - -=head2 Version Range - -The I type is a subtype of String. It describes a range -of Versions that may be present or installed to fulfill prerequisites. -It is specified in detail in the L section. - -=head1 STRUCTURE - -The metadata structure is a data element of type Map. This section -describes valid keys within the Map. - -Any keys not described in this specification document (whether top-level -or within compound data structures described herein) are considered -I and B begin with an "x" or "X" and be followed by an -underscore; i.e. they must match the pattern: C<< qr{\Ax_}i >>. If a -custom key refers to a compound data structure, subkeys within it do not -need an "x_" or "X_" prefix. - -Consumers of metadata may ignore any or all custom keys. All other keys -not described herein are invalid and should be ignored by consumers. -Producers must not generate or output invalid keys. - -For each key, an example is provided followed by a description. The -description begins with the version of spec in which the key was added -or in which the definition was modified, whether the key is I -or I and the data type of the corresponding data element. -These items are in parentheses, brackets and braces, respectively. - -If a data type is a Map or Map subtype, valid subkeys will be described -as well. - -Some fields are marked I. These are shown for historical -context and must not be produced in or consumed from any metadata structure -of version 2 or higher. - -=head2 REQUIRED FIELDS - -=head3 abstract - -Example: - - abstract => 'Build and install Perl modules' - -(Spec 1.2) [required] {String} - -This is a short description of the purpose of the distribution. - -=head3 author - -Example: - - author => [ 'Ken Williams ' ] - -(Spec 1.2) [required] {List of one or more Strings} - -This List indicates the person(s) to contact concerning the -distribution. The preferred form of the contact string is: - - contact-name - -This field provides a general contact list independent of other -structured fields provided within the L field, such as -C. The addressee(s) can be contacted for any purpose -including but not limited to (security) problems with the distribution, -questions about the distribution or bugs in the distribution. - -A distribution's original author is usually the contact listed within -this field. Co-maintainers, successor maintainers or mailing lists -devoted to the distribution may also be listed in addition to or instead -of the original author. - -=head3 dynamic_config - -Example: - - dynamic_config => 1 - -(Spec 2) [required] {Boolean} - -A boolean flag indicating whether a F or F (or -similar) must be executed to determine prerequisites. - -This field should be set to a true value if the distribution performs -some dynamic configuration (asking questions, sensing the environment, -etc.) as part of its configuration. This field should be set to a false -value to indicate that prerequisites included in metadata may be -considered final and valid for static analysis. - -This field explicitly B indicate whether installation may be -safely performed without using a Makefile or Build file, as there may be -special files to install or custom installation targets (e.g. for -dual-life modules that exist on CPAN as well as in the Perl core). This -field only defines whether prerequisites are complete as given in the -metadata. - -=head3 generated_by - -Example: - - generated_by => 'Module::Build version 0.36' - -(Spec 1.0) [required] {String} - -This field indicates the tool that was used to create this metadata. -There are no defined semantics for this field, but it is traditional to -use a string in the form "Generating::Package version 1.23" or the -author's name, if the file was generated by hand. - -=head3 license - -Example: - - license => [ 'perl_5' ] - - license => [ 'apache_2', 'mozilla_1_0' ] - -(Spec 2) [required] {List of one or more License Strings} - -One or more licenses that apply to some or all of the files in the -distribution. If multiple licenses are listed, the distribution -documentation should be consulted to clarify the interpretation of -multiple licenses. - -The following list of license strings are valid: - - string description - ------------- ----------------------------------------------- - agpl_3 GNU Affero General Public License, Version 3 - apache_1_1 Apache Software License, Version 1.1 - apache_2_0 Apache License, Version 2.0 - artistic_1 Artistic License, (Version 1) - artistic_2 Artistic License, Version 2.0 - bsd BSD License (three-clause) - freebsd FreeBSD License (two-clause) - gfdl_1_2 GNU Free Documentation License, Version 1.2 - gfdl_1_3 GNU Free Documentation License, Version 1.3 - gpl_1 GNU General Public License, Version 1 - gpl_2 GNU General Public License, Version 2 - gpl_3 GNU General Public License, Version 3 - lgpl_2_1 GNU Lesser General Public License, Version 2.1 - lgpl_3_0 GNU Lesser General Public License, Version 3.0 - mit MIT (aka X11) License - mozilla_1_0 Mozilla Public License, Version 1.0 - mozilla_1_1 Mozilla Public License, Version 1.1 - openssl OpenSSL License - perl_5 The Perl 5 License (Artistic 1 & GPL 1 or later) - qpl_1_0 Q Public License, Version 1.0 - ssleay Original SSLeay License - sun Sun Internet Standards Source License (SISSL) - zlib zlib License - -The following license strings are also valid and indicate other -licensing not described above: - - string description - ------------- ----------------------------------------------- - open_source Other Open Source Initiative (OSI) approved license - restricted Requires special permission from copyright holder - unrestricted Not an OSI approved license, but not restricted - unknown License not provided in metadata - -All other strings are invalid in the license field. - -=head3 meta-spec - -Example: - - 'meta-spec' => { - version => '2', - url => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec', - } - -(Spec 1.2) [required] {Map} - -This field indicates the version of the CPAN Meta Spec that should be -used to interpret the metadata. Consumers must check this key as soon -as possible and abort further metadata processing if the meta-spec -version is not supported by the consumer. - -The following keys are valid, but only C is required. - -=over - -=item version - -This subkey gives the integer I of the CPAN Meta Spec against -which the document was generated. - -=item url - -This is a I of the metadata specification document corresponding to -the given version. This is strictly for human-consumption and should -not impact the interpretation of the document. - -=back - -=head3 name - -Example: - - name => 'Module-Build' - -(Spec 1.0) [required] {String} - -This field is the name of the distribution. This is often created by -taking the "main package" in the distribution and changing C<::> to -C<->, but the name may be completely unrelated to the packages within -the distribution. C.f. L. - -=head3 release_status - -Example: - - release_status => 'stable' - -(Spec 2) [required] {String} - -This field provides the release status of this distribution. If the -C field contains an underscore character, then -C B be "stable." - -The C field B have one of the following values: - -=over - -=item stable - -This indicates an ordinary, "final" release that should be indexed by PAUSE -or other indexers. - -=item testing - -This indicates a "beta" release that is substantially complete, but has an -elevated risk of bugs and requires additional testing. The distribution -should not be installed over a stable release without an explicit request -or other confirmation from a user. This release status may also be used -for "release candidate" versions of a distribution. - -=item unstable - -This indicates an "alpha" release that is under active development, but has -been released for early feedback or testing and may be missing features or -may have serious bugs. The distribution should not be installed over a -stable release without an explicit request or other confirmation from a -user. - -=back - -Consumers B use this field to determine how to index the -distribution for CPAN or other repositories in addition to or in -replacement of heuristics based on version number or file name. - -=head3 version - -Example: - - version => '0.36' - -(Spec 1.0) [required] {Version} - -This field gives the version of the distribution to which the metadata -structure refers. - -=head2 OPTIONAL FIELDS - -=head3 description - -Example: - - description => "Module::Build is a system for " - . "building, testing, and installing Perl modules. " - . "It is meant to ... blah blah blah ...", - -(Spec 2) [optional] {String} - -A longer, more complete description of the purpose or intended use of -the distribution than the one provided by the C key. - -=head3 keywords - -Example: - - keywords => [ qw/ toolchain cpan dual-life / ] - -(Spec 1.1) [optional] {List of zero or more Strings} - -A List of keywords that describe this distribution. Keywords -B include whitespace. - -=head3 no_index - -Example: - - no_index => { - file => [ 'My/Module.pm' ], - directory => [ 'My/Private' ], - package => [ 'My::Module::Secret' ], - namespace => [ 'My::Module::Sample' ], - } - -(Spec 1.2) [optional] {Map} - -This Map describes any files, directories, packages, and namespaces that -are private to the packaging or implementation of the distribution and -should be ignored by indexing or search tools. - -Valid subkeys are as follows: - -=over - -=item file - -A I of relative paths to files. Paths B specified with -unix convetions. - -=item directory - -A I of relative paths to directories. Paths B specified -with unix convetions. - -[ Note: previous editions of the spec had C instead of C ] - -=item package - -A I of package names. - -=item namespace - -A I of package namespaces, where anything below the namespace -must be ignored, but I the namespace itself. - -In the example above for C, C would -be ignored, but C would not. - -=back - -=head3 optional_features - -Example: - - optional_features => { - sqlite => { - description => 'Provides SQLite support', - prereqs => { - runtime => { - requires => { - 'DBD::SQLite' => '1.25' - } - } - } - } - } - -(Spec 2) [optional] {Map} - -This Map describes optional features with incremental prerequisites. -Each key of the C Map is a String used to identify -the feature and each value is a Map with additional information about -the feature. Valid subkeys include: - -=over - -=item description - -This is a String describing the feature. Every optional feature -should provide a description - -=item prereqs - -This entry is required and has the same structure as that of the -C> key. It provides a list of package requirements -that must be satisfied for the feature to be supported or enabled. - -There is one crucial restriction: the preqreqs of an optional feature -B include C phase prereqs. - -=back - -Consumers B include optional features as prerequisites without -explict instruction from users (whether via interactive prompting, -a function parameter or a configuration value, etc. ). - -If an optional feature is used by a consumer to add additional -prerequisites, the consumer should merge the optional feature -prerequisites into those given by the C key using the same -semantics. See L for details on -merging prerequisites. - -I Because there is currently no way for a -distribution to specify a dependency on an optional feature of another -dependency, the use of C is discouraged. Instead, -create a separate, installable distribution that ensures the desired -feature is available. For example, if C has a "Baz" feature, -release a separate C distribution that satisfies -requirements for the feature. - -=head3 prereqs - -Example: - - prereqs => { - runtime => { - requires => { - 'perl' => '5.006', - 'File::Spec' => '0.86', - 'JSON' => '2.16', - }, - recommends => { - 'JSON::XS' => '2.26', - }, - suggests => { - 'Archive::Tar' => '0', - }, - }, - build => { - requires => { - 'Alien::SDL' => '1.00', - }, - }, - test => { - recommends => { - 'Test::Deep' => '0.10', - }, - } - } - -(Spec 2) [optional] {Map} - -This is a Map that describes all the prerequisites of the distribution. -The keys are phases of activity, such as C, C, C -or C. Values are Maps in which the keys name the type of -prerequisite relationship such as C, C, or -C and the value provides a set of prerequisite relations. The -set of relations B be specified as a Map of package names to -version ranges. - -The full definition for this field is given in the L -section. - -=head3 provides - -Example: - - provides => { - 'Foo::Bar' => { - file => 'lib/Foo/Bar.pm', - version => 0.27_02 - }, - 'Foo::Bar::Blah' => { - file => 'lib/Foo/Bar/Blah.pm', - }, - 'Foo::Bar::Baz' => { - file => 'lib/Foo/Bar/Baz.pm', - version => 0.3, - }, - } - -(Spec 1.2) [optional] {Map} - -This describes all packages provided by this distribution. This -information is used by distribution and automation mechanisms like -PAUSE, CPAN, and search.cpan.org to build indexes saying in which -distribution various packages can be found. - -The keys of C are package names that can be found within -the distribution. The values are Maps with the following valid subkeys: - -=over - -=item file - -This field is required. The value must contain a relative file path -from the root of the distribution to the module containing the package. - -=item version - -This field contains a I String for the package, if one exists. - -=back - -=head3 resources - -Example: - - resources => { - license => [ 'http://dev.perl.org/licenses/' ], - homepage => 'http://sourceforge.net/projects/module-build', - bugtracker => { - web => 'http://github.com/dagolden/cpan-meta-spec/issues', - mailto => 'meta-bugs@example.com', - }, - repository => { - url => 'git://github.com/dagolden/cpan-meta-spec.git', - web => 'http://github.com/dagolden/cpan-meta-spec', - type => 'git', - }, - x_twitter => 'http://twitter.com/cpan_linked/', - } - -(Spec 2) [optional] {Map} - -This field describes resources related to this distribution. - -Valid subkeys include: - -=over - -=item homepage - -The official home of this project on the web. - -=item license - -A List of I's that relate to this distribution's license. As with the -top-level C field, distribution documentation should be consulted -to clarify the interpretation of multiple licenses provided here. - -=item bugtracker - -This entry describes the bug tracking system for this distribution. It -is a Map with the following valid keys: - - web - a URL pointing to a web front-end for the bug tracker - mailto - an email address to which bugs can be sent - -=item repository - -This entry describes the source control repository for this distribution. It -is a Map with the following valid keys: - - url - a URL pointing to the repository itself - web - a URL pointing to a web front-end for the repository - type - a lowercase string indicating the VCS used - -Because a url like C is ambiguous as to -type, producers should provide a C whenever a C key is given. -The C field should be the name of the most common program used -to work with the repository, e.g. git, svn, cvs, darcs, bzr or hg. - -=back - -=head2 DEPRECATED FIELDS - -=head3 build_requires - -I<(Deprecated in Spec 2)> [optional] {String} - -Replaced by C - -=head3 configure_requires - -I<(Deprecated in Spec 2)> [optional] {String} - -Replaced by C - -=head3 conflicts - -I<(Deprecated in Spec 2)> [optional] {String} - -Replaced by C - -=head3 distribution_type - -I<(Deprecated in Spec 2)> [optional] {String} - -This field indicated 'module' or 'script' but was considered -meaningless, since many distributions are hybrids of several kinds of -things. - -=head3 license_uri - -I<(Deprecated in Spec 1.2)> [optional] {URL} - -Replaced by C in C - -=head3 private - -I<(Deprecated in Spec 1.2)> [optional] {Map} - -This field has been renamed to L. - -=head3 recommends - -I<(Deprecated in Spec 2)> [optional] {String} - -Replaced by C - -=head3 requires - -I<(Deprecated in Spec 2)> [optional] {String} - -Replaced by C - -=head1 VERSION NUMBERS - -=head2 Version Formats - -This section defines the Version type, used by several fields in the -CPAN Meta Spec. - -Version numbers must be treated as strings, not numbers. For -example, C<1.200> B be serialized as C<1.2>. Version -comparison should be delegated to the Perl L module, version -0.80 or newer. - -Unless otherwise specified, version numbers B appear in one of two -formats: - -=over - -=item Decimal versions - -Decimal versions are regular "decimal numbers", with some limitations. -They B be non-negative and B begin and end with a digit. A -single underscore B be included, but B be between two digits. -They B use exponential notation ("1.23e-2"). - - version => '1.234' # OK - version => '1.23_04' # OK - - version => '1.23_04_05' # Illegal - version => '1.' # Illegal - version => '.1' # Illegal - -=item Dotted-integer versions - -Dotted-integer (also known as dotted-decimal) versions consist of -positive integers separated by full stop characters (i.e. "dots", -"periods" or "decimal points"). This are equivalent in format to Perl -"v-strings", with some additional restrictions on form. They must be -given in "normal" form, which has a leading "v" character and at least -three integer components. To retain a one-to-one mapping with decimal -versions, all components after the first B be restricted to the -range 0 to 999. The final component B be separated by an -underscore character instead of a period. - - version => 'v1.2.3' # OK - version => 'v1.2_3' # OK - version => 'v1.2.3.4' # OK - version => 'v1.2.3_4' # OK - version => 'v2009.10.31' # OK - - version => 'v1.2' # Illegal - version => '1.2.3' # Illegal - version => 'v1.2_3_4' # Illegal - version => 'v1.2009.10.31' # Not recommended - -=back - -=head2 Version Ranges - -Some fields (prereq, optional_features) indicate the particular -version(s) of some other module that may be required as a prerequisite. -This section details the Version Range type used to provide this -information. - -The simplest format for a Version Range is just the version -number itself, e.g. C<2.4>. This means that B version 2.4 -must be present. To indicate that B version of a prerequisite is -okay, even if the prerequisite doesn't define a version at all, use -the version C<0>. - -Alternatively, a version range B use the operators E (less than), -E= (less than or equal), E (greater than), E= (greater than -or equal), == (equal), and != (not equal). For example, the -specification C 2.0> means that any version of the prerequisite -less than 2.0 is suitable. - -For more complicated situations, version specifications B be AND-ed -together using commas. The specification C= 1.2, != 1.5, E -2.0> indicates a version that must be B 1.2, B 2.0, -and B 1.5. - -=head1 PREREQUISITES - -=head2 Prereq Spec - -The C key in the top-level metadata and within -C define the relationship between a distribution and -other packages. The prereq spec structure is a hierarchical data -structure which divides prerequisites into I of activity in the -installation process and I that indicate how -prerequisites should be resolved. - -For example, to specify that C is C during the -C phase, this entry would appear in the distribution metadata: - - prereqs => { - test => { - requires => { - 'Data::Dumper' => '2.00' - } - } - } - -=head3 Phases - -Requirements for regular use must be listed in the C phase. -Other requirements should be listed in the earliest stage in which they -are required and consumers must accumulate and satisfy requirements -across phases before executing the activity. For example, C -requirements must also be available during the C phase. - - before action requirements that must be met - ---------------- -------------------------------- - perl Build.PL configure - perl Makefile.PL - - make configure, runtime, build - Build - - make test configure, runtime, build, test - Build test - -Consumers that install the distribution must ensure that -I requirements are also installed and may install -dependencies from other phases. - - after action requirements that must be met - ---------------- -------------------------------- - make install runtime - Build install - -=over - -=item configure - -The configure phase occurs before any dynamic configuration has been -attempted. Libraries required by the configure phase B be -available for use before the distribution building tool has been -executed. - -=item build - -The build phase is when the distribution's source code is compiled (if -necessary) and otherwise made ready for installation. - -=item test - -The test phase is when the distribution's automated test suite is run. -Any library that is needed only for testing and not for subsequent use -should be listed here. - -=item runtime - -The runtime phase refers not only to when the distribution's contents -are installed, but also to its continued use. Any library that is a -prerequisite for regular use of this distribution should be indicated -here. - -=item develop - -The develop phase's prereqs are libraries needed to work on the -distribution's source code as its author does. These tools might be -needed to build a release tarball, to run author-only tests, or to -perform other tasks related to developing new versions of the -distribution. - -=back - -=head3 Relationships - -=over - -=item requires - -These dependencies B be installed for proper completion of the -phase. - -=item recommends - -Recommended dependencies are I encouraged and should be -satisfied except in resource constrained environments. - -=item suggests - -These dependencies are optional, but are suggested for enhanced operation -of the described distribution. - -=item conflicts - -These libraries cannot be installed when the phase is in operation. -This is a very rare situation, and the C relationship should -be used with great caution, or not at all. - -=back - -=head2 Merging and Resolving Prerequisites - -Whenever metadata consumers merge prerequisites, either from different -phases or from C, they should merged in a way which -preserves the intended semantics of the prerequisite structure. Generally, -this means concatenating the version specifications using commas, as -described in the L section. - -Another subtle error that can occur in resolving prerequisites comes from -the way that modules in prerequisites are indexed to distribution files on -CPAN. When a module is deleted from a distribution, prerequisites calling -for that module could indicate an older distribution should installed, -potentially overwriting files from a newer distribution. - -For example, as of Oct 31, 2009, the CPAN index file contained these -module-distribution mappings: - - Class::MOP 0.94 D/DR/DROLSKY/Class-MOP-0.94.tar.gz - Class::MOP::Class 0.94 D/DR/DROLSKY/Class-MOP-0.94.tar.gz - Class::MOP::Class::Immutable 0.04 S/ST/STEVAN/Class-MOP-0.36.tar.gz - -Consider the case where "Class::MOP" 0.94 is installed. If a -distribution specified "Class::MOP::Class::Immutable" as a prerequisite, -it could result in Class-MOP-0.36.tar.gz being installed, overwriting -any files from Class-MOP-0.94.tar.gz. - -Consumers of metadata B test whether prerequisites would result -in installed module files being "downgraded" to an older version and -B warn users or ignore the prerequisite that would cause such a -result. - -=head1 SERIALIZATION - -Distribution metadata should be serialized (as a hashref) as -JSON-encoded data and packaged with distributions as the file -F. - -In the past, the distribution metadata structure had been packed with -distributions as F, a file in the YAML Tiny format (for which, -see L). Tools that consume distribution metadata from disk -should be capable of loading F, but should prefer F -if both are found. - -=head1 NOTES FOR IMPLEMENTORS - -=head2 Extracting Version Numbers from Perl Modules - -To get the version number from a Perl module, consumers should use the -C<< MM->parse_version($file) >> method provided by L or -the L module provided with L. For -example, for the module given by C<$mod>, the version may be retrieved in one -of the following ways: - - # via ExtUtils::MakeMaker - my $file = MM->_installed_file_for_module($mod); - my $version = MM->parse_version($file) - -The private C<_installed_file_for_module> method may be replaced with -other methods for locating a module in C<@INC>. - - # via Module::Build - my $info = Module::Build::ModuleInfo->new_from_module($mod); - my $version = $info->version; - -If only a filename is available, the following approach may be used: - - # via Module::Build - my $info = Module::Build::ModuleInfo->new_from_file($file); - my $version = $info->version; - -=head2 Comparing Version Numbers - -The L module provides the most reliable way to compare version -numbers in all the various ways they might be provided or might exist -within modules. Given two strings containing version numbers, C<$v1> and -C<$v2>, they should be converted to C objects before using -ordinary comparison operators. For example: - - use version; - if ( version->new($v1) <=> version->new($v2) ) { - print "Versions are not equal\n"; - } - -If the only comparison needed is whether an installed module is of a -sufficiently high version, a direct test may be done using the string -form of C and the C function. For example, for module C<$mod> -and version prerequisite C<$prereq>: - - if ( eval "use $mod $prereq (); 1" ) { - print "Module $mod version is OK.\n"; - } - -If the values of C<$mod> and C<$prereq> have not been scrubbed, however, -this presents security implications. - -=head1 SEE ALSO - -CPAN, L - -CPAN.pm, L - -CPANPLUS, L - -ExtUtils::MakeMaker, L - -Module::Build, L - -Module::Install, L - -JSON, L - -YAML, L - -=head1 CONTRIBUTORS - -Ken Williams wrote the original CPAN Meta Spec (also known as the -"META.yml spec") in 2003 and maintained it through several revisions -with input from various members of the community. In 2005, Randy -Sims redrafted it from HTML to POD for the version 1.2 release. Ken -continued to maintain the spec through version 1.4. - -In late 2009, David Golden organized the version 2 proposal review -process. David and Ricardo Signes drafted the final version 2 spec -in April 2010 based on the version 1.4 spec and patches contributed -during the proposal process. - -Several others have contributed patches over the years. The full list -of contributors in the repository history currently includes: - - 2shortplanks - Avar Arnfjord Bjarmason - Christopher J. Madsen - Damyan Ivanov - David Golden - Eric Wilhelm - Ken Williams - Lars DIECKOW - Michael G. Schwern - Randy Sims - Ricardo Signes - -=head1 AUTHORS - -=over 4 - -=item * - -David Golden - -=item * - -Ricardo Signes - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 2010 by David Golden and Ricardo Signes. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - diff --git a/perl/vendor/lib/CPAN/Meta/Validator.pm b/perl/vendor/lib/CPAN/Meta/Validator.pm deleted file mode 100644 index 819011c..0000000 --- a/perl/vendor/lib/CPAN/Meta/Validator.pm +++ /dev/null @@ -1,1002 +0,0 @@ -use 5.006; -use strict; -use warnings; -package CPAN::Meta::Validator; -BEGIN { - $CPAN::Meta::Validator::VERSION = '2.110930'; -} -# ABSTRACT: validate CPAN distribution metadata structures - - -#--------------------------------------------------------------------------# -# This code copied and adapted from Test::CPAN::Meta -# by Barbie, for Miss Barbell Productions, -# L -#--------------------------------------------------------------------------# - -#--------------------------------------------------------------------------# -# Specification Definitions -#--------------------------------------------------------------------------# - -my %known_specs = ( - '1.4' => 'http://module-build.sourceforge.net/META-spec-v1.4.html', - '1.3' => 'http://module-build.sourceforge.net/META-spec-v1.3.html', - '1.2' => 'http://module-build.sourceforge.net/META-spec-v1.2.html', - '1.1' => 'http://module-build.sourceforge.net/META-spec-v1.1.html', - '1.0' => 'http://module-build.sourceforge.net/META-spec-v1.0.html' -); -my %known_urls = map {$known_specs{$_} => $_} keys %known_specs; - -my $module_map1 = { 'map' => { ':key' => { name => \&module, value => \&exversion } } }; - -my $module_map2 = { 'map' => { ':key' => { name => \&module, value => \&version } } }; - -my $no_index_2 = { - 'map' => { file => { list => { value => \&string } }, - directory => { list => { value => \&string } }, - 'package' => { list => { value => \&string } }, - namespace => { list => { value => \&string } }, - ':key' => { name => \&custom_2, value => \&anything }, - } -}; - -my $no_index_1_3 = { - 'map' => { file => { list => { value => \&string } }, - directory => { list => { value => \&string } }, - 'package' => { list => { value => \&string } }, - namespace => { list => { value => \&string } }, - ':key' => { name => \&string, value => \&anything }, - } -}; - -my $no_index_1_2 = { - 'map' => { file => { list => { value => \&string } }, - dir => { list => { value => \&string } }, - 'package' => { list => { value => \&string } }, - namespace => { list => { value => \&string } }, - ':key' => { name => \&string, value => \&anything }, - } -}; - -my $no_index_1_1 = { - 'map' => { ':key' => { name => \&string, list => { value => \&string } }, - } -}; - -my $prereq_map = { - map => { - ':key' => { - name => \&phase, - 'map' => { - ':key' => { - name => \&relation, - %$module_map1, - }, - }, - } - }, -}; - -my %definitions = ( - '2' => { - # REQUIRED - 'abstract' => { mandatory => 1, value => \&string }, - 'author' => { mandatory => 1, lazylist => { value => \&string } }, - 'dynamic_config' => { mandatory => 1, value => \&boolean }, - 'generated_by' => { mandatory => 1, value => \&string }, - 'license' => { mandatory => 1, lazylist => { value => \&license } }, - 'meta-spec' => { - mandatory => 1, - 'map' => { - version => { mandatory => 1, value => \&version}, - url => { value => \&url }, - ':key' => { name => \&custom_2, value => \&anything }, - } - }, - 'name' => { mandatory => 1, value => \&string }, - 'release_status' => { mandatory => 1, value => \&release_status }, - 'version' => { mandatory => 1, value => \&version }, - - # OPTIONAL - 'description' => { value => \&string }, - 'keywords' => { lazylist => { value => \&string } }, - 'no_index' => $no_index_2, - 'optional_features' => { - 'map' => { - ':key' => { - name => \&string, - 'map' => { - description => { value => \&string }, - prereqs => $prereq_map, - ':key' => { name => \&custom_2, value => \&anything }, - } - } - } - }, - 'prereqs' => $prereq_map, - 'provides' => { - 'map' => { - ':key' => { - name => \&module, - 'map' => { - file => { mandatory => 1, value => \&file }, - version => { value => \&version }, - ':key' => { name => \&custom_2, value => \&anything }, - } - } - } - }, - 'resources' => { - 'map' => { - license => { lazylist => { value => \&url } }, - homepage => { value => \&url }, - bugtracker => { - 'map' => { - web => { value => \&url }, - mailto => { value => \&string}, - ':key' => { name => \&custom_2, value => \&anything }, - } - }, - repository => { - 'map' => { - web => { value => \&url }, - url => { value => \&url }, - type => { value => \&string }, - ':key' => { name => \&custom_2, value => \&anything }, - } - }, - ':key' => { value => \&string, name => \&custom_2 }, - } - }, - - # CUSTOM -- additional user defined key/value pairs - # note we can only validate the key name, as the structure is user defined - ':key' => { name => \&custom_2, value => \&anything }, - }, - -'1.4' => { - 'meta-spec' => { - mandatory => 1, - 'map' => { - version => { mandatory => 1, value => \&version}, - url => { mandatory => 1, value => \&urlspec }, - ':key' => { name => \&string, value => \&anything }, - }, - }, - - 'name' => { mandatory => 1, value => \&string }, - 'version' => { mandatory => 1, value => \&version }, - 'abstract' => { mandatory => 1, value => \&string }, - 'author' => { mandatory => 1, list => { value => \&string } }, - 'license' => { mandatory => 1, value => \&license }, - 'generated_by' => { mandatory => 1, value => \&string }, - - 'distribution_type' => { value => \&string }, - 'dynamic_config' => { value => \&boolean }, - - 'requires' => $module_map1, - 'recommends' => $module_map1, - 'build_requires' => $module_map1, - 'configure_requires' => $module_map1, - 'conflicts' => $module_map2, - - 'optional_features' => { - 'map' => { - ':key' => { name => \&string, - 'map' => { description => { value => \&string }, - requires => $module_map1, - recommends => $module_map1, - build_requires => $module_map1, - conflicts => $module_map2, - ':key' => { name => \&string, value => \&anything }, - } - } - } - }, - - 'provides' => { - 'map' => { - ':key' => { name => \&module, - 'map' => { - file => { mandatory => 1, value => \&file }, - version => { value => \&version }, - ':key' => { name => \&string, value => \&anything }, - } - } - } - }, - - 'no_index' => $no_index_1_3, - 'private' => $no_index_1_3, - - 'keywords' => { list => { value => \&string } }, - - 'resources' => { - 'map' => { license => { value => \&url }, - homepage => { value => \&url }, - bugtracker => { value => \&url }, - repository => { value => \&url }, - ':key' => { value => \&string, name => \&custom_1 }, - } - }, - - # additional user defined key/value pairs - # note we can only validate the key name, as the structure is user defined - ':key' => { name => \&string, value => \&anything }, -}, - -'1.3' => { - 'meta-spec' => { - mandatory => 1, - 'map' => { - version => { mandatory => 1, value => \&version}, - url => { mandatory => 1, value => \&urlspec }, - ':key' => { name => \&string, value => \&anything }, - }, - }, - - 'name' => { mandatory => 1, value => \&string }, - 'version' => { mandatory => 1, value => \&version }, - 'abstract' => { mandatory => 1, value => \&string }, - 'author' => { mandatory => 1, list => { value => \&string } }, - 'license' => { mandatory => 1, value => \&license }, - 'generated_by' => { mandatory => 1, value => \&string }, - - 'distribution_type' => { value => \&string }, - 'dynamic_config' => { value => \&boolean }, - - 'requires' => $module_map1, - 'recommends' => $module_map1, - 'build_requires' => $module_map1, - 'conflicts' => $module_map2, - - 'optional_features' => { - 'map' => { - ':key' => { name => \&string, - 'map' => { description => { value => \&string }, - requires => $module_map1, - recommends => $module_map1, - build_requires => $module_map1, - conflicts => $module_map2, - ':key' => { name => \&string, value => \&anything }, - } - } - } - }, - - 'provides' => { - 'map' => { - ':key' => { name => \&module, - 'map' => { - file => { mandatory => 1, value => \&file }, - version => { value => \&version }, - ':key' => { name => \&string, value => \&anything }, - } - } - } - }, - - - 'no_index' => $no_index_1_3, - 'private' => $no_index_1_3, - - 'keywords' => { list => { value => \&string } }, - - 'resources' => { - 'map' => { license => { value => \&url }, - homepage => { value => \&url }, - bugtracker => { value => \&url }, - repository => { value => \&url }, - ':key' => { value => \&string, name => \&custom_1 }, - } - }, - - # additional user defined key/value pairs - # note we can only validate the key name, as the structure is user defined - ':key' => { name => \&string, value => \&anything }, -}, - -# v1.2 is misleading, it seems to assume that a number of fields where created -# within v1.1, when they were created within v1.2. This may have been an -# original mistake, and that a v1.1 was retro fitted into the timeline, when -# v1.2 was originally slated as v1.1. But I could be wrong ;) -'1.2' => { - 'meta-spec' => { - mandatory => 1, - 'map' => { - version => { mandatory => 1, value => \&version}, - url => { mandatory => 1, value => \&urlspec }, - ':key' => { name => \&string, value => \&anything }, - }, - }, - - - 'name' => { mandatory => 1, value => \&string }, - 'version' => { mandatory => 1, value => \&version }, - 'license' => { mandatory => 1, value => \&license }, - 'generated_by' => { mandatory => 1, value => \&string }, - 'author' => { mandatory => 1, list => { value => \&string } }, - 'abstract' => { mandatory => 1, value => \&string }, - - 'distribution_type' => { value => \&string }, - 'dynamic_config' => { value => \&boolean }, - - 'keywords' => { list => { value => \&string } }, - - 'private' => $no_index_1_2, - '$no_index' => $no_index_1_2, - - 'requires' => $module_map1, - 'recommends' => $module_map1, - 'build_requires' => $module_map1, - 'conflicts' => $module_map2, - - 'optional_features' => { - 'map' => { - ':key' => { name => \&string, - 'map' => { description => { value => \&string }, - requires => $module_map1, - recommends => $module_map1, - build_requires => $module_map1, - conflicts => $module_map2, - ':key' => { name => \&string, value => \&anything }, - } - } - } - }, - - 'provides' => { - 'map' => { - ':key' => { name => \&module, - 'map' => { - file => { mandatory => 1, value => \&file }, - version => { value => \&version }, - ':key' => { name => \&string, value => \&anything }, - } - } - } - }, - - 'resources' => { - 'map' => { license => { value => \&url }, - homepage => { value => \&url }, - bugtracker => { value => \&url }, - repository => { value => \&url }, - ':key' => { value => \&string, name => \&custom_1 }, - } - }, - - # additional user defined key/value pairs - # note we can only validate the key name, as the structure is user defined - ':key' => { name => \&string, value => \&anything }, -}, - -# note that the 1.1 spec only specifies 'version' as mandatory -'1.1' => { - 'name' => { value => \&string }, - 'version' => { mandatory => 1, value => \&version }, - 'license' => { value => \&license }, - 'generated_by' => { value => \&string }, - - 'license_uri' => { value => \&url }, - 'distribution_type' => { value => \&string }, - 'dynamic_config' => { value => \&boolean }, - - 'private' => $no_index_1_1, - - 'requires' => $module_map1, - 'recommends' => $module_map1, - 'build_requires' => $module_map1, - 'conflicts' => $module_map2, - - # additional user defined key/value pairs - # note we can only validate the key name, as the structure is user defined - ':key' => { name => \&string, value => \&anything }, -}, - -# note that the 1.0 spec doesn't specify optional or mandatory fields -# but we will treat version as mandatory since otherwise META 1.0 is -# completely arbitrary and pointless -'1.0' => { - 'name' => { value => \&string }, - 'version' => { mandatory => 1, value => \&version }, - 'license' => { value => \&license }, - 'generated_by' => { value => \&string }, - - 'license_uri' => { value => \&url }, - 'distribution_type' => { value => \&string }, - 'dynamic_config' => { value => \&boolean }, - - 'requires' => $module_map1, - 'recommends' => $module_map1, - 'build_requires' => $module_map1, - 'conflicts' => $module_map2, - - # additional user defined key/value pairs - # note we can only validate the key name, as the structure is user defined - ':key' => { name => \&string, value => \&anything }, -}, -); - -#--------------------------------------------------------------------------# -# Code -#--------------------------------------------------------------------------# - - -sub new { - my ($class,$data) = @_; - - # create an attributes hash - my $self = { - 'data' => $data, - 'spec' => $data->{'meta-spec'}{'version'} || "1.0", - 'errors' => undef, - }; - - # create the object - return bless $self, $class; -} - - -sub is_valid { - my $self = shift; - my $data = $self->{data}; - my $spec_version = $self->{spec}; - $self->check_map($definitions{$spec_version},$data); - return ! $self->errors; -} - - -sub errors { - my $self = shift; - return () unless(defined $self->{errors}); - return @{$self->{errors}}; -} - - -my $spec_error = "Missing validation action in specification. " - . "Must be one of 'map', 'list', 'lazylist', or 'value'"; - -sub check_map { - my ($self,$spec,$data) = @_; - - if(ref($spec) ne 'HASH') { - $self->_error( "Unknown META specification, cannot validate." ); - return; - } - - if(ref($data) ne 'HASH') { - $self->_error( "Expected a map structure from string or file." ); - return; - } - - for my $key (keys %$spec) { - next unless($spec->{$key}->{mandatory}); - next if(defined $data->{$key}); - push @{$self->{stack}}, $key; - $self->_error( "Missing mandatory field, '$key'" ); - pop @{$self->{stack}}; - } - - for my $key (keys %$data) { - push @{$self->{stack}}, $key; - if($spec->{$key}) { - if($spec->{$key}{value}) { - $spec->{$key}{value}->($self,$key,$data->{$key}); - } elsif($spec->{$key}{'map'}) { - $self->check_map($spec->{$key}{'map'},$data->{$key}); - } elsif($spec->{$key}{'list'}) { - $self->check_list($spec->{$key}{'list'},$data->{$key}); - } elsif($spec->{$key}{'lazylist'}) { - $self->check_lazylist($spec->{$key}{'lazylist'},$data->{$key}); - } else { - $self->_error( "$spec_error for '$key'" ); - } - - } elsif ($spec->{':key'}) { - $spec->{':key'}{name}->($self,$key,$key); - if($spec->{':key'}{value}) { - $spec->{':key'}{value}->($self,$key,$data->{$key}); - } elsif($spec->{':key'}{'map'}) { - $self->check_map($spec->{':key'}{'map'},$data->{$key}); - } elsif($spec->{':key'}{'list'}) { - $self->check_list($spec->{':key'}{'list'},$data->{$key}); - } elsif($spec->{':key'}{'lazylist'}) { - $self->check_lazylist($spec->{':key'}{'lazylist'},$data->{$key}); - } else { - $self->_error( "$spec_error for ':key'" ); - } - - - } else { - $self->_error( "Unknown key, '$key', found in map structure" ); - } - pop @{$self->{stack}}; - } -} - -# if it's a string, make it into a list and check the list -sub check_lazylist { - my ($self,$spec,$data) = @_; - - if ( defined $data && ! ref($data) ) { - $data = [ $data ]; - } - - $self->check_list($spec,$data); -} - -sub check_list { - my ($self,$spec,$data) = @_; - - if(ref($data) ne 'ARRAY') { - $self->_error( "Expected a list structure" ); - return; - } - - if(defined $spec->{mandatory}) { - if(!defined $data->[0]) { - $self->_error( "Missing entries from mandatory list" ); - } - } - - for my $value (@$data) { - push @{$self->{stack}}, $value || ""; - if(defined $spec->{value}) { - $spec->{value}->($self,'list',$value); - } elsif(defined $spec->{'map'}) { - $self->check_map($spec->{'map'},$value); - } elsif(defined $spec->{'list'}) { - $self->check_list($spec->{'list'},$value); - } elsif(defined $spec->{'lazylist'}) { - $self->check_lazylist($spec->{'lazylist'},$value); - } elsif ($spec->{':key'}) { - $self->check_map($spec,$value); - } else { - $self->_error( "$spec_error associated with '$self->{stack}[-2]'" ); - } - pop @{$self->{stack}}; - } -} - - -sub header { - my ($self,$key,$value) = @_; - if(defined $value) { - return 1 if($value && $value =~ /^--- #YAML:1.0/); - } - $self->_error( "file does not have a valid YAML header." ); - return 0; -} - -sub release_status { - my ($self,$key,$value) = @_; - if(defined $value) { - my $version = $self->{data}{version} || ''; - if ( $version =~ /_/ ) { - return 1 if ( $value =~ /\A(?:testing|unstable)\z/ ); - $self->_error( "'$value' for '$key' is invalid for version '$version'" ); - } - else { - return 1 if ( $value =~ /\A(?:stable|testing|unstable)\z/ ); - $self->_error( "'$value' for '$key' is invalid" ); - } - } - else { - $self->_error( "'$key' is not defined" ); - } - return 0; -} - -# _uri_split taken from URI::Split by Gisle Aas, Copyright 2003 -sub _uri_split { - return $_[0] =~ m,(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?,; -} - -sub url { - my ($self,$key,$value) = @_; - if(defined $value) { - my ($scheme, $auth, $path, $query, $frag) = _uri_split($value); - unless ( defined $scheme && length $scheme ) { - $self->_error( "'$value' for '$key' does not have a URL scheme" ); - return 0; - } - unless ( defined $auth && length $auth ) { - $self->_error( "'$value' for '$key' does not have a URL authority" ); - return 0; - } - return 1; - } - $value ||= ''; - $self->_error( "'$value' for '$key' is not a valid URL." ); - return 0; -} - -sub urlspec { - my ($self,$key,$value) = @_; - if(defined $value) { - return 1 if($value && $known_specs{$self->{spec}} eq $value); - if($value && $known_urls{$value}) { - $self->_error( 'META specification URL does not match version' ); - return 0; - } - } - $self->_error( 'Unknown META specification' ); - return 0; -} - -sub anything { return 1 } - -sub string { - my ($self,$key,$value) = @_; - if(defined $value) { - return 1 if($value || $value =~ /^0$/); - } - $self->_error( "value is an undefined string" ); - return 0; -} - -sub string_or_undef { - my ($self,$key,$value) = @_; - return 1 unless(defined $value); - return 1 if($value || $value =~ /^0$/); - $self->_error( "No string defined for '$key'" ); - return 0; -} - -sub file { - my ($self,$key,$value) = @_; - return 1 if(defined $value); - $self->_error( "No file defined for '$key'" ); - return 0; -} - -sub exversion { - my ($self,$key,$value) = @_; - if(defined $value && ($value || $value =~ /0/)) { - my $pass = 1; - for(split(",",$value)) { $self->version($key,$_) or ($pass = 0); } - return $pass; - } - $value = '' unless(defined $value); - $self->_error( "'$value' for '$key' is not a valid version." ); - return 0; -} - -sub version { - my ($self,$key,$value) = @_; - if(defined $value) { - return 0 unless($value || $value =~ /0/); - return 1 if($value =~ /^\s*((<|<=|>=|>|!=|==)\s*)?v?\d+((\.\d+((_|\.)\d+)?)?)/); - } else { - $value = ''; - } - $self->_error( "'$value' for '$key' is not a valid version." ); - return 0; -} - -sub boolean { - my ($self,$key,$value) = @_; - if(defined $value) { - return 1 if($value =~ /^(0|1|true|false)$/); - } else { - $value = ''; - } - $self->_error( "'$value' for '$key' is not a boolean value." ); - return 0; -} - -my %v1_licenses = ( - 'perl' => 'http://dev.perl.org/licenses/', - 'gpl' => 'http://www.opensource.org/licenses/gpl-license.php', - 'apache' => 'http://apache.org/licenses/LICENSE-2.0', - 'artistic' => 'http://opensource.org/licenses/artistic-license.php', - 'artistic_2' => 'http://opensource.org/licenses/artistic-license-2.0.php', - 'lgpl' => 'http://www.opensource.org/licenses/lgpl-license.phpt', - 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php', - 'gpl' => 'http://www.opensource.org/licenses/gpl-license.php', - 'mit' => 'http://opensource.org/licenses/mit-license.php', - 'mozilla' => 'http://opensource.org/licenses/mozilla1.1.php', - 'open_source' => undef, - 'unrestricted' => undef, - 'restrictive' => undef, - 'unknown' => undef, -); - -my %v2_licenses = map { $_ => 1 } qw( - agpl_3 - apache_1_1 - apache_2_0 - artistic_1 - artistic_2 - bsd - freebsd - gfdl_1_2 - gfdl_1_3 - gpl_1 - gpl_2 - gpl_3 - lgpl_2_1 - lgpl_3_0 - mit - mozilla_1_0 - mozilla_1_1 - openssl - perl_5 - qpl_1_0 - ssleay - sun - zlib - open_source - restricted - unrestricted - unknown -); - -sub license { - my ($self,$key,$value) = @_; - my $licenses = $self->{spec} < 2 ? \%v1_licenses : \%v2_licenses; - if(defined $value) { - return 1 if($value && exists $licenses->{$value}); - } else { - $value = ''; - } - $self->_error( "License '$value' is invalid" ); - return 0; -} - -sub custom_1 { - my ($self,$key) = @_; - if(defined $key) { - # a valid user defined key should be alphabetic - # and contain at least one capital case letter. - return 1 if($key && $key =~ /^[_a-z]+$/i && $key =~ /[A-Z]/); - } else { - $key = ''; - } - $self->_error( "Custom resource '$key' must be in CamelCase." ); - return 0; -} - -sub custom_2 { - my ($self,$key) = @_; - if(defined $key) { - return 1 if($key && $key =~ /^x_/i); # user defined - } else { - $key = ''; - } - $self->_error( "Custom key '$key' must begin with 'x_' or 'X_'." ); - return 0; -} - -sub identifier { - my ($self,$key) = @_; - if(defined $key) { - return 1 if($key && $key =~ /^([a-z][_a-z]+)$/i); # spec 2.0 defined - } else { - $key = ''; - } - $self->_error( "Key '$key' is not a legal identifier." ); - return 0; -} - -sub module { - my ($self,$key) = @_; - if(defined $key) { - return 1 if($key && $key =~ /^[A-Za-z0-9_]+(::[A-Za-z0-9_]+)*$/); - } else { - $key = ''; - } - $self->_error( "Key '$key' is not a legal module name." ); - return 0; -} - -my @valid_phases = qw/ configure build test runtime develop /; -sub phase { - my ($self,$key) = @_; - if(defined $key) { - return 1 if( length $key && grep { $key eq $_ } @valid_phases ); - return 1 if $key =~ /x_/i; - } else { - $key = ''; - } - $self->_error( "Key '$key' is not a legal phase." ); - return 0; -} - -my @valid_relations = qw/ requires recommends suggests conflicts /; -sub relation { - my ($self,$key) = @_; - if(defined $key) { - return 1 if( length $key && grep { $key eq $_ } @valid_relations ); - return 1 if $key =~ /x_/i; - } else { - $key = ''; - } - $self->_error( "Key '$key' is not a legal prereq relationship." ); - return 0; -} - -sub _error { - my $self = shift; - my $mess = shift; - - $mess .= ' ('.join(' -> ',@{$self->{stack}}).')' if($self->{stack}); - $mess .= " [Validation: $self->{spec}]"; - - push @{$self->{errors}}, $mess; -} - -1; - - - -=pod - -=head1 NAME - -CPAN::Meta::Validator - validate CPAN distribution metadata structures - -=head1 VERSION - -version 2.110930 - -=head1 SYNOPSIS - - my $struct = decode_json_file('META.json'); - - my $cmv = CPAN::Meta::Validator->new( $struct ); - - unless ( $cmv->is_valid ) { - my $msg = "Invalid META structure. Errors found:\n"; - $msg .= join( "\n", $cmv->errors ); - die $msg; - } - -=head1 DESCRIPTION - -This module validates a CPAN Meta structure against the version of the -the specification claimed in the C field of the structure. - -=head1 METHODS - -=head2 new - - my $cmv = CPAN::Meta::Validator->new( $struct ) - -The constructor must be passed a metadata structure. - -=head2 is_valid - - if ( $cmv->is_valid ) { - ... - } - -Returns a boolean value indicating whether the metadata provided -is valid. - -=head2 errors - - warn( join "\n", $cmv->errors ); - -Returns a list of errors seen during validation. - -=begin internals - -=head2 Check Methods - -=over - -=item * check_map($spec,$data) - -Checks whether a map (or hash) part of the data structure conforms to the -appropriate specification definition. -=item * check_list($spec,$data) - -Checks whether a list (or array) part of the data structure conforms to -the appropriate specification definition. -=item * check_lazylist($spec,$data) - -Checks whether a list conforms, but converts strings to a single-element list -=back - -=head2 Validator Methods - -=over - -=item * header($self,$key,$value) - -Validates that the header is valid. - -Note: No longer used as we now read the data structure, not the file.=item * url($self,$key,$value) - -Validates that a given value is in an acceptable URL format -=item * urlspec($self,$key,$value) - -Validates that the URL to a META specification is a known one. -=item * string_or_undef($self,$key,$value) - -Validates that the value is either a string or an undef value. Bit of a -catchall function for parts of the data structure that are completely user -defined. -=item * string($self,$key,$value) - -Validates that a string exists for the given key. -=item * file($self,$key,$value) - -Validate that a file is passed for the given key. This may be made more -thorough in the future. For now it acts like \&string. -=item * exversion($self,$key,$value) - -Validates a list of versions, e.g. '<= 5, >=2, ==3, !=4, >1, <6, 0'. -=item * version($self,$key,$value) - -Validates a single version string. Versions of the type '5.8.8' and '0.00_00' -are both valid. A leading 'v' like 'v1.2.3' is also valid. -=item * boolean($self,$key,$value) - -Validates for a boolean value. Currently these values are '1', '0', 'true', -'false', however the latter 2 may be removed. -=item * license($self,$key,$value) - -Validates that a value is given for the license. Returns 1 if an known license -type, or 2 if a value is given but the license type is not a recommended one. -=item * custom_1($self,$key,$value) - -Validates that the given key is in CamelCase, to indicate a user defined -keyword and only has characters in the class [-_a-zA-Z]. In version 1.X -of the spec, this was only explicitly stated for 'resources'. -=item * custom_2($self,$key,$value) - -Validates that the given key begins with 'x_' or 'X_', to indicate a user -defined keyword and only has characters in the class [-_a-zA-Z] -=item * identifier($self,$key,$value) - -Validates that key is in an acceptable format for the META specification, -for an identifier, i.e. any that matches the regular expression -qr/[a-z][a-z_]/i. -=item * module($self,$key,$value) - -Validates that a given key is in an acceptable module name format, e.g. -'Test::CPAN::Meta::Version'. -=back - -=end internals - -=head1 BUGS - -Please report any bugs or feature using the CPAN Request Tracker. -Bugs can be submitted through the web interface at -L - -When submitting a bug or request, please include a test-file or a patch to an -existing test-file that illustrates the bug or desired feature. - -=head1 AUTHORS - -=over 4 - -=item * - -David Golden - -=item * - -Ricardo Signes - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 2010 by David Golden and Ricardo Signes. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - - -__END__ - - -