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";
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};
418 push @skip, _macify($_);
421 return sub {0} unless (scalar @skip > 0);
423 my $opts = $Is_VMS_mode ? '(?i)' : '';
425 # Make sure each entry is isolated in its own parentheses, in case
426 # any of them contain alternations
427 my $regex = join '|', map "(?:$_)", @skip;
429 return sub { $_[0] =~ qr{$opts$regex} };
432 # checks for the special directives
434 # #!include /path/to/some/manifest.skip
435 # in a custom MANIFEST.SKIP for, for including
436 # the content of, respectively, the default MANIFEST.SKIP
437 # and an external manifest.skip file
438 sub _check_mskip_directives {
443 unless (open M, "< $mfile") {
444 warn "Problem opening $mfile: $!";
448 if (/^#!include_default\s*$/) {
449 if (my @default = _include_mskip_file()) {
450 push @lines, @default;
451 warn "Debug: Including default MANIFEST.SKIP\n" if $Debug;
456 if (/^#!include\s+(.*)\s*$/) {
457 my $external_file = $1;
458 if (my @external = _include_mskip_file($external_file)) {
459 push @lines, @external;
460 warn "Debug: Including external $external_file\n" if $Debug;
469 my $bakbase = $mfile;
470 $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
471 rename $mfile, "$bakbase.bak";
472 warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
473 unless (open M, "> $mfile") {
474 warn "Problem opening $mfile: $!";
477 print M $_ for (@lines);
482 # returns an array containing the lines of an external
483 # manifest.skip file, if given, or $DEFAULT_MSKIP
484 sub _include_mskip_file {
485 my $mskip = shift || $DEFAULT_MSKIP;
487 warn qq{Included file "$mskip" not found - skipping};
491 unless (open M, "< $mskip") {
492 warn "Problem opening $mskip: $!";
496 push @lines, "\n#!start included $mskip\n";
497 push @lines, $_ while <M>;
499 push @lines, "#!end included $mskip\n\n";
505 manicopy(\%src, $dest_dir);
506 manicopy(\%src, $dest_dir, $how);
508 Copies the files that are the keys in %src to the $dest_dir. %src is
509 typically returned by the maniread() function.
511 manicopy( maniread(), $dest_dir );
513 This function is useful for producing a directory tree identical to the
514 intended distribution tree.
516 $how can be used to specify a different methods of "copying". Valid
517 values are C<cp>, which actually copies the files, C<ln> which creates
518 hard links, and C<best> which mostly links the files but copies any
519 symbolic link to make a tree without any symbolic link. C<cp> is the
525 my($read,$target,$how)=@_;
526 croak "manicopy() called without target argument" unless defined $target;
529 require File::Basename;
531 $target = VMS::Filespec::unixify($target) if $Is_VMS_mode;
532 File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
533 foreach my $file (keys %$read){
536 my $dir = _maccat($target, $file);
538 File::Path::mkpath($dir,1,0755);
540 cp_if_diff($file, _maccat($target, $file), $how);
542 $file = VMS::Filespec::unixify($file) if $Is_VMS_mode;
543 if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
544 my $dir = File::Basename::dirname($file);
545 $dir = VMS::Filespec::unixify($dir) if $Is_VMS_mode;
546 File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
548 cp_if_diff($file, "$target/$file", $how);
554 my($from, $to, $how)=@_;
556 carp "$from not found";
561 open(F,"< $from\0") or die "Can't read $from: $!\n";
562 if (open(T,"< $to\0")) {
564 while (<F>) { $diff++,last if $_ ne <T>; }
565 $diff++ unless eof(T);
572 unlink($to) or confess "unlink $to: $!";
575 best($from,$to), last STRICT_SWITCH if $how eq 'best';
576 cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
577 ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
578 croak("ExtUtils::Manifest::cp_if_diff " .
579 "called with illegal how argument [$how]. " .
580 "Legal values are 'best', 'cp', and 'ln'.");
586 my ($srcFile, $dstFile) = @_;
587 my ($access,$mod) = (stat $srcFile)[8,9];
589 copy($srcFile,$dstFile);
590 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
591 _manicopy_chmod($srcFile, $dstFile);
596 my ($srcFile, $dstFile) = @_;
597 # Fix-me - VMS can support links.
598 return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
599 link($srcFile, $dstFile);
601 unless( _manicopy_chmod($srcFile, $dstFile) ) {
608 # 1) Strip off all group and world permissions.
609 # 2) Let everyone read it.
610 # 3) If the owner can execute it, everyone can.
611 sub _manicopy_chmod {
612 my($srcFile, $dstFile) = @_;
614 my $perm = 0444 | (stat $srcFile)[2] & 0700;
615 chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
618 # Files that are often modified in the distdir. Don't hard link them.
619 my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
621 my ($srcFile, $dstFile) = @_;
623 my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
624 if ($is_exception or !$Config{d_link} or -l $srcFile) {
625 cp($srcFile, $dstFile);
627 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
634 return $file unless $Is_MacOS;
648 return "$f1/$f2" unless $Is_MacOS;
651 $f1 =~ s/([^:]:):/$1/g;
658 return $file unless $Is_MacOS;
661 $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
670 maniadd({ $file => $comment, ...});
672 Adds an entry to an existing F<MANIFEST> unless its already there.
674 $file will be normalized (ie. Unixified). B<UNIMPLEMENTED>
679 my($additions) = shift;
681 _normalize($additions);
682 _fix_manifest($MANIFEST);
684 my $manifest = maniread();
685 my @needed = grep { !exists $manifest->{$_} } keys %$additions;
686 return 1 unless @needed;
688 open(MANIFEST, ">>$MANIFEST") or
689 die "maniadd() could not open $MANIFEST: $!";
691 foreach my $file (_sort @needed) {
692 my $comment = $additions->{$file} || '';
694 $file =~ s/([\\'])/\\$1/g;
697 printf MANIFEST "%-40s %s\n", $file, $comment;
699 close MANIFEST or die "Error closing $MANIFEST: $!";
705 # Sometimes MANIFESTs are missing a trailing newline. Fix this.
707 my $manifest_file = shift;
709 open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
711 # Yes, we should be using seek(), but I'd like to avoid loading POSIX
713 my @manifest = <MANIFEST>;
716 unless( $manifest[-1] =~ /\n\z/ ) {
717 open MANIFEST, ">>$MANIFEST" or die "Could not open $MANIFEST: $!";
734 A list of files in the distribution, one file per line. The MANIFEST
735 always uses Unix filepath conventions even if you're not on Unix. This
736 means F<foo/bar> style not F<foo\bar>.
738 Anything between white space and an end of line within a C<MANIFEST>
739 file is considered to be a comment. Any line beginning with # is also
740 a comment. Beginning with ExtUtils::Manifest 1.52, a filename may
741 contain whitespace characters if it is enclosed in single quotes; single
742 quotes or backslashes in that filename must be backslash-escaped.
746 some/other/file comment about some/file
747 'some/third file' comment
752 The file MANIFEST.SKIP may contain regular expressions of files that
753 should be ignored by mkmanifest() and filecheck(). The regular
754 expressions should appear one on each line. Blank lines and lines
755 which start with C<#> are skipped. Use C<\#> if you need a regular
756 expression to start with a C<#>.
760 # Version control files and dirs.
766 # Makemaker generated files and dirs.
772 # Temp, old and emacs backup files.
778 If no MANIFEST.SKIP file is found, a default set of skips will be
779 used, similar to the example above. If you want nothing skipped,
780 simply make an empty MANIFEST.SKIP file.
782 In one's own MANIFEST.SKIP file, certain directives
783 can be used to include the contents of other MANIFEST.SKIP
784 files. At present two such directives are recognized.
788 =item #!include_default
790 This inserts the contents of the default MANIFEST.SKIP file
792 =item #!include /Path/to/another/manifest.skip
794 This inserts the contents of the specified external file
798 The included contents will be inserted into the MANIFEST.SKIP
799 file in between I<#!start included /path/to/manifest.skip>
800 and I<#!end included /path/to/manifest.skip> markers.
801 The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
805 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
806 C<&maniread>, and C<&manicopy> are exportable.
808 =head2 GLOBAL VARIABLES
810 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
811 results in both a different C<MANIFEST> and a different
812 C<MANIFEST.SKIP> file. This is useful if you want to maintain
813 different distributions for different audiences (say a user version
814 and a developer version including RCS).
816 C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
817 all functions act silently.
819 C<$ExtUtils::Manifest::Debug> defaults to 0. If set to a true value,
820 or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
825 All diagnostic output is sent to C<STDERR>.
829 =item C<Not in MANIFEST:> I<file>
831 is reported if a file is found which is not in C<MANIFEST>.
833 =item C<Skipping> I<file>
835 is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
837 =item C<No such file:> I<file>
839 is reported if a file mentioned in a C<MANIFEST> file does not
842 =item C<MANIFEST:> I<$!>
844 is reported if C<MANIFEST> could not be opened.
846 =item C<Added to MANIFEST:> I<file>
848 is reported by mkmanifest() if $Verbose is set and a file is added
849 to MANIFEST. $Verbose is set to 1 by default.
857 =item B<PERL_MM_MANIFEST_DEBUG>
865 L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
869 Andreas Koenig C<andreas.koenig@anima.de>
871 Maintained by Michael G Schwern C<schwern@pobox.com> within the
872 ExtUtils-MakeMaker package and, as a separate CPAN package, by
873 Randy Kobes C<r.kobes@uwinnipeg.ca>.