1 package ExtUtils::Manifest;
12 use vars qw($VERSION @ISA @EXPORT_OK
13 $Is_MacOS $Is_VMS $Is_VMS_mode $Is_VMS_lc $Is_VMS_nodot
14 $Debug $Verbose $Quiet $MANIFEST $DEFAULT_MSKIP);
18 @EXPORT_OK = qw(mkmanifest
19 manicheck filecheck fullcheck skipcheck
20 manifind maniread manicopy maniadd
24 $Is_MacOS = $^O eq 'MacOS';
25 $Is_VMS = $^O eq 'VMS';
28 $Is_VMS_nodot = 0; # No dots in dir names or double dots in files
31 require VMS::Filespec if $Is_VMS;
39 if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
40 $vms_unix_rpt = VMS::Feature::current("filename_unix_report");
41 $vms_efs = VMS::Feature::current("efs_charset");
42 $vms_case = VMS::Feature::current("efs_case_preserve");
44 my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
45 my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || '';
46 my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || '';
47 $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i;
48 $vms_efs = $efs_charset =~ /^[ET1]/i;
49 $vms_case = $efs_case =~ /^[ET1]/i;
51 $Is_VMS_lc = 0 if ($vms_case);
52 $Is_VMS_mode = 0 if ($vms_unix_rpt);
53 $Is_VMS_nodot = 0 if ($vms_efs);
56 $Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
57 $Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
58 $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
60 $MANIFEST = 'MANIFEST';
62 $DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
67 ExtUtils::Manifest - utilities to write and check a MANIFEST file
71 use ExtUtils::Manifest qw(...funcs to import...);
75 my @missing_files = manicheck;
76 my @skipped = skipcheck;
77 my @extra_files = filecheck;
78 my($missing, $extra) = fullcheck;
80 my $found = manifind();
82 my $manifest = maniread();
84 manicopy($read,$target);
86 maniadd({$file => $comment, ...});
93 ExtUtils::Manifest exports no functions by default. The following are
102 Writes all files in and below the current directory to your F<MANIFEST>.
103 It works similar to the result of the Unix command
107 All files that match any regular expression in a file F<MANIFEST.SKIP>
108 (if it exists) are ignored.
110 Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.
115 return sort { lc $a cmp lc $b } @_;
120 my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
121 $read = {} if $manimiss;
123 my $bakbase = $MANIFEST;
124 $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
125 rename $MANIFEST, "$bakbase.bak" unless $manimiss;
126 open M, "> $MANIFEST" or die "Could not open $MANIFEST: $!";
127 my $skip = maniskip();
128 my $found = manifind();
129 my($key,$val,$file,%all);
130 %all = (%$found, %$read);
131 $all{$MANIFEST} = ($Is_VMS_mode ? "$MANIFEST\t\t" : '') .
133 if $manimiss; # add new MANIFEST to known file list
134 foreach $file (_sort keys %all) {
135 if ($skip->($file)) {
136 # Policy: only remove files if they're listed in MANIFEST.SKIP.
137 # Don't remove files just because they don't exist.
138 warn "Removed from $MANIFEST: $file\n" if $Verbose and exists $read->{$file};
142 warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
144 my $text = $all{$file};
145 $file = _unmacify($file);
146 my $tabs = (5 - (length($file)+1)/8);
147 $tabs = 1 if $tabs < 1;
148 $tabs = 0 unless $text;
150 $file =~ s/([\\'])/\\$1/g;
153 print M $file, "\t" x $tabs, $text, "\n";
158 # Geez, shouldn't this use File::Spec or File::Basename or something?
159 # Why so careful about dependencies?
160 sub clean_up_filename {
161 my $filename = shift;
162 $filename =~ s|^\./||;
163 $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
170 my $found = manifind();
172 returns a hash reference. The keys of the hash are the files found
173 below the current directory.
182 my $name = clean_up_filename($File::Find::name);
183 warn "Debug: diskfile $name\n" if $Debug;
187 $name =~ s#(.*)\.$#\L$1#;
188 $name = uc($name) if $name =~ /^MANIFEST(\.SKIP)?$/i;
190 $found->{$name} = "";
193 # We have to use "$File::Find::dir/$_" in preprocess, because
194 # $File::Find::name is unavailable.
195 # Also, it's okay to use / here, because MANIFEST files use Unix-style
197 find({wanted => $wanted},
198 $Is_MacOS ? ":" : ".");
206 my @missing_files = manicheck();
208 checks if all the files within a C<MANIFEST> in the current directory
209 really do exist. If C<MANIFEST> and the tree below the current
210 directory are in sync it silently returns an empty list.
211 Otherwise it returns a list of files which are listed in the
212 C<MANIFEST> but missing from the directory, and by default also
213 outputs these names to STDERR.
218 return _check_files();
224 my @extra_files = filecheck();
226 finds files below the current directory that are not mentioned in the
227 C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
228 consulted. Any file matching a regular expression in such a file will
229 not be reported as missing in the C<MANIFEST> file. The list of any
230 extraneous files found is returned, and by default also reported to
236 return _check_manifest();
242 my($missing, $extra) = fullcheck();
244 does both a manicheck() and a filecheck(), returning then as two array
250 return [_check_files()], [_check_manifest()];
256 my @skipped = skipcheck();
258 lists all the files that are skipped due to your C<MANIFEST.SKIP>
265 my $found = manifind();
266 my $matches = maniskip();
269 foreach my $file (_sort keys %$found){
270 if (&$matches($file)){
271 warn "Skipping $file\n" unless $Quiet;
272 push @skipped, $file;
283 my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
284 my $read = maniread() || {};
285 my $found = manifind($p);
288 foreach my $file (_sort keys %$read){
289 warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
292 $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
293 $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
295 unless ( exists $found->{$file} ) {
296 warn "No such file: $file\n" unless $Quiet;
297 push @missfile, $file;
305 sub _check_manifest {
307 my $read = maniread() || {};
308 my $found = manifind($p);
309 my $skip = maniskip();
312 foreach my $file (_sort keys %$found){
313 next if $skip->($file);
314 warn "Debug: manicheck checking from disk $file\n" if $Debug;
315 unless ( exists $read->{$file} ) {
316 my $canon = $Is_MacOS ? "\t" . _unmacify($file) : '';
317 warn "Not in $MANIFEST: $file$canon\n" unless $Quiet;
318 push @missentry, $file;
328 my $manifest = maniread();
329 my $manifest = maniread($manifest_file);
331 reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
332 directory) and returns a HASH reference with files being the keys and
333 comments being the values of the HASH. Blank lines and lines which
334 start with C<#> in the C<MANIFEST> file are discarded.
340 $mfile ||= $MANIFEST;
343 unless (open M, "< $mfile"){
344 warn "Problem opening $mfile: $!";
354 # filename may contain spaces if enclosed in ''
355 # (in which case, \\ and \' are escapes)
356 if (($file, $comment) = /^'(\\[\\']|.+)+'\s*(.*)/) {
357 $file =~ s/\\([\\'])/$1/g;
360 ($file, $comment) = /^(\S+)\s*(.*)/;
365 $file = _macify($file);
366 $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
368 elsif ($Is_VMS_mode) {
369 require File::Basename;
370 my($base,$dir) = File::Basename::fileparse($file);
371 # Resolve illegal file specifications in the same way as tar
374 my(@pieces) = split(/\./,$base);
376 { $base = shift(@pieces) . '.' . join('_',@pieces); }
377 my $okfile = "$dir$base";
378 warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
382 unless $Is_VMS_lc &&($file =~ /^MANIFEST(\.SKIP)?$/);
385 $read->{$file} = $comment;
393 my $skipchk = maniskip();
394 my $skipchk = maniskip($manifest_skip_file);
396 if ($skipchk->($file)) { .. }
398 reads a named C<MANIFEST.SKIP> file (defaults to C<MANIFEST.SKIP> in
399 the current directory) and returns a CODE reference that tests whether
400 a given filename should be skipped.
404 # returns an anonymous sub that decides if an argument matches
407 my $mfile = shift || "$MANIFEST.SKIP";
408 _check_mskip_directives($mfile) if -f $mfile;
410 open M, "< $mfile" or open M, "< $DEFAULT_MSKIP" or return sub {0};
414 $_ =~ qr{^\s*(?:(?:'([^\\']*(?:\\.[^\\']*)*)')|([^#\s]\S*))?(?:(?:\s*)|(?:\s+(.*?)\s*))$};
419 $filename =~ s/\\(['\\])/$1/g;
421 next if (not defined($filename) or not $filename);
422 push @skip, _macify($filename);
425 return sub {0} unless (scalar @skip > 0);
427 my $opts = $Is_VMS_mode ? '(?i)' : '';
429 # Make sure each entry is isolated in its own parentheses, in case
430 # any of them contain alternations
431 my $regex = join '|', map "(?:$_)", @skip;
433 return sub { $_[0] =~ qr{$opts$regex} };
436 # checks for the special directives
438 # #!include /path/to/some/manifest.skip
439 # in a custom MANIFEST.SKIP for, for including
440 # the content of, respectively, the default MANIFEST.SKIP
441 # and an external manifest.skip file
442 sub _check_mskip_directives {
447 unless (open M, "< $mfile") {
448 warn "Problem opening $mfile: $!";
452 if (/^#!include_default\s*$/) {
453 if (my @default = _include_mskip_file()) {
454 push @lines, @default;
455 warn "Debug: Including default MANIFEST.SKIP\n" if $Debug;
460 if (/^#!include\s+(.*)\s*$/) {
461 my $external_file = $1;
462 if (my @external = _include_mskip_file($external_file)) {
463 push @lines, @external;
464 warn "Debug: Including external $external_file\n" if $Debug;
473 my $bakbase = $mfile;
474 $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
475 rename $mfile, "$bakbase.bak";
476 warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
477 unless (open M, "> $mfile") {
478 warn "Problem opening $mfile: $!";
481 print M $_ for (@lines);
486 # returns an array containing the lines of an external
487 # manifest.skip file, if given, or $DEFAULT_MSKIP
488 sub _include_mskip_file {
489 my $mskip = shift || $DEFAULT_MSKIP;
491 warn qq{Included file "$mskip" not found - skipping};
495 unless (open M, "< $mskip") {
496 warn "Problem opening $mskip: $!";
500 push @lines, "\n#!start included $mskip\n";
501 push @lines, $_ while <M>;
503 push @lines, "#!end included $mskip\n\n";
509 manicopy(\%src, $dest_dir);
510 manicopy(\%src, $dest_dir, $how);
512 Copies the files that are the keys in %src to the $dest_dir. %src is
513 typically returned by the maniread() function.
515 manicopy( maniread(), $dest_dir );
517 This function is useful for producing a directory tree identical to the
518 intended distribution tree.
520 $how can be used to specify a different methods of "copying". Valid
521 values are C<cp>, which actually copies the files, C<ln> which creates
522 hard links, and C<best> which mostly links the files but copies any
523 symbolic link to make a tree without any symbolic link. C<cp> is the
529 my($read,$target,$how)=@_;
530 croak "manicopy() called without target argument" unless defined $target;
533 require File::Basename;
535 $target = VMS::Filespec::unixify($target) if $Is_VMS_mode;
536 File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
537 foreach my $file (keys %$read){
540 my $dir = _maccat($target, $file);
542 File::Path::mkpath($dir,1,0755);
544 cp_if_diff($file, _maccat($target, $file), $how);
546 $file = VMS::Filespec::unixify($file) if $Is_VMS_mode;
547 if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
548 my $dir = File::Basename::dirname($file);
549 $dir = VMS::Filespec::unixify($dir) if $Is_VMS_mode;
550 File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
552 cp_if_diff($file, "$target/$file", $how);
558 my($from, $to, $how)=@_;
560 carp "$from not found";
565 open(F,"< $from\0") or die "Can't read $from: $!\n";
566 if (open(T,"< $to\0")) {
568 while (<F>) { $diff++,last if $_ ne <T>; }
569 $diff++ unless eof(T);
576 unlink($to) or confess "unlink $to: $!";
579 best($from,$to), last STRICT_SWITCH if $how eq 'best';
580 cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
581 ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
582 croak("ExtUtils::Manifest::cp_if_diff " .
583 "called with illegal how argument [$how]. " .
584 "Legal values are 'best', 'cp', and 'ln'.");
590 my ($srcFile, $dstFile) = @_;
591 my ($access,$mod) = (stat $srcFile)[8,9];
593 copy($srcFile,$dstFile);
594 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
595 _manicopy_chmod($srcFile, $dstFile);
600 my ($srcFile, $dstFile) = @_;
601 # Fix-me - VMS can support links.
602 return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
603 link($srcFile, $dstFile);
605 unless( _manicopy_chmod($srcFile, $dstFile) ) {
612 # 1) Strip off all group and world permissions.
613 # 2) Let everyone read it.
614 # 3) If the owner can execute it, everyone can.
615 sub _manicopy_chmod {
616 my($srcFile, $dstFile) = @_;
618 my $perm = 0444 | (stat $srcFile)[2] & 0700;
619 chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
622 # Files that are often modified in the distdir. Don't hard link them.
623 my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
625 my ($srcFile, $dstFile) = @_;
627 my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
628 if ($is_exception or !$Config{d_link} or -l $srcFile) {
629 cp($srcFile, $dstFile);
631 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
638 return $file unless $Is_MacOS;
652 return "$f1/$f2" unless $Is_MacOS;
655 $f1 =~ s/([^:]:):/$1/g;
662 return $file unless $Is_MacOS;
665 $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
674 maniadd({ $file => $comment, ...});
676 Adds an entry to an existing F<MANIFEST> unless its already there.
678 $file will be normalized (ie. Unixified). B<UNIMPLEMENTED>
683 my($additions) = shift;
685 _normalize($additions);
686 _fix_manifest($MANIFEST);
688 my $manifest = maniread();
689 my @needed = grep { !exists $manifest->{$_} } keys %$additions;
690 return 1 unless @needed;
692 open(MANIFEST, ">>$MANIFEST") or
693 die "maniadd() could not open $MANIFEST: $!";
695 foreach my $file (_sort @needed) {
696 my $comment = $additions->{$file} || '';
698 $file =~ s/([\\'])/\\$1/g;
701 printf MANIFEST "%-40s %s\n", $file, $comment;
703 close MANIFEST or die "Error closing $MANIFEST: $!";
709 # Make sure this MANIFEST is consistently written with native
710 # newlines and has a terminal newline.
712 my $manifest_file = shift;
714 open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
716 my @manifest = split /(\015\012|\012|\015)/, <MANIFEST>, -1;
718 my $must_rewrite = "";
719 if ($manifest[-1] eq ""){
720 # sane case: last line had a terminal newline
722 for (my $i=1; $i<=$#manifest; $i+=2) {
723 unless ($manifest[$i] eq "\n") {
724 $must_rewrite = "not a newline at pos $i";
729 $must_rewrite = "last line without newline";
732 if ( $must_rewrite ) {
733 1 while unlink $MANIFEST; # avoid multiple versions on VMS
734 open MANIFEST, ">", $MANIFEST or die "(must_rewrite=$must_rewrite) Could not open >$MANIFEST: $!";
735 for (my $i=0; $i<=$#manifest; $i+=2) {
736 print MANIFEST "$manifest[$i]\n";
738 close MANIFEST or die "could not write $MANIFEST: $!";
753 A list of files in the distribution, one file per line. The MANIFEST
754 always uses Unix filepath conventions even if you're not on Unix. This
755 means F<foo/bar> style not F<foo\bar>.
757 Anything between white space and an end of line within a C<MANIFEST>
758 file is considered to be a comment. Any line beginning with # is also
759 a comment. Beginning with ExtUtils::Manifest 1.52, a filename may
760 contain whitespace characters if it is enclosed in single quotes; single
761 quotes or backslashes in that filename must be backslash-escaped.
765 some/other/file comment about some/file
766 'some/third file' comment
771 The file MANIFEST.SKIP may contain regular expressions of files that
772 should be ignored by mkmanifest() and filecheck(). The regular
773 expressions should appear one on each line. Blank lines and lines
774 which start with C<#> are skipped. Use C<\#> if you need a regular
775 expression to start with a C<#>.
779 # Version control files and dirs.
785 # Makemaker generated files and dirs.
791 # Temp, old and emacs backup files.
797 If no MANIFEST.SKIP file is found, a default set of skips will be
798 used, similar to the example above. If you want nothing skipped,
799 simply make an empty MANIFEST.SKIP file.
801 In one's own MANIFEST.SKIP file, certain directives
802 can be used to include the contents of other MANIFEST.SKIP
803 files. At present two such directives are recognized.
807 =item #!include_default
809 This inserts the contents of the default MANIFEST.SKIP file
811 =item #!include /Path/to/another/manifest.skip
813 This inserts the contents of the specified external file
817 The included contents will be inserted into the MANIFEST.SKIP
818 file in between I<#!start included /path/to/manifest.skip>
819 and I<#!end included /path/to/manifest.skip> markers.
820 The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
824 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
825 C<&maniread>, and C<&manicopy> are exportable.
827 =head2 GLOBAL VARIABLES
829 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
830 results in both a different C<MANIFEST> and a different
831 C<MANIFEST.SKIP> file. This is useful if you want to maintain
832 different distributions for different audiences (say a user version
833 and a developer version including RCS).
835 C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
836 all functions act silently.
838 C<$ExtUtils::Manifest::Debug> defaults to 0. If set to a true value,
839 or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
844 All diagnostic output is sent to C<STDERR>.
848 =item C<Not in MANIFEST:> I<file>
850 is reported if a file is found which is not in C<MANIFEST>.
852 =item C<Skipping> I<file>
854 is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
856 =item C<No such file:> I<file>
858 is reported if a file mentioned in a C<MANIFEST> file does not
861 =item C<MANIFEST:> I<$!>
863 is reported if C<MANIFEST> could not be opened.
865 =item C<Added to MANIFEST:> I<file>
867 is reported by mkmanifest() if $Verbose is set and a file is added
868 to MANIFEST. $Verbose is set to 1 by default.
876 =item B<PERL_MM_MANIFEST_DEBUG>
884 L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
888 Andreas Koenig C<andreas.koenig@anima.de>
890 Maintained by Michael G Schwern C<schwern@pobox.com> within the
891 ExtUtils-MakeMaker package and, as a separate CPAN package, by
892 Randy Kobes C<r.kobes@uwinnipeg.ca>.