1 package ExtUtils::Manifest;
12 use vars qw($VERSION @ISA @EXPORT_OK
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';
26 require VMS::Filespec if $Is_VMS;
28 $Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
29 $Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
30 $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
32 $MANIFEST = 'MANIFEST';
34 $DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
39 ExtUtils::Manifest - utilities to write and check a MANIFEST file
43 use ExtUtils::Manifest qw(...funcs to import...);
47 my @missing_files = manicheck;
48 my @skipped = skipcheck;
49 my @extra_files = filecheck;
50 my($missing, $extra) = fullcheck;
52 my $found = manifind();
54 my $manifest = maniread();
56 manicopy($read,$target);
58 maniadd({$file => $comment, ...});
65 ExtUtils::Manifest exports no functions by default. The following are
74 Writes all files in and below the current directory to your F<MANIFEST>.
75 It works similar to the result of the Unix command
79 All files that match any regular expression in a file F<MANIFEST.SKIP>
80 (if it exists) are ignored.
82 Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.
87 return sort { lc $a cmp lc $b } @_;
92 my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
93 $read = {} if $manimiss;
95 my $bakbase = $MANIFEST;
96 $bakbase =~ s/\./_/g if $Is_VMS; # avoid double dots
97 rename $MANIFEST, "$bakbase.bak" unless $manimiss;
98 open M, "> $MANIFEST" or die "Could not open $MANIFEST: $!";
99 my $skip = maniskip();
100 my $found = manifind();
101 my($key,$val,$file,%all);
102 %all = (%$found, %$read);
103 $all{$MANIFEST} = ($Is_VMS ? "$MANIFEST\t\t" : '') . 'This list of files'
104 if $manimiss; # add new MANIFEST to known file list
105 foreach $file (_sort keys %all) {
106 if ($skip->($file)) {
107 # Policy: only remove files if they're listed in MANIFEST.SKIP.
108 # Don't remove files just because they don't exist.
109 warn "Removed from $MANIFEST: $file\n" if $Verbose and exists $read->{$file};
113 warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
115 my $text = $all{$file};
116 $file = _unmacify($file);
117 my $tabs = (5 - (length($file)+1)/8);
118 $tabs = 1 if $tabs < 1;
119 $tabs = 0 unless $text;
121 $file =~ s/([\\'])/\\$1/g;
124 print M $file, "\t" x $tabs, $text, "\n";
129 # Geez, shouldn't this use File::Spec or File::Basename or something?
130 # Why so careful about dependencies?
131 sub clean_up_filename {
132 my $filename = shift;
133 $filename =~ s|^\./||;
134 $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
141 my $found = manifind();
143 returns a hash reference. The keys of the hash are the files found
144 below the current directory.
153 my $name = clean_up_filename($File::Find::name);
154 warn "Debug: diskfile $name\n" if $Debug;
158 $name =~ s#(.*)\.$#\L$1#;
159 $name = uc($name) if $name =~ /^MANIFEST(\.SKIP)?$/i;
161 $found->{$name} = "";
164 # We have to use "$File::Find::dir/$_" in preprocess, because
165 # $File::Find::name is unavailable.
166 # Also, it's okay to use / here, because MANIFEST files use Unix-style
168 find({wanted => $wanted},
169 $Is_MacOS ? ":" : ".");
177 my @missing_files = manicheck();
179 checks if all the files within a C<MANIFEST> in the current directory
180 really do exist. If C<MANIFEST> and the tree below the current
181 directory are in sync it silently returns an empty list.
182 Otherwise it returns a list of files which are listed in the
183 C<MANIFEST> but missing from the directory, and by default also
184 outputs these names to STDERR.
189 return _check_files();
195 my @extra_files = filecheck();
197 finds files below the current directory that are not mentioned in the
198 C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
199 consulted. Any file matching a regular expression in such a file will
200 not be reported as missing in the C<MANIFEST> file. The list of any
201 extraneous files found is returned, and by default also reported to
207 return _check_manifest();
213 my($missing, $extra) = fullcheck();
215 does both a manicheck() and a filecheck(), returning then as two array
221 return [_check_files()], [_check_manifest()];
227 my @skipped = skipcheck();
229 lists all the files that are skipped due to your C<MANIFEST.SKIP>
236 my $found = manifind();
237 my $matches = maniskip();
240 foreach my $file (_sort keys %$found){
241 if (&$matches($file)){
242 warn "Skipping $file\n";
243 push @skipped, $file;
254 my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
255 my $read = maniread() || {};
256 my $found = manifind($p);
259 foreach my $file (_sort keys %$read){
260 warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
263 $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
264 $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
266 unless ( exists $found->{$file} ) {
267 warn "No such file: $file\n" unless $Quiet;
268 push @missfile, $file;
276 sub _check_manifest {
278 my $read = maniread() || {};
279 my $found = manifind($p);
280 my $skip = maniskip();
283 foreach my $file (_sort keys %$found){
284 next if $skip->($file);
285 warn "Debug: manicheck checking from disk $file\n" if $Debug;
286 unless ( exists $read->{$file} ) {
287 my $canon = $Is_MacOS ? "\t" . _unmacify($file) : '';
288 warn "Not in $MANIFEST: $file$canon\n" unless $Quiet;
289 push @missentry, $file;
299 my $manifest = maniread();
300 my $manifest = maniread($manifest_file);
302 reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
303 directory) and returns a HASH reference with files being the keys and
304 comments being the values of the HASH. Blank lines and lines which
305 start with C<#> in the C<MANIFEST> file are discarded.
311 $mfile ||= $MANIFEST;
314 unless (open M, "< $mfile"){
315 warn "Problem opening $mfile: $!";
325 # filename may contain spaces if enclosed in ''
326 # (in which case, \\ and \' are escapes)
327 if (($file, $comment) = /^'(\\[\\']|.+)+'\s*(.*)/) {
328 $file =~ s/\\([\\'])/$1/g;
331 ($file, $comment) = /^(\S+)\s*(.*)/;
336 $file = _macify($file);
337 $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
340 require File::Basename;
341 my($base,$dir) = File::Basename::fileparse($file);
342 # Resolve illegal file specifications in the same way as tar
344 my(@pieces) = split(/\./,$base);
345 if (@pieces > 2) { $base = shift(@pieces) . '.' . join('_',@pieces); }
346 my $okfile = "$dir$base";
347 warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
349 $file = lc($file) unless $file =~ /^MANIFEST(\.SKIP)?$/;
352 $read->{$file} = $comment;
360 my $skipchk = maniskip();
361 my $skipchk = maniskip($manifest_skip_file);
363 if ($skipchk->($file)) { .. }
365 reads a named C<MANIFEST.SKIP> file (defaults to C<MANIFEST.SKIP> in
366 the current directory) and returns a CODE reference that tests whether
367 a given filename should be skipped.
371 # returns an anonymous sub that decides if an argument matches
374 my $mfile = shift || "$MANIFEST.SKIP";
375 _check_mskip_directives($mfile) if -f $mfile;
377 open M, "< $mfile" or open M, "< $DEFAULT_MSKIP" or return sub {0};
385 push @skip, _macify($_);
388 return sub {0} unless (scalar @skip > 0);
390 my $opts = $Is_VMS ? '(?i)' : '';
392 # Make sure each entry is isolated in its own parentheses, in case
393 # any of them contain alternations
394 my $regex = join '|', map "(?:$_)", @skip;
396 return sub { $_[0] =~ qr{$opts$regex} };
399 # checks for the special directives
401 # #!include /path/to/some/manifest.skip
402 # in a custom MANIFEST.SKIP for, for including
403 # the content of, respectively, the default MANIFEST.SKIP
404 # and an external manifest.skip file
405 sub _check_mskip_directives {
410 unless (open M, "< $mfile") {
411 warn "Problem opening $mfile: $!";
415 if (/^#!include_default\s*$/) {
416 if (my @default = _include_mskip_file()) {
417 push @lines, @default;
418 warn "Debug: Including default MANIFEST.SKIP\n" if $Debug;
423 if (/^#!include\s+(.*)\s*$/) {
424 my $external_file = $1;
425 if (my @external = _include_mskip_file($external_file)) {
426 push @lines, @external;
427 warn "Debug: Including external $external_file\n" if $Debug;
436 my $bakbase = $mfile;
437 $bakbase =~ s/\./_/g if $Is_VMS; # avoid double dots
438 rename $mfile, "$bakbase.bak";
439 warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
440 unless (open M, "> $mfile") {
441 warn "Problem opening $mfile: $!";
444 print M $_ for (@lines);
449 # returns an array containing the lines of an external
450 # manifest.skip file, if given, or $DEFAULT_MSKIP
451 sub _include_mskip_file {
452 my $mskip = shift || $DEFAULT_MSKIP;
454 warn qq{Included file "$mskip" not found - skipping};
458 unless (open M, "< $mskip") {
459 warn "Problem opening $mskip: $!";
463 push @lines, "\n#!start included $mskip\n";
464 push @lines, $_ while <M>;
466 push @lines, "#!end included $mskip\n\n";
472 manicopy(\%src, $dest_dir);
473 manicopy(\%src, $dest_dir, $how);
475 Copies the files that are the keys in %src to the $dest_dir. %src is
476 typically returned by the maniread() function.
478 manicopy( maniread(), $dest_dir );
480 This function is useful for producing a directory tree identical to the
481 intended distribution tree.
483 $how can be used to specify a different methods of "copying". Valid
484 values are C<cp>, which actually copies the files, C<ln> which creates
485 hard links, and C<best> which mostly links the files but copies any
486 symbolic link to make a tree without any symbolic link. C<cp> is the
492 my($read,$target,$how)=@_;
493 croak "manicopy() called without target argument" unless defined $target;
496 require File::Basename;
498 $target = VMS::Filespec::unixify($target) if $Is_VMS;
499 File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
500 foreach my $file (keys %$read){
503 my $dir = _maccat($target, $file);
505 File::Path::mkpath($dir,1,0755);
507 cp_if_diff($file, _maccat($target, $file), $how);
509 $file = VMS::Filespec::unixify($file) if $Is_VMS;
510 if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
511 my $dir = File::Basename::dirname($file);
512 $dir = VMS::Filespec::unixify($dir) if $Is_VMS;
513 File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
515 cp_if_diff($file, "$target/$file", $how);
521 my($from, $to, $how)=@_;
523 carp "$from not found";
528 open(F,"< $from\0") or die "Can't read $from: $!\n";
529 if (open(T,"< $to\0")) {
531 while (<F>) { $diff++,last if $_ ne <T>; }
532 $diff++ unless eof(T);
539 unlink($to) or confess "unlink $to: $!";
542 best($from,$to), last STRICT_SWITCH if $how eq 'best';
543 cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
544 ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
545 croak("ExtUtils::Manifest::cp_if_diff " .
546 "called with illegal how argument [$how]. " .
547 "Legal values are 'best', 'cp', and 'ln'.");
553 my ($srcFile, $dstFile) = @_;
554 my ($access,$mod) = (stat $srcFile)[8,9];
556 copy($srcFile,$dstFile);
557 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
558 _manicopy_chmod($srcFile, $dstFile);
563 my ($srcFile, $dstFile) = @_;
564 return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
565 link($srcFile, $dstFile);
567 unless( _manicopy_chmod($srcFile, $dstFile) ) {
574 # 1) Strip off all group and world permissions.
575 # 2) Let everyone read it.
576 # 3) If the owner can execute it, everyone can.
577 sub _manicopy_chmod {
578 my($srcFile, $dstFile) = @_;
580 my $perm = 0444 | (stat $srcFile)[2] & 0700;
581 chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
584 # Files that are often modified in the distdir. Don't hard link them.
585 my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
587 my ($srcFile, $dstFile) = @_;
589 my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
590 if ($is_exception or !$Config{d_link} or -l $srcFile) {
591 cp($srcFile, $dstFile);
593 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
600 return $file unless $Is_MacOS;
614 return "$f1/$f2" unless $Is_MacOS;
617 $f1 =~ s/([^:]:):/$1/g;
624 return $file unless $Is_MacOS;
627 $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
636 maniadd({ $file => $comment, ...});
638 Adds an entry to an existing F<MANIFEST> unless its already there.
640 $file will be normalized (ie. Unixified). B<UNIMPLEMENTED>
645 my($additions) = shift;
647 _normalize($additions);
648 _fix_manifest($MANIFEST);
650 my $manifest = maniread();
651 my @needed = grep { !exists $manifest->{$_} } keys %$additions;
652 return 1 unless @needed;
654 open(MANIFEST, ">>$MANIFEST") or
655 die "maniadd() could not open $MANIFEST: $!";
657 foreach my $file (_sort @needed) {
658 my $comment = $additions->{$file} || '';
660 $file =~ s/([\\'])/\\$1/g;
663 printf MANIFEST "%-40s %s\n", $file, $comment;
665 close MANIFEST or die "Error closing $MANIFEST: $!";
671 # Sometimes MANIFESTs are missing a trailing newline. Fix this.
673 my $manifest_file = shift;
675 open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
677 # Yes, we should be using seek(), but I'd like to avoid loading POSIX
679 my @manifest = <MANIFEST>;
682 unless( $manifest[-1] =~ /\n\z/ ) {
683 open MANIFEST, ">>$MANIFEST" or die "Could not open $MANIFEST: $!";
700 A list of files in the distribution, one file per line. The MANIFEST
701 always uses Unix filepath conventions even if you're not on Unix. This
702 means F<foo/bar> style not F<foo\bar>.
704 Anything between white space and an end of line within a C<MANIFEST>
705 file is considered to be a comment. Any line beginning with # is also
706 a comment. Beginning with ExtUtils::Manifest 1.52, a filename may
707 contain whitespace characters if it is enclosed in single quotes; single
708 quotes or backslashes in that filename must be backslash-escaped.
712 some/other/file comment about some/file
713 'some/third file' comment
718 The file MANIFEST.SKIP may contain regular expressions of files that
719 should be ignored by mkmanifest() and filecheck(). The regular
720 expressions should appear one on each line. Blank lines and lines
721 which start with C<#> are skipped. Use C<\#> if you need a regular
722 expression to start with a C<#>.
726 # Version control files and dirs.
732 # Makemaker generated files and dirs.
738 # Temp, old and emacs backup files.
744 If no MANIFEST.SKIP file is found, a default set of skips will be
745 used, similar to the example above. If you want nothing skipped,
746 simply make an empty MANIFEST.SKIP file.
748 In one's own MANIFEST.SKIP file, certain directives
749 can be used to include the contents of other MANIFEST.SKIP
750 files. At present two such directives are recognized.
754 =item #!include_default
756 This inserts the contents of the default MANIFEST.SKIP file
758 =item #!include /Path/to/another/manifest.skip
760 This inserts the contents of the specified external file
764 The included contents will be inserted into the MANIFEST.SKIP
765 file in between I<#!start included /path/to/manifest.skip>
766 and I<#!end included /path/to/manifest.skip> markers.
767 The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
771 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
772 C<&maniread>, and C<&manicopy> are exportable.
774 =head2 GLOBAL VARIABLES
776 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
777 results in both a different C<MANIFEST> and a different
778 C<MANIFEST.SKIP> file. This is useful if you want to maintain
779 different distributions for different audiences (say a user version
780 and a developer version including RCS).
782 C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
783 all functions act silently.
785 C<$ExtUtils::Manifest::Debug> defaults to 0. If set to a true value,
786 or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
791 All diagnostic output is sent to C<STDERR>.
795 =item C<Not in MANIFEST:> I<file>
797 is reported if a file is found which is not in C<MANIFEST>.
799 =item C<Skipping> I<file>
801 is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
803 =item C<No such file:> I<file>
805 is reported if a file mentioned in a C<MANIFEST> file does not
808 =item C<MANIFEST:> I<$!>
810 is reported if C<MANIFEST> could not be opened.
812 =item C<Added to MANIFEST:> I<file>
814 is reported by mkmanifest() if $Verbose is set and a file is added
815 to MANIFEST. $Verbose is set to 1 by default.
823 =item B<PERL_MM_MANIFEST_DEBUG>
831 L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
835 Andreas Koenig C<andreas.koenig@anima.de>
837 Maintained by Michael G Schwern C<schwern@pobox.com> within the
838 ExtUtils-MakeMaker package and, as a separate CPAN package, by
839 Randy Kobes C<r.kobes@uwinnipeg.ca>.