xref: /openbsd-src/gnu/usr.bin/perl/cpan/ExtUtils-Manifest/lib/ExtUtils/Manifest.pm (revision 09467b48e8bc8b4905716062da846024139afbf2)
1package ExtUtils::Manifest; # git description: 1.71-18-g17b7919
2
3require Exporter;
4use Config;
5use File::Basename;
6use File::Copy 'copy';
7use File::Find;
8use File::Spec 0.8;
9use Carp;
10use strict;
11use warnings;
12
13our $VERSION = '1.72';
14our @ISA = ('Exporter');
15our @EXPORT_OK = qw(mkmanifest
16                manicheck  filecheck  fullcheck  skipcheck
17                manifind   maniread   manicopy   maniadd
18                maniskip
19               );
20
21our $Is_MacOS = $^O eq 'MacOS';
22our $Is_VMS   = $^O eq 'VMS';
23our $Is_VMS_mode = 0;
24our $Is_VMS_lc = 0;
25our $Is_VMS_nodot = 0;  # No dots in dir names or double dots in files
26
27if ($Is_VMS) {
28    require VMS::Filespec if $Is_VMS;
29    my $vms_unix_rpt;
30    my $vms_efs;
31    my $vms_case;
32
33    $Is_VMS_mode = 1;
34    $Is_VMS_lc = 1;
35    $Is_VMS_nodot = 1;
36    if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
37        $vms_unix_rpt = VMS::Feature::current("filename_unix_report");
38        $vms_efs = VMS::Feature::current("efs_charset");
39        $vms_case = VMS::Feature::current("efs_case_preserve");
40    } else {
41        my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
42        my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || '';
43        my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || '';
44        $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i;
45        $vms_efs = $efs_charset =~ /^[ET1]/i;
46        $vms_case = $efs_case =~ /^[ET1]/i;
47    }
48    $Is_VMS_lc = 0 if ($vms_case);
49    $Is_VMS_mode = 0 if ($vms_unix_rpt);
50    $Is_VMS_nodot = 0 if ($vms_efs);
51}
52
53our $Debug   = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
54our $Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
55                   $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
56our $Quiet = 0;
57our $MANIFEST = 'MANIFEST';
58
59our $DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
60
61
62=head1 NAME
63
64ExtUtils::Manifest - Utilities to write and check a MANIFEST file
65
66=head1 VERSION
67
68version 1.72
69
70=head1 SYNOPSIS
71
72    use ExtUtils::Manifest qw(...funcs to import...);
73
74    mkmanifest();
75
76    my @missing_files    = manicheck;
77    my @skipped          = skipcheck;
78    my @extra_files      = filecheck;
79    my($missing, $extra) = fullcheck;
80
81    my $found    = manifind();
82
83    my $manifest = maniread();
84
85    manicopy($read,$target);
86
87    maniadd({$file => $comment, ...});
88
89
90=head1 DESCRIPTION
91
92...
93
94=head1 FUNCTIONS
95
96ExtUtils::Manifest exports no functions by default.  The following are
97exported on request:
98
99=head2 mkmanifest
100
101    mkmanifest();
102
103Writes all files in and below the current directory to your F<MANIFEST>.
104It works similar to the result of the Unix command
105
106    find . > MANIFEST
107
108All files that match any regular expression in a file F<MANIFEST.SKIP>
109(if it exists) are ignored.
110
111Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.
112
113=cut
114
115sub _sort {
116    return sort { lc $a cmp lc $b } @_;
117}
118
119sub mkmanifest {
120    my $manimiss = 0;
121    my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
122    $read = {} if $manimiss;
123    local *M;
124    my $bakbase = $MANIFEST;
125    $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
126    rename $MANIFEST, "$bakbase.bak" unless $manimiss;
127    open M, "> $MANIFEST" or die "Could not open $MANIFEST: $!";
128    binmode M, ':raw';
129    my $skip = maniskip();
130    my $found = manifind();
131    my($key,$val,$file,%all);
132    %all = (%$found, %$read);
133    $all{$MANIFEST} = ($Is_VMS_mode ? "$MANIFEST\t\t" : '') .
134                     'This list of files'
135        if $manimiss; # add new MANIFEST to known file list
136    foreach $file (_sort keys %all) {
137	if ($skip->($file)) {
138	    # Policy: only remove files if they're listed in MANIFEST.SKIP.
139	    # Don't remove files just because they don't exist.
140	    warn "Removed from $MANIFEST: $file\n" if $Verbose and exists $read->{$file};
141	    next;
142	}
143	if ($Verbose){
144	    warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
145	}
146	my $text = $all{$file};
147	$file = _unmacify($file);
148	my $tabs = (5 - (length($file)+1)/8);
149	$tabs = 1 if $tabs < 1;
150	$tabs = 0 unless $text;
151        if ($file =~ /\s/) {
152            $file =~ s/([\\'])/\\$1/g;
153            $file = "'$file'";
154        }
155	print M $file, "\t" x $tabs, $text, "\n";
156    }
157    close M;
158}
159
160# Geez, shouldn't this use File::Spec or File::Basename or something?
161# Why so careful about dependencies?
162sub clean_up_filename {
163  my $filename = shift;
164  $filename =~ s|^\./||;
165  $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
166  if ( $Is_VMS ) {
167      $filename =~ s/\.$//;                           # trim trailing dot
168      $filename = VMS::Filespec::unixify($filename);  # unescape spaces, etc.
169      if( $Is_VMS_lc ) {
170          $filename = lc($filename);
171          $filename = uc($filename) if $filename =~ /^MANIFEST(\.SKIP)?$/i;
172      }
173  }
174  return $filename;
175}
176
177
178=head2 manifind
179
180    my $found = manifind();
181
182returns a hash reference. The keys of the hash are the files found
183below the current directory.
184
185=cut
186
187sub manifind {
188    my $p = shift || {};
189    my $found = {};
190
191    my $wanted = sub {
192	my $name = clean_up_filename($File::Find::name);
193	warn "Debug: diskfile $name\n" if $Debug;
194	return if -d $_;
195	$found->{$name} = "";
196    };
197
198    # We have to use "$File::Find::dir/$_" in preprocess, because
199    # $File::Find::name is unavailable.
200    # Also, it's okay to use / here, because MANIFEST files use Unix-style
201    # paths.
202    find({wanted => $wanted, follow_fast => 1},
203	 $Is_MacOS ? ":" : ".");
204
205    return $found;
206}
207
208
209=head2 manicheck
210
211    my @missing_files = manicheck();
212
213checks if all the files within a C<MANIFEST> in the current directory
214really do exist. If C<MANIFEST> and the tree below the current
215directory are in sync it silently returns an empty list.
216Otherwise it returns a list of files which are listed in the
217C<MANIFEST> but missing from the directory, and by default also
218outputs these names to STDERR.
219
220=cut
221
222sub manicheck {
223    return _check_files();
224}
225
226
227=head2 filecheck
228
229    my @extra_files = filecheck();
230
231finds files below the current directory that are not mentioned in the
232C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
233consulted. Any file matching a regular expression in such a file will
234not be reported as missing in the C<MANIFEST> file. The list of any
235extraneous files found is returned, and by default also reported to
236STDERR.
237
238=cut
239
240sub filecheck {
241    return _check_manifest();
242}
243
244
245=head2 fullcheck
246
247    my($missing, $extra) = fullcheck();
248
249does both a manicheck() and a filecheck(), returning then as two array
250refs.
251
252=cut
253
254sub fullcheck {
255    return [_check_files()], [_check_manifest()];
256}
257
258
259=head2 skipcheck
260
261    my @skipped = skipcheck();
262
263lists all the files that are skipped due to your C<MANIFEST.SKIP>
264file.
265
266=cut
267
268sub skipcheck {
269    my($p) = @_;
270    my $found = manifind();
271    my $matches = maniskip();
272
273    my @skipped = ();
274    foreach my $file (_sort keys %$found){
275        if (&$matches($file)){
276            warn "Skipping $file\n" unless $Quiet;
277            push @skipped, $file;
278            next;
279        }
280    }
281
282    return @skipped;
283}
284
285
286sub _check_files {
287    my $p = shift;
288    my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
289    my $read = maniread() || {};
290    my $found = manifind($p);
291
292    my(@missfile) = ();
293    foreach my $file (_sort keys %$read){
294        warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
295        if ($dosnames){
296            $file = lc $file;
297            $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
298            $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
299        }
300        unless ( exists $found->{$file} ) {
301            warn "No such file: $file\n" unless $Quiet;
302            push @missfile, $file;
303        }
304    }
305
306    return @missfile;
307}
308
309
310sub _check_manifest {
311    my($p) = @_;
312    my $read = maniread() || {};
313    my $found = manifind($p);
314    my $skip  = maniskip();
315
316    my @missentry = ();
317    foreach my $file (_sort keys %$found){
318        next if $skip->($file);
319        warn "Debug: manicheck checking from disk $file\n" if $Debug;
320        unless ( exists $read->{$file} ) {
321            my $canon = $Is_MacOS ? "\t" . _unmacify($file) : '';
322            warn "Not in $MANIFEST: $file$canon\n" unless $Quiet;
323            push @missentry, $file;
324        }
325    }
326
327    return @missentry;
328}
329
330
331=head2 maniread
332
333    my $manifest = maniread();
334    my $manifest = maniread($manifest_file);
335
336reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
337directory) and returns a HASH reference with files being the keys and
338comments being the values of the HASH.  Blank lines and lines which
339start with C<#> in the C<MANIFEST> file are discarded.
340
341=cut
342
343sub maniread {
344    my ($mfile) = @_;
345    $mfile ||= $MANIFEST;
346    my $read = {};
347    local *M;
348    unless (open M, "< $mfile"){
349        warn "Problem opening $mfile: $!";
350        return $read;
351    }
352    local $_;
353    while (<M>){
354        chomp;
355        next if /^\s*#/;
356
357        my($file, $comment);
358
359        # filename may contain spaces if enclosed in ''
360        # (in which case, \\ and \' are escapes)
361        if (($file, $comment) = /^'((?:\\[\\']|.+)+)'\s*(.*)/) {
362            $file =~ s/\\([\\'])/$1/g;
363        }
364        else {
365            ($file, $comment) = /^(\S+)\s*(.*)/;
366        }
367        next unless $file;
368
369        if ($Is_MacOS) {
370            $file = _macify($file);
371            $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
372        }
373        elsif ($Is_VMS_mode) {
374            require File::Basename;
375            my($base,$dir) = File::Basename::fileparse($file);
376            # Resolve illegal file specifications in the same way as tar
377            if ($Is_VMS_nodot) {
378                $dir =~ tr/./_/;
379                my(@pieces) = split(/\./,$base);
380                if (@pieces > 2)
381                    { $base = shift(@pieces) . '.' . join('_',@pieces); }
382                my $okfile = "$dir$base";
383                warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
384                $file = $okfile;
385            }
386            if( $Is_VMS_lc ) {
387                $file = lc($file);
388                $file = uc($file) if $file =~ /^MANIFEST(\.SKIP)?$/i;
389            }
390        }
391
392        $read->{$file} = $comment;
393    }
394    close M;
395    $read;
396}
397
398=head2 maniskip
399
400    my $skipchk = maniskip();
401    my $skipchk = maniskip($manifest_skip_file);
402
403    if ($skipchk->($file)) { .. }
404
405reads a named C<MANIFEST.SKIP> file (defaults to C<MANIFEST.SKIP> in
406the current directory) and returns a CODE reference that tests whether
407a given filename should be skipped.
408
409=cut
410
411# returns an anonymous sub that decides if an argument matches
412sub maniskip {
413    my @skip ;
414    my $mfile = shift || "$MANIFEST.SKIP";
415    _check_mskip_directives($mfile) if -f $mfile;
416    local(*M, $_);
417    open M, "< $mfile" or open M, "< $DEFAULT_MSKIP" or return sub {0};
418    while (<M>){
419      chomp;
420      s/\r//;
421      $_ =~ qr{^\s*(?:(?:'([^\\']*(?:\\.[^\\']*)*)')|([^#\s]\S*))?(?:(?:\s*)|(?:\s+(.*?)\s*))$};
422      #my $comment = $3;
423      my $filename = $2;
424      if ( defined($1) ) {
425        $filename = $1;
426        $filename =~ s/\\(['\\])/$1/g;
427      }
428      next if (not defined($filename) or not $filename);
429      push @skip, _macify($filename);
430    }
431    close M;
432    return sub {0} unless (scalar @skip > 0);
433
434    my $opts = $Is_VMS_mode ? '(?i)' : '';
435
436    # Make sure each entry is isolated in its own parentheses, in case
437    # any of them contain alternations
438    my $regex = join '|', map "(?:$_)", @skip;
439
440    return sub { $_[0] =~ qr{$opts$regex} };
441}
442
443# checks for the special directives
444#   #!include_default
445#   #!include /path/to/some/manifest.skip
446# in a custom MANIFEST.SKIP for, for including
447# the content of, respectively, the default MANIFEST.SKIP
448# and an external manifest.skip file
449sub _check_mskip_directives {
450    my $mfile = shift;
451    local (*M, $_);
452    my @lines = ();
453    my $flag = 0;
454    unless (open M, "< $mfile") {
455        warn "Problem opening $mfile: $!";
456        return;
457    }
458    while (<M>) {
459        if (/^#!include_default\s*$/) {
460	    if (my @default = _include_mskip_file()) {
461	        push @lines, @default;
462		warn "Debug: Including default MANIFEST.SKIP\n" if $Debug;
463		$flag++;
464	    }
465	    next;
466        }
467	if (/^#!include\s+(.*)\s*$/) {
468	    my $external_file = $1;
469	    if (my @external = _include_mskip_file($external_file)) {
470	        push @lines, @external;
471		warn "Debug: Including external $external_file\n" if $Debug;
472		$flag++;
473	    }
474            next;
475        }
476        push @lines, $_;
477    }
478    close M;
479    return unless $flag;
480    my $bakbase = $mfile;
481    $bakbase =~ s/\./_/g if $Is_VMS_nodot;  # avoid double dots
482    rename $mfile, "$bakbase.bak";
483    warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
484    unless (open M, "> $mfile") {
485        warn "Problem opening $mfile: $!";
486        return;
487    }
488    binmode M, ':raw';
489    print M $_ for (@lines);
490    close M;
491    return;
492}
493
494# returns an array containing the lines of an external
495# manifest.skip file, if given, or $DEFAULT_MSKIP
496sub _include_mskip_file {
497    my $mskip = shift || $DEFAULT_MSKIP;
498    unless (-f $mskip) {
499        warn qq{Included file "$mskip" not found - skipping};
500        return;
501    }
502    local (*M, $_);
503    unless (open M, "< $mskip") {
504        warn "Problem opening $mskip: $!";
505        return;
506    }
507    my @lines = ();
508    push @lines, "\n#!start included $mskip\n";
509    push @lines, $_ while <M>;
510    close M;
511    push @lines, "#!end included $mskip\n\n";
512    return @lines;
513}
514
515=head2 manicopy
516
517    manicopy(\%src, $dest_dir);
518    manicopy(\%src, $dest_dir, $how);
519
520Copies the files that are the keys in %src to the $dest_dir.  %src is
521typically returned by the maniread() function.
522
523    manicopy( maniread(), $dest_dir );
524
525This function is useful for producing a directory tree identical to the
526intended distribution tree.
527
528$how can be used to specify a different methods of "copying".  Valid
529values are C<cp>, which actually copies the files, C<ln> which creates
530hard links, and C<best> which mostly links the files but copies any
531symbolic link to make a tree without any symbolic link.  C<cp> is the
532default.
533
534=cut
535
536sub manicopy {
537    my($read,$target,$how)=@_;
538    croak "manicopy() called without target argument" unless defined $target;
539    $how ||= 'cp';
540    require File::Path;
541    require File::Basename;
542
543    $target = VMS::Filespec::unixify($target) if $Is_VMS_mode;
544    File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
545    foreach my $file (keys %$read){
546	if ($Is_MacOS) {
547	    if ($file =~ m!:!) {
548		my $dir = _maccat($target, $file);
549		$dir =~ s/[^:]+$//;
550		File::Path::mkpath($dir,1,0755);
551	    }
552	    cp_if_diff($file, _maccat($target, $file), $how);
553	} else {
554	    $file = VMS::Filespec::unixify($file) if $Is_VMS_mode;
555	    if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
556		my $dir = File::Basename::dirname($file);
557		$dir = VMS::Filespec::unixify($dir) if $Is_VMS_mode;
558		File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
559	    }
560	    cp_if_diff($file, "$target/$file", $how);
561	}
562    }
563}
564
565sub cp_if_diff {
566    my($from, $to, $how)=@_;
567    if (! -f $from) {
568        carp "$from not found";
569        return;
570    }
571    my($diff) = 0;
572    local(*F,*T);
573    open(F,"< $from\0") or die "Can't read $from: $!\n";
574    if (open(T,"< $to\0")) {
575        local $_;
576	while (<F>) { $diff++,last if $_ ne <T>; }
577	$diff++ unless eof(T);
578	close T;
579    }
580    else { $diff++; }
581    close F;
582    if ($diff) {
583	if (-e $to) {
584	    unlink($to) or confess "unlink $to: $!";
585	}
586        STRICT_SWITCH: {
587	    best($from,$to), last STRICT_SWITCH if $how eq 'best';
588	    cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
589	    ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
590	    croak("ExtUtils::Manifest::cp_if_diff " .
591		  "called with illegal how argument [$how]. " .
592		  "Legal values are 'best', 'cp', and 'ln'.");
593	}
594    }
595}
596
597sub cp {
598    my ($srcFile, $dstFile) = @_;
599    my ($access,$mod) = (stat $srcFile)[8,9];
600
601    copy($srcFile,$dstFile);
602    utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
603    _manicopy_chmod($srcFile, $dstFile);
604}
605
606
607sub ln {
608    my ($srcFile, $dstFile) = @_;
609    # Fix-me - VMS can support links.
610    return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
611    link($srcFile, $dstFile);
612
613    unless( _manicopy_chmod($srcFile, $dstFile) ) {
614        unlink $dstFile;
615        return;
616    }
617    1;
618}
619
620# 1) Strip off all group and world permissions.
621# 2) Let everyone read it.
622# 3) If the owner can execute it, everyone can.
623sub _manicopy_chmod {
624    my($srcFile, $dstFile) = @_;
625
626    my $perm = 0444 | (stat $srcFile)[2] & 0700;
627    chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
628}
629
630# Files that are often modified in the distdir.  Don't hard link them.
631my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
632sub best {
633    my ($srcFile, $dstFile) = @_;
634
635    my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
636    if ($is_exception or !$Config{d_link} or -l $srcFile) {
637	cp($srcFile, $dstFile);
638    } else {
639	ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
640    }
641}
642
643sub _macify {
644    my($file) = @_;
645
646    return $file unless $Is_MacOS;
647
648    $file =~ s|^\./||;
649    if ($file =~ m|/|) {
650	$file =~ s|/+|:|g;
651	$file = ":$file";
652    }
653
654    $file;
655}
656
657sub _maccat {
658    my($f1, $f2) = @_;
659
660    return "$f1/$f2" unless $Is_MacOS;
661
662    $f1 .= ":$f2";
663    $f1 =~ s/([^:]:):/$1/g;
664    return $f1;
665}
666
667sub _unmacify {
668    my($file) = @_;
669
670    return $file unless $Is_MacOS;
671
672    $file =~ s|^:||;
673    $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
674    $file =~ y|:|/|;
675
676    $file;
677}
678
679
680=head2 maniadd
681
682  maniadd({ $file => $comment, ...});
683
684Adds an entry to an existing F<MANIFEST> unless its already there.
685
686$file will be normalized (ie. Unixified).  B<UNIMPLEMENTED>
687
688=cut
689
690sub maniadd {
691    my($additions) = shift;
692
693    _normalize($additions);
694    _fix_manifest($MANIFEST);
695
696    my $manifest = maniread();
697    my @needed = grep !exists $manifest->{$_}, keys %$additions;
698    return 1 unless @needed;
699
700    open(MANIFEST, ">>$MANIFEST") or
701      die "maniadd() could not open $MANIFEST: $!";
702    binmode MANIFEST, ':raw';
703
704    foreach my $file (_sort @needed) {
705        my $comment = $additions->{$file} || '';
706        if ($file =~ /\s/) {
707            $file =~ s/([\\'])/\\$1/g;
708            $file = "'$file'";
709        }
710        printf MANIFEST "%-40s %s\n", $file, $comment;
711    }
712    close MANIFEST or die "Error closing $MANIFEST: $!";
713
714    return 1;
715}
716
717
718# Make sure this MANIFEST is consistently written with native
719# newlines and has a terminal newline.
720sub _fix_manifest {
721    my $manifest_file = shift;
722
723    open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
724    local $/;
725    my @manifest = split /(\015\012|\012|\015)/, <MANIFEST>, -1;
726    close MANIFEST;
727    my $must_rewrite = "";
728    if ($manifest[-1] eq ""){
729        # sane case: last line had a terminal newline
730        pop @manifest;
731        for (my $i=1; $i<=$#manifest; $i+=2) {
732            unless ($manifest[$i] eq "\n") {
733                $must_rewrite = "not a newline at pos $i";
734                last;
735            }
736        }
737    } else {
738        $must_rewrite = "last line without newline";
739    }
740
741    if ( $must_rewrite ) {
742        1 while unlink $MANIFEST; # avoid multiple versions on VMS
743        open MANIFEST, ">", $MANIFEST or die "(must_rewrite=$must_rewrite) Could not open >$MANIFEST: $!";
744	binmode MANIFEST, ':raw';
745        for (my $i=0; $i<=$#manifest; $i+=2) {
746            print MANIFEST "$manifest[$i]\n";
747        }
748        close MANIFEST or die "could not write $MANIFEST: $!";
749    }
750}
751
752
753# UNIMPLEMENTED
754sub _normalize {
755    return;
756}
757
758=head2 MANIFEST
759
760A list of files in the distribution, one file per line.  The MANIFEST
761always uses Unix filepath conventions even if you're not on Unix.  This
762means F<foo/bar> style not F<foo\bar>.
763
764Anything between white space and an end of line within a C<MANIFEST>
765file is considered to be a comment.  Any line beginning with # is also
766a comment. Beginning with ExtUtils::Manifest 1.52, a filename may
767contain whitespace characters if it is enclosed in single quotes; single
768quotes or backslashes in that filename must be backslash-escaped.
769
770    # this a comment
771    some/file
772    some/other/file            comment about some/file
773    'some/third file'          comment
774
775
776=head2 MANIFEST.SKIP
777
778The file MANIFEST.SKIP may contain regular expressions of files that
779should be ignored by mkmanifest() and filecheck(). The regular
780expressions should appear one on each line. Blank lines and lines
781which start with C<#> are skipped.  Use C<\#> if you need a regular
782expression to start with a C<#>.
783
784For example:
785
786    # Version control files and dirs.
787    \bRCS\b
788    \bCVS\b
789    ,v$
790    \B\.svn\b
791
792    # Makemaker generated files and dirs.
793    ^MANIFEST\.
794    ^Makefile$
795    ^blib/
796    ^MakeMaker-\d
797
798    # Temp, old and emacs backup files.
799    ~$
800    \.old$
801    ^#.*#$
802    ^\.#
803
804If no MANIFEST.SKIP file is found, a default set of skips will be
805used, similar to the example above.  If you want nothing skipped,
806simply make an empty MANIFEST.SKIP file.
807
808In one's own MANIFEST.SKIP file, certain directives
809can be used to include the contents of other MANIFEST.SKIP
810files. At present two such directives are recognized.
811
812=over 4
813
814=item #!include_default
815
816This inserts the contents of the default MANIFEST.SKIP file
817
818=item #!include /Path/to/another/manifest.skip
819
820This inserts the contents of the specified external file
821
822=back
823
824The included contents will be inserted into the MANIFEST.SKIP
825file in between I<#!start included /path/to/manifest.skip>
826and I<#!end included /path/to/manifest.skip> markers.
827The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
828
829=head2 EXPORT_OK
830
831C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
832C<&maniread>, and C<&manicopy> are exportable.
833
834=head2 GLOBAL VARIABLES
835
836C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
837results in both a different C<MANIFEST> and a different
838C<MANIFEST.SKIP> file. This is useful if you want to maintain
839different distributions for different audiences (say a user version
840and a developer version including RCS).
841
842C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
843all functions act silently.
844
845C<$ExtUtils::Manifest::Debug> defaults to 0.  If set to a true value,
846or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
847produced.
848
849=head1 DIAGNOSTICS
850
851All diagnostic output is sent to C<STDERR>.
852
853=over 4
854
855=item C<Not in MANIFEST:> I<file>
856
857is reported if a file is found which is not in C<MANIFEST>.
858
859=item C<Skipping> I<file>
860
861is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
862
863=item C<No such file:> I<file>
864
865is reported if a file mentioned in a C<MANIFEST> file does not
866exist.
867
868=item C<MANIFEST:> I<$!>
869
870is reported if C<MANIFEST> could not be opened.
871
872=item C<Added to MANIFEST:> I<file>
873
874is reported by mkmanifest() if $Verbose is set and a file is added
875to MANIFEST. $Verbose is set to 1 by default.
876
877=back
878
879=head1 ENVIRONMENT
880
881=over 4
882
883=item B<PERL_MM_MANIFEST_DEBUG>
884
885Turns on debugging
886
887=back
888
889=head1 SEE ALSO
890
891L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
892
893=head1 AUTHOR
894
895Andreas Koenig C<andreas.koenig@anima.de>
896
897Currently maintained by the Perl Toolchain Gang.
898
899=head1 COPYRIGHT AND LICENSE
900
901This software is copyright (c) 1996- by Andreas Koenig.
902
903This is free software; you can redistribute it and/or modify it under
904the same terms as the Perl 5 programming language system itself.
905
906=cut
907
9081;
909