This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to ExtUtils-Command-1.16
[perl5.git] / lib / ExtUtils / Manifest.pm
CommitLineData
005c1a0e
AD
1package ExtUtils::Manifest;
2
005c1a0e 3require Exporter;
8e07c86e 4use Config;
5dca256e 5use File::Basename;
79dd614e 6use File::Copy 'copy';
5dca256e 7use File::Find;
57b1a898 8use File::Spec;
005c1a0e 9use Carp;
8a1da95f 10use strict;
11
57b1a898
MS
12use vars qw($VERSION @ISA @EXPORT_OK
13 $Is_MacOS $Is_VMS
14 $Debug $Verbose $Quiet $MANIFEST $DEFAULT_MSKIP);
8a1da95f 15
7a5ea4ae 16$VERSION = '1.55';
8a1da95f 17@ISA=('Exporter');
479d2113
MS
18@EXPORT_OK = qw(mkmanifest
19 manicheck filecheck fullcheck skipcheck
20 manifind maniread manicopy maniadd
6dbcfe36 21 maniskip
479d2113 22 );
005c1a0e 23
db5fd395 24$Is_MacOS = $^O eq 'MacOS';
479d2113 25$Is_VMS = $^O eq 'VMS';
f6d6199c 26require VMS::Filespec if $Is_VMS;
005c1a0e 27
479d2113 28$Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
75e2e551
MS
29$Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
30 $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
005c1a0e 31$Quiet = 0;
cb1a09d0 32$MANIFEST = 'MANIFEST';
479d2113 33
5dca256e 34$DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
4e68a208 35
479d2113
MS
36
37=head1 NAME
38
39ExtUtils::Manifest - utilities to write and check a MANIFEST file
40
41=head1 SYNOPSIS
42
43 use ExtUtils::Manifest qw(...funcs to import...);
44
45 mkmanifest();
46
47 my @missing_files = manicheck;
48 my @skipped = skipcheck;
49 my @extra_files = filecheck;
50 my($missing, $extra) = fullcheck;
51
52 my $found = manifind();
53
54 my $manifest = maniread();
55
56 manicopy($read,$target);
57
58 maniadd({$file => $comment, ...});
59
60
61=head1 DESCRIPTION
62
63=head2 Functions
64
65ExtUtils::Manifest exports no functions by default. The following are
66exported on request
67
68=over 4
69
70=item mkmanifest
71
72 mkmanifest();
73
74Writes all files in and below the current directory to your F<MANIFEST>.
6dbcfe36 75It works similar to the result of the Unix command
479d2113
MS
76
77 find . > MANIFEST
78
79All files that match any regular expression in a file F<MANIFEST.SKIP>
80(if it exists) are ignored.
81
6dbcfe36 82Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.
479d2113
MS
83
84=cut
85
dedf98bc
MS
86sub _sort {
87 return sort { lc $a cmp lc $b } @_;
88}
89
005c1a0e
AD
90sub mkmanifest {
91 my $manimiss = 0;
0300da75 92 my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
005c1a0e 93 $read = {} if $manimiss;
864a5fa8 94 local *M;
a2fa79ff
CB
95 my $bakbase = $MANIFEST;
96 $bakbase =~ s/\./_/g if $Is_VMS; # avoid double dots
97 rename $MANIFEST, "$bakbase.bak" unless $manimiss;
6dbcfe36
SP
98 open M, "> $MANIFEST" or die "Could not open $MANIFEST: $!";
99 my $skip = maniskip();
005c1a0e
AD
100 my $found = manifind();
101 my($key,$val,$file,%all);
f1387719 102 %all = (%$found, %$read);
84876ac5 103 $all{$MANIFEST} = ($Is_VMS ? "$MANIFEST\t\t" : '') . 'This list of files'
104 if $manimiss; # add new MANIFEST to known file list
dedf98bc 105 foreach $file (_sort keys %all) {
f6d6199c
MS
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};
110 next;
111 }
005c1a0e 112 if ($Verbose){
cb1a09d0 113 warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
005c1a0e 114 }
8e07c86e 115 my $text = $all{$file};
db5fd395 116 $file = _unmacify($file);
005c1a0e
AD
117 my $tabs = (5 - (length($file)+1)/8);
118 $tabs = 1 if $tabs < 1;
8e07c86e 119 $tabs = 0 unless $text;
6dbcfe36
SP
120 if ($file =~ /\s/) {
121 $file =~ s/([\\'])/\\$1/g;
122 $file = "'$file'";
123 }
8e07c86e 124 print M $file, "\t" x $tabs, $text, "\n";
005c1a0e
AD
125 }
126 close M;
127}
128
f6d6199c
MS
129# Geez, shouldn't this use File::Spec or File::Basename or something?
130# Why so careful about dependencies?
131sub clean_up_filename {
132 my $filename = shift;
133 $filename =~ s|^\./||;
134 $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
135 return $filename;
136}
137
479d2113
MS
138
139=item manifind
140
141 my $found = manifind();
142
143returns a hash reference. The keys of the hash are the files found
144below the current directory.
145
146=cut
147
005c1a0e 148sub manifind {
f6d6199c 149 my $p = shift || {};
f6d6199c
MS
150 my $found = {};
151
152 my $wanted = sub {
153 my $name = clean_up_filename($File::Find::name);
154 warn "Debug: diskfile $name\n" if $Debug;
57b1a898 155 return if -d $_;
f6d6199c
MS
156
157 if( $Is_VMS ) {
158 $name =~ s#(.*)\.$#\L$1#;
159 $name = uc($name) if $name =~ /^MANIFEST(\.SKIP)?$/i;
160 }
161 $found->{$name} = "";
162 };
163
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
167 # paths.
57b1a898 168 find({wanted => $wanted},
f6d6199c
MS
169 $Is_MacOS ? ":" : ".");
170
171 return $found;
005c1a0e
AD
172}
173
479d2113
MS
174
175=item manicheck
176
177 my @missing_files = manicheck();
178
179checks if all the files within a C<MANIFEST> in the current directory
180really do exist. If C<MANIFEST> and the tree below the current
2c91f887 181directory are in sync it silently returns an empty list.
479d2113
MS
182Otherwise it returns a list of files which are listed in the
183C<MANIFEST> but missing from the directory, and by default also
184outputs these names to STDERR.
185
186=cut
005c1a0e
AD
187
188sub manicheck {
45bc4d3a 189 return _check_files();
005c1a0e
AD
190}
191
479d2113
MS
192
193=item filecheck
194
195 my @extra_files = filecheck();
196
197finds files below the current directory that are not mentioned in the
198C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
199consulted. Any file matching a regular expression in such a file will
200not be reported as missing in the C<MANIFEST> file. The list of any
201extraneous files found is returned, and by default also reported to
202STDERR.
203
204=cut
205
005c1a0e 206sub filecheck {
45bc4d3a 207 return _check_manifest();
005c1a0e
AD
208}
209
479d2113
MS
210
211=item fullcheck
212
213 my($missing, $extra) = fullcheck();
214
215does both a manicheck() and a filecheck(), returning then as two array
216refs.
217
218=cut
219
220sub fullcheck {
221 return [_check_files()], [_check_manifest()];
222}
223
224
225=item skipcheck
226
227 my @skipped = skipcheck();
228
229lists all the files that are skipped due to your C<MANIFEST.SKIP>
230file.
231
232=cut
233
8e07c86e 234sub skipcheck {
45bc4d3a
JH
235 my($p) = @_;
236 my $found = manifind();
6dbcfe36 237 my $matches = maniskip();
45bc4d3a
JH
238
239 my @skipped = ();
dedf98bc 240 foreach my $file (_sort keys %$found){
45bc4d3a
JH
241 if (&$matches($file)){
242 warn "Skipping $file\n";
243 push @skipped, $file;
244 next;
245 }
246 }
247
248 return @skipped;
8e07c86e
AD
249}
250
f6d6199c 251
45bc4d3a
JH
252sub _check_files {
253 my $p = shift;
39e571d4 254 my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
45bc4d3a
JH
255 my $read = maniread() || {};
256 my $found = manifind($p);
257
258 my(@missfile) = ();
dedf98bc 259 foreach my $file (_sort keys %$read){
45bc4d3a
JH
260 warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
261 if ($dosnames){
262 $file = lc $file;
263 $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
264 $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
265 }
266 unless ( exists $found->{$file} ) {
267 warn "No such file: $file\n" unless $Quiet;
268 push @missfile, $file;
269 }
005c1a0e 270 }
45bc4d3a
JH
271
272 return @missfile;
273}
274
275
276sub _check_manifest {
277 my($p) = @_;
278 my $read = maniread() || {};
279 my $found = manifind($p);
6dbcfe36 280 my $skip = maniskip();
45bc4d3a
JH
281
282 my @missentry = ();
dedf98bc 283 foreach my $file (_sort keys %$found){
45bc4d3a
JH
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;
290 }
005c1a0e 291 }
45bc4d3a
JH
292
293 return @missentry;
005c1a0e
AD
294}
295
45bc4d3a 296
479d2113
MS
297=item maniread
298
299 my $manifest = maniread();
300 my $manifest = maniread($manifest_file);
301
302reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
303directory) and returns a HASH reference with files being the keys and
304comments being the values of the HASH. Blank lines and lines which
305start with C<#> in the C<MANIFEST> file are discarded.
306
307=cut
308
005c1a0e
AD
309sub maniread {
310 my ($mfile) = @_;
15a074ca 311 $mfile ||= $MANIFEST;
005c1a0e
AD
312 my $read = {};
313 local *M;
6dbcfe36 314 unless (open M, "< $mfile"){
1c14aae0 315 warn "Problem opening $mfile: $!";
2530b651 316 return $read;
005c1a0e 317 }
2530b651 318 local $_;
005c1a0e 319 while (<M>){
2530b651 320 chomp;
1df8d179 321 next if /^\s*#/;
0e3309e2 322
6dbcfe36
SP
323 my($file, $comment);
324
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;
329 }
330 else {
331 ($file, $comment) = /^(\S+)\s*(.*)/;
332 }
0e3309e2
MS
333 next unless $file;
334
2530b651
MS
335 if ($Is_MacOS) {
336 $file = _macify($file);
337 $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
338 }
339 elsif ($Is_VMS) {
340 require File::Basename;
341 my($base,$dir) = File::Basename::fileparse($file);
342 # Resolve illegal file specifications in the same way as tar
343 $dir =~ tr/./_/;
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;
349e1be1 348 $file = $okfile;
f6d6199c 349 $file = lc($file) unless $file =~ /^MANIFEST(\.SKIP)?$/;
2530b651 350 }
0e3309e2
MS
351
352 $read->{$file} = $comment;
005c1a0e
AD
353 }
354 close M;
355 $read;
356}
357
6dbcfe36
SP
358=item maniskip
359
360 my $skipchk = maniskip();
361 my $skipchk = maniskip($manifest_skip_file);
362
363 if ($skipchk->($file)) { .. }
364
365reads a named C<MANIFEST.SKIP> file (defaults to C<MANIFEST.SKIP> in
366the current directory) and returns a CODE reference that tests whether
367a given filename should be skipped.
368
369=cut
370
005c1a0e 371# returns an anonymous sub that decides if an argument matches
6dbcfe36 372sub maniskip {
005c1a0e 373 my @skip ;
6dbcfe36 374 my $mfile = shift || "$MANIFEST.SKIP";
1c14aae0
RGS
375 _check_mskip_directives($mfile) if -f $mfile;
376 local(*M, $_);
6dbcfe36 377 open M, "< $mfile" or open M, "< $DEFAULT_MSKIP" or return sub {0};
005c1a0e
AD
378 while (<M>){
379 chomp;
b3217f3b 380 s/\r//;
15a074ca 381 next if /^#/;
005c1a0e 382 next if /^\s*$/;
6dbcfe36
SP
383 s/^'//;
384 s/'$//;
db5fd395 385 push @skip, _macify($_);
005c1a0e
AD
386 }
387 close M;
b3217f3b
SP
388 return sub {0} unless (scalar @skip > 0);
389
f6d6199c
MS
390 my $opts = $Is_VMS ? '(?i)' : '';
391
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;
395
45bc4d3a 396 return sub { $_[0] =~ qr{$opts$regex} };
005c1a0e
AD
397}
398
1c14aae0
RGS
399# checks for the special directives
400# #!include_default
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
405sub _check_mskip_directives {
406 my $mfile = shift;
407 local (*M, $_);
408 my @lines = ();
409 my $flag = 0;
6dbcfe36 410 unless (open M, "< $mfile") {
1c14aae0
RGS
411 warn "Problem opening $mfile: $!";
412 return;
413 }
414 while (<M>) {
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;
419 $flag++;
420 }
421 next;
422 }
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;
428 $flag++;
429 }
430 next;
431 }
432 push @lines, $_;
433 }
434 close M;
435 return unless $flag;
a2fa79ff
CB
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;
6dbcfe36 440 unless (open M, "> $mfile") {
1c14aae0
RGS
441 warn "Problem opening $mfile: $!";
442 return;
443 }
444 print M $_ for (@lines);
445 close M;
446 return;
447}
448
449# returns an array containing the lines of an external
450# manifest.skip file, if given, or $DEFAULT_MSKIP
451sub _include_mskip_file {
452 my $mskip = shift || $DEFAULT_MSKIP;
453 unless (-f $mskip) {
454 warn qq{Included file "$mskip" not found - skipping};
455 return;
456 }
457 local (*M, $_);
6dbcfe36 458 unless (open M, "< $mskip") {
1c14aae0
RGS
459 warn "Problem opening $mskip: $!";
460 return;
461 }
462 my @lines = ();
463 push @lines, "\n#!start included $mskip\n";
464 push @lines, $_ while <M>;
465 close M;
466 push @lines, "#!end included $mskip\n\n";
467 return @lines;
468}
469
479d2113
MS
470=item manicopy
471
a7d1454b
RGS
472 manicopy(\%src, $dest_dir);
473 manicopy(\%src, $dest_dir, $how);
479d2113 474
a7d1454b
RGS
475Copies the files that are the keys in %src to the $dest_dir. %src is
476typically returned by the maniread() function.
477
478 manicopy( maniread(), $dest_dir );
479
480This function is useful for producing a directory tree identical to the
481intended distribution tree.
482
483$how can be used to specify a different methods of "copying". Valid
479d2113
MS
484values are C<cp>, which actually copies the files, C<ln> which creates
485hard links, and C<best> which mostly links the files but copies any
a7d1454b 486symbolic link to make a tree without any symbolic link. C<cp> is the
479d2113
MS
487default.
488
489=cut
490
005c1a0e 491sub manicopy {
8e07c86e 492 my($read,$target,$how)=@_;
005c1a0e 493 croak "manicopy() called without target argument" unless defined $target;
15a074ca 494 $how ||= 'cp';
005c1a0e
AD
495 require File::Path;
496 require File::Basename;
57b1a898 497
8e07c86e 498 $target = VMS::Filespec::unixify($target) if $Is_VMS;
553c0e07 499 File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
57b1a898 500 foreach my $file (keys %$read){
db5fd395
CN
501 if ($Is_MacOS) {
502 if ($file =~ m!:!) {
503 my $dir = _maccat($target, $file);
504 $dir =~ s/[^:]+$//;
505 File::Path::mkpath($dir,1,0755);
506 }
507 cp_if_diff($file, _maccat($target, $file), $how);
508 } else {
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);
514 }
515 cp_if_diff($file, "$target/$file", $how);
84876ac5 516 }
005c1a0e
AD
517 }
518}
519
520sub cp_if_diff {
8a1da95f 521 my($from, $to, $how)=@_;
6dbcfe36
SP
522 if (! -f $from) {
523 carp "$from not found";
524 return;
525 }
8e07c86e
AD
526 my($diff) = 0;
527 local(*F,*T);
57b1a898 528 open(F,"< $from\0") or die "Can't read $from: $!\n";
db5fd395 529 if (open(T,"< $to\0")) {
2530b651 530 local $_;
8e07c86e
AD
531 while (<F>) { $diff++,last if $_ ne <T>; }
532 $diff++ unless eof(T);
533 close T;
534 }
535 else { $diff++; }
536 close F;
537 if ($diff) {
538 if (-e $to) {
539 unlink($to) or confess "unlink $to: $!";
540 }
7292dc67 541 STRICT_SWITCH: {
15a074ca
A
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'.");
548 }
8e07c86e
AD
549 }
550}
551
8e07c86e
AD
552sub cp {
553 my ($srcFile, $dstFile) = @_;
a7d1454b
RGS
554 my ($access,$mod) = (stat $srcFile)[8,9];
555
79dd614e 556 copy($srcFile,$dstFile);
9607fc9c 557 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
1c14aae0 558 _manicopy_chmod($srcFile, $dstFile);
8e07c86e
AD
559}
560
a7d1454b 561
8e07c86e
AD
562sub ln {
563 my ($srcFile, $dstFile) = @_;
f0f13d0e 564 return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
8e07c86e 565 link($srcFile, $dstFile);
57b1a898 566
1c14aae0 567 unless( _manicopy_chmod($srcFile, $dstFile) ) {
57b1a898
MS
568 unlink $dstFile;
569 return;
4e6ea2c3
GS
570 }
571 1;
8e07c86e
AD
572}
573
a7d1454b
RGS
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.
577sub _manicopy_chmod {
1c14aae0 578 my($srcFile, $dstFile) = @_;
57b1a898 579
1c14aae0
RGS
580 my $perm = 0444 | (stat $srcFile)[2] & 0700;
581 chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
a7d1454b 582}
57b1a898 583
7292dc67
RGS
584# Files that are often modified in the distdir. Don't hard link them.
585my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
4633a7c4
LW
586sub best {
587 my ($srcFile, $dstFile) = @_;
7292dc67
RGS
588
589 my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
590 if ($is_exception or !$Config{d_link} or -l $srcFile) {
4633a7c4
LW
591 cp($srcFile, $dstFile);
592 } else {
3dee4013 593 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
4633a7c4
LW
594 }
595}
596
db5fd395
CN
597sub _macify {
598 my($file) = @_;
599
600 return $file unless $Is_MacOS;
a7d1454b 601
db5fd395
CN
602 $file =~ s|^\./||;
603 if ($file =~ m|/|) {
604 $file =~ s|/+|:|g;
605 $file = ":$file";
606 }
a7d1454b 607
db5fd395
CN
608 $file;
609}
610
611sub _maccat {
612 my($f1, $f2) = @_;
a7d1454b 613
db5fd395 614 return "$f1/$f2" unless $Is_MacOS;
a7d1454b 615
db5fd395
CN
616 $f1 .= ":$f2";
617 $f1 =~ s/([^:]:):/$1/g;
618 return $f1;
619}
620
621sub _unmacify {
622 my($file) = @_;
623
624 return $file unless $Is_MacOS;
5dca256e 625
db5fd395
CN
626 $file =~ s|^:||;
627 $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
628 $file =~ y|:|/|;
5dca256e 629
db5fd395
CN
630 $file;
631}
632
79dd614e 633
479d2113 634=item maniadd
79dd614e 635
479d2113 636 maniadd({ $file => $comment, ...});
79dd614e 637
1df8d179 638Adds an entry to an existing F<MANIFEST> unless its already there.
79dd614e 639
479d2113 640$file will be normalized (ie. Unixified). B<UNIMPLEMENTED>
79dd614e 641
479d2113 642=cut
79dd614e 643
479d2113
MS
644sub maniadd {
645 my($additions) = shift;
79dd614e 646
479d2113 647 _normalize($additions);
2530b651 648 _fix_manifest($MANIFEST);
79dd614e 649
479d2113 650 my $manifest = maniread();
30361541
JH
651 my @needed = grep { !exists $manifest->{$_} } keys %$additions;
652 return 1 unless @needed;
1df8d179 653
30361541
JH
654 open(MANIFEST, ">>$MANIFEST") or
655 die "maniadd() could not open $MANIFEST: $!";
2c91f887 656
30361541 657 foreach my $file (_sort @needed) {
dedf98bc 658 my $comment = $additions->{$file} || '';
6dbcfe36
SP
659 if ($file =~ /\s/) {
660 $file =~ s/([\\'])/\\$1/g;
661 $file = "'$file'";
662 }
30361541 663 printf MANIFEST "%-40s %s\n", $file, $comment;
479d2113 664 }
30361541
JH
665 close MANIFEST or die "Error closing $MANIFEST: $!";
666
667 return 1;
479d2113 668}
79dd614e 669
2530b651
MS
670
671# Sometimes MANIFESTs are missing a trailing newline. Fix this.
672sub _fix_manifest {
673 my $manifest_file = shift;
674
675 open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
676
677 # Yes, we should be using seek(), but I'd like to avoid loading POSIX
678 # to get SEEK_*
679 my @manifest = <MANIFEST>;
680 close MANIFEST;
681
682 unless( $manifest[-1] =~ /\n\z/ ) {
683 open MANIFEST, ">>$MANIFEST" or die "Could not open $MANIFEST: $!";
684 print MANIFEST "\n";
685 close MANIFEST;
686 }
687}
5dca256e 688
2530b651 689
479d2113
MS
690# UNIMPLEMENTED
691sub _normalize {
692 return;
693}
79dd614e 694
79dd614e 695
479d2113 696=back
79dd614e 697
479d2113 698=head2 MANIFEST
79dd614e 699
5dca256e
RGS
700A list of files in the distribution, one file per line. The MANIFEST
701always uses Unix filepath conventions even if you're not on Unix. This
702means F<foo/bar> style not F<foo\bar>.
703
479d2113 704Anything between white space and an end of line within a C<MANIFEST>
5dca256e 705file is considered to be a comment. Any line beginning with # is also
6dbcfe36
SP
706a comment. Beginning with ExtUtils::Manifest 1.52, a filename may
707contain whitespace characters if it is enclosed in single quotes; single
708quotes or backslashes in that filename must be backslash-escaped.
5dca256e
RGS
709
710 # this a comment
711 some/file
712 some/other/file comment about some/file
6dbcfe36 713 'some/third file' comment
79dd614e 714
79dd614e 715
479d2113 716=head2 MANIFEST.SKIP
79dd614e 717
718The file MANIFEST.SKIP may contain regular expressions of files that
719should be ignored by mkmanifest() and filecheck(). The regular
15a074ca
A
720expressions should appear one on each line. Blank lines and lines
721which start with C<#> are skipped. Use C<\#> if you need a regular
5dca256e
RGS
722expression to start with a C<#>.
723
724For example:
79dd614e 725
0b9c804f 726 # Version control files and dirs.
79dd614e 727 \bRCS\b
0b9c804f
MS
728 \bCVS\b
729 ,v$
479d2113 730 \B\.svn\b
0b9c804f
MS
731
732 # Makemaker generated files and dirs.
79dd614e 733 ^MANIFEST\.
734 ^Makefile$
79dd614e 735 ^blib/
736 ^MakeMaker-\d
737
0b9c804f
MS
738 # Temp, old and emacs backup files.
739 ~$
740 \.old$
741 ^#.*#$
cfcce72b 742 ^\.#
0b9c804f
MS
743
744If no MANIFEST.SKIP file is found, a default set of skips will be
745used, similar to the example above. If you want nothing skipped,
746simply make an empty MANIFEST.SKIP file.
747
1c14aae0
RGS
748In one's own MANIFEST.SKIP file, certain directives
749can be used to include the contents of other MANIFEST.SKIP
750files. At present two such directives are recognized.
751
752=over 4
753
754=item #!include_default
755
756This inserts the contents of the default MANIFEST.SKIP file
757
758=item #!include /Path/to/another/manifest.skip
759
760This inserts the contents of the specified external file
761
762=back
763
764The included contents will be inserted into the MANIFEST.SKIP
765file in between I<#!start included /path/to/manifest.skip>
766and I<#!end included /path/to/manifest.skip> markers.
767The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
0b9c804f 768
479d2113 769=head2 EXPORT_OK
79dd614e 770
771C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
772C<&maniread>, and C<&manicopy> are exportable.
773
479d2113 774=head2 GLOBAL VARIABLES
79dd614e 775
776C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
777results in both a different C<MANIFEST> and a different
778C<MANIFEST.SKIP> file. This is useful if you want to maintain
779different distributions for different audiences (say a user version
780and a developer version including RCS).
781
81ff29e3 782C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
79dd614e 783all functions act silently.
784
0b9c804f
MS
785C<$ExtUtils::Manifest::Debug> defaults to 0. If set to a true value,
786or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
787produced.
788
79dd614e 789=head1 DIAGNOSTICS
790
791All diagnostic output is sent to C<STDERR>.
792
bbc7dcd2 793=over 4
79dd614e 794
795=item C<Not in MANIFEST:> I<file>
796
45bc4d3a
JH
797is reported if a file is found which is not in C<MANIFEST>.
798
799=item C<Skipping> I<file>
800
801is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
79dd614e 802
803=item C<No such file:> I<file>
804
805is reported if a file mentioned in a C<MANIFEST> file does not
806exist.
807
808=item C<MANIFEST:> I<$!>
809
810is reported if C<MANIFEST> could not be opened.
811
812=item C<Added to MANIFEST:> I<file>
813
814is reported by mkmanifest() if $Verbose is set and a file is added
815to MANIFEST. $Verbose is set to 1 by default.
816
817=back
818
0b9c804f
MS
819=head1 ENVIRONMENT
820
821=over 4
822
823=item B<PERL_MM_MANIFEST_DEBUG>
824
825Turns on debugging
826
827=back
828
79dd614e 829=head1 SEE ALSO
830
831L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
832
833=head1 AUTHOR
834
a7d1454b
RGS
835Andreas Koenig C<andreas.koenig@anima.de>
836
4c857482
SP
837Maintained by Michael G Schwern C<schwern@pobox.com> within the
838ExtUtils-MakeMaker package and, as a separate CPAN package, by
839Randy Kobes C<r.kobes@uwinnipeg.ca>.
79dd614e 840
841=cut
479d2113
MS
842
8431;