Re: [PATCH] Add CPANPLUS 0.78 to the core
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / Manifest.pm
index 819e72c..ee508c8 100644 (file)
@@ -2,8 +2,9 @@ package ExtUtils::Manifest;
 
 require Exporter;
 use Config;
-use File::Find;
+use File::Basename;
 use File::Copy 'copy';
+use File::Find;
 use File::Spec;
 use Carp;
 use strict;
@@ -12,7 +13,7 @@ use vars qw($VERSION @ISA @EXPORT_OK
           $Is_MacOS $Is_VMS 
           $Debug $Verbose $Quiet $MANIFEST $DEFAULT_MSKIP);
 
-$VERSION = 1.41;
+$VERSION = '1.51_01';
 @ISA=('Exporter');
 @EXPORT_OK = qw(mkmanifest
                 manicheck  filecheck  fullcheck  skipcheck
@@ -29,9 +30,7 @@ $Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
 $Quiet = 0;
 $MANIFEST = 'MANIFEST';
 
-my $Filename = __FILE__;
-$DEFAULT_MSKIP = (File::Spec->splitpath($Filename))[1].
-                 "$MANIFEST.SKIP";
+$DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
 
 
 =head1 NAME
@@ -94,7 +93,9 @@ sub mkmanifest {
     my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
     $read = {} if $manimiss;
     local *M;
-    rename $MANIFEST, "$MANIFEST.bak" unless $manimiss;
+    my $bakbase = $MANIFEST;
+    $bakbase =~ s/\./_/g if $Is_VMS; # avoid double dots
+    rename $MANIFEST, "$bakbase.bak" unless $manimiss;
     open M, ">$MANIFEST" or die "Could not open $MANIFEST: $!";
     my $skip = _maniskip();
     my $found = manifind();
@@ -113,7 +114,6 @@ sub mkmanifest {
            warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
        }
        my $text = $all{$file};
-       ($file,$text) = split(/\s+/,$text,2) if $Is_VMS && $text;
        $file = _unmacify($file);
        my $tabs = (5 - (length($file)+1)/8);
        $tabs = 1 if $tabs < 1;
@@ -309,7 +309,7 @@ sub maniread {
     my $read = {};
     local *M;
     unless (open M, $mfile){
-        warn "$mfile: $!";
+        warn "Problem opening $mfile: $!";
         return $read;
     }
     local $_;
@@ -347,15 +347,19 @@ sub maniread {
 sub _maniskip {
     my @skip ;
     my $mfile = "$MANIFEST.SKIP";
-    local(*M,$_);
+    _check_mskip_directives($mfile) if -f $mfile;
+    local(*M, $_);
     open M, $mfile or open M, $DEFAULT_MSKIP or return sub {0};
     while (<M>){
        chomp;
+       s/\r//;
        next if /^#/;
        next if /^\s*$/;
        push @skip, _macify($_);
     }
     close M;
+    return sub {0} unless (scalar @skip > 0);
+
     my $opts = $Is_VMS ? '(?i)' : '';
 
     # Make sure each entry is isolated in its own parentheses, in case
@@ -365,19 +369,94 @@ sub _maniskip {
     return sub { $_[0] =~ qr{$opts$regex} };
 }
 
+# checks for the special directives
+#   #!include_default
+#   #!include /path/to/some/manifest.skip
+# in a custom MANIFEST.SKIP for, for including
+# the content of, respectively, the default MANIFEST.SKIP
+# and an external manifest.skip file
+sub _check_mskip_directives {
+    my $mfile = shift;
+    local (*M, $_);
+    my @lines = ();
+    my $flag = 0;
+    unless (open M, $mfile) {
+        warn "Problem opening $mfile: $!";
+        return;
+    }
+    while (<M>) {
+        if (/^#!include_default\s*$/) {
+           if (my @default = _include_mskip_file()) {
+               push @lines, @default;
+               warn "Debug: Including default MANIFEST.SKIP\n" if $Debug;
+               $flag++;
+           }
+           next;
+        }
+       if (/^#!include\s+(.*)\s*$/) {
+           my $external_file = $1;
+           if (my @external = _include_mskip_file($external_file)) {
+               push @lines, @external;
+               warn "Debug: Including external $external_file\n" if $Debug;
+               $flag++;
+           }
+            next;
+        }
+        push @lines, $_;
+    }
+    close M;
+    return unless $flag;
+    my $bakbase = $mfile;
+    $bakbase =~ s/\./_/g if $Is_VMS;  # avoid double dots
+    rename $mfile, "$bakbase.bak";
+    warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
+    unless (open M, ">$mfile") {
+        warn "Problem opening $mfile: $!";
+        return;
+    }
+    print M $_ for (@lines);
+    close M;
+    return;
+}
+
+# returns an array containing the lines of an external
+# manifest.skip file, if given, or $DEFAULT_MSKIP
+sub _include_mskip_file {
+    my $mskip = shift || $DEFAULT_MSKIP;
+    unless (-f $mskip) {
+        warn qq{Included file "$mskip" not found - skipping};
+        return;
+    }
+    local (*M, $_);
+    unless (open M, $mskip) {
+        warn "Problem opening $mskip: $!";
+        return;
+    }
+    my @lines = ();
+    push @lines, "\n#!start included $mskip\n";
+    push @lines, $_ while <M>;
+    close M;
+    push @lines, "#!end included $mskip\n\n";
+    return @lines;
+}
+
 =item manicopy
 
-    manicopy($src, $dest_dir);
-    manicopy($src, $dest_dir, $how);
+    manicopy(\%src, $dest_dir);
+    manicopy(\%src, $dest_dir, $how);
+
+Copies the files that are the keys in %src to the $dest_dir.  %src is
+typically returned by the maniread() function.
+
+    manicopy( maniread(), $dest_dir );
+
+This function is useful for producing a directory tree identical to the 
+intended distribution tree. 
 
-copies the files that are the keys in the HASH I<%$src> to the
-$dest_dir. The HASH reference $read is typically returned by the
-maniread() function. This function is useful for producing a directory
-tree identical to the intended distribution tree. The third parameter
-$how can be used to specify a different methods of "copying". Valid
+$how can be used to specify a different methods of "copying".  Valid
 values are C<cp>, which actually copies the files, C<ln> which creates
 hard links, and C<best> which mostly links the files but copies any
-symbolic link to make a tree without any symbolic link. Best is the
+symbolic link to make a tree without any symbolic link.  C<cp> is the 
 default.
 
 =cut
@@ -429,7 +508,7 @@ sub cp_if_diff {
        if (-e $to) {
            unlink($to) or confess "unlink $to: $!";
        }
-      STRICT_SWITCH: {
+        STRICT_SWITCH: {
            best($from,$to), last STRICT_SWITCH if $how eq 'best';
            cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
            ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
@@ -442,43 +521,43 @@ sub cp_if_diff {
 
 sub cp {
     my ($srcFile, $dstFile) = @_;
-    my ($perm,$access,$mod) = (stat $srcFile)[2,8,9];
+    my ($access,$mod) = (stat $srcFile)[8,9];
+
     copy($srcFile,$dstFile);
     utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
-    # chmod a+rX-w,go-w
-    chmod(  0444 | ( $perm & 0111 ? 0111 : 0 ),  $dstFile ) 
-      unless ($^O eq 'MacOS');
+    _manicopy_chmod($srcFile, $dstFile);
 }
 
+
 sub ln {
     my ($srcFile, $dstFile) = @_;
     return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
     link($srcFile, $dstFile);
 
-    # chmod a+r,go-w+X (except "X" only applies to u=x)
-    local($_) = $dstFile;
-    my $mode= 0444 | (stat)[2] & 0700;
-    if (! chmod(  $mode | ( $mode & 0100 ? 0111 : 0 ),  $_  )) {
+    unless( _manicopy_chmod($srcFile, $dstFile) ) {
         unlink $dstFile;
         return;
     }
     1;
 }
 
-unless (defined $Config{d_link}) {
-    # Really cool fix from Ilya :)
-    local $SIG{__WARN__} = sub { 
-        warn @_ unless $_[0] =~ /^Subroutine .* redefined/;
-    };
-    *ln = \&cp;
-}
-
-
+# 1) Strip off all group and world permissions.
+# 2) Let everyone read it.
+# 3) If the owner can execute it, everyone can.
+sub _manicopy_chmod {
+    my($srcFile, $dstFile) = @_;
 
+    my $perm = 0444 | (stat $srcFile)[2] & 0700;
+    chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
+}
 
+# Files that are often modified in the distdir.  Don't hard link them.
+my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
 sub best {
     my ($srcFile, $dstFile) = @_;
-    if (-l $srcFile) {
+
+    my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
+    if ($is_exception or !$Config{d_link} or -l $srcFile) {
        cp($srcFile, $dstFile);
     } else {
        ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
@@ -489,21 +568,21 @@ sub _macify {
     my($file) = @_;
 
     return $file unless $Is_MacOS;
-    
+
     $file =~ s|^\./||;
     if ($file =~ m|/|) {
        $file =~ s|/+|:|g;
        $file = ":$file";
     }
-    
+
     $file;
 }
 
 sub _maccat {
     my($f1, $f2) = @_;
-    
+
     return "$f1/$f2" unless $Is_MacOS;
-    
+
     $f1 .= ":$f2";
     $f1 =~ s/([^:]:):/$1/g;
     return $f1;
@@ -513,11 +592,11 @@ sub _unmacify {
     my($file) = @_;
 
     return $file unless $Is_MacOS;
-    
+
     $file =~ s|^:||;
     $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
     $file =~ y|:|/|;
-    
+
     $file;
 }
 
@@ -539,17 +618,19 @@ sub maniadd {
     _fix_manifest($MANIFEST);
 
     my $manifest = maniread();
-    my $is_open;
-    foreach my $file (_sort keys %$additions) {
-        next if exists $manifest->{$file};
+    my @needed = grep { !exists $manifest->{$_} } keys %$additions;
+    return 1 unless @needed;
 
-        $is_open++ or open(MANIFEST, ">>$MANIFEST") or 
-          die "Could not open $MANIFEST: $!";
+    open(MANIFEST, ">>$MANIFEST") or 
+      die "maniadd() could not open $MANIFEST: $!";
 
+    foreach my $file (_sort @needed) {
         my $comment = $additions->{$file} || '';
-        printf MANIFEST "%-40s%s\n", $file, $comment;
+        printf MANIFEST "%-40s %s\n", $file, $comment;
     }
-    close MANIFEST if $is_open;
+    close MANIFEST or die "Error closing $MANIFEST: $!";
+
+    return 1;
 }
 
 
@@ -570,7 +651,7 @@ sub _fix_manifest {
         close MANIFEST;
     }
 }
-        
+
 
 # UNIMPLEMENTED
 sub _normalize {
@@ -582,9 +663,17 @@ sub _normalize {
 
 =head2 MANIFEST
 
+A list of files in the distribution, one file per line.  The MANIFEST
+always uses Unix filepath conventions even if you're not on Unix.  This
+means F<foo/bar> style not F<foo\bar>.
+
 Anything between white space and an end of line within a C<MANIFEST>
-file is considered to be a comment.  Filenames and comments are
-separated by one or more TAB characters in the output. 
+file is considered to be a comment.  Any line beginning with # is also
+a comment.
+
+    # this a comment
+    some/file
+    some/other/file            comment about some/file
 
 
 =head2 MANIFEST.SKIP
@@ -593,7 +682,9 @@ The file MANIFEST.SKIP may contain regular expressions of files that
 should be ignored by mkmanifest() and filecheck(). The regular
 expressions should appear one on each line. Blank lines and lines
 which start with C<#> are skipped.  Use C<\#> if you need a regular
-expression to start with a sharp character. A typical example:
+expression to start with a C<#>.
+
+For example:
 
     # Version control files and dirs.
     \bRCS\b
@@ -617,6 +708,26 @@ If no MANIFEST.SKIP file is found, a default set of skips will be
 used, similar to the example above.  If you want nothing skipped,
 simply make an empty MANIFEST.SKIP file.
 
+In one's own MANIFEST.SKIP file, certain directives
+can be used to include the contents of other MANIFEST.SKIP
+files. At present two such directives are recognized.
+
+=over 4
+
+=item #!include_default
+
+This inserts the contents of the default MANIFEST.SKIP file
+
+=item #!include /Path/to/another/manifest.skip
+
+This inserts the contents of the specified external file
+
+=back
+
+The included contents will be inserted into the MANIFEST.SKIP
+file in between I<#!start included /path/to/manifest.skip>
+and I<#!end included /path/to/manifest.skip> markers.
+The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
 
 =head2 EXPORT_OK
 
@@ -684,7 +795,11 @@ L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
 
 =head1 AUTHOR
 
-Andreas Koenig <F<andreas.koenig@anima.de>>
+Andreas Koenig C<andreas.koenig@anima.de>
+
+Maintained by Michael G Schwern C<schwern@pobox.com> within the
+ExtUtils-MakeMaker package and, as a separate CPAN package, by
+Randy Kobes C<r.kobes@uwinnipeg.ca>.
 
 =cut