This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update ExtUtils::Manifest from 1.72 to 1.73
[perl5.git] / cpan / ExtUtils-Manifest / lib / ExtUtils / Manifest.pm
CommitLineData
8d01fcd8 1package ExtUtils::Manifest; # git description: 1.72-7-g54209ce
005c1a0e 2
005c1a0e 3require Exporter;
8e07c86e 4use Config;
5dca256e 5use File::Basename;
79dd614e 6use File::Copy 'copy';
5dca256e 7use File::Find;
9ec867d3 8use File::Spec 0.8;
005c1a0e 9use Carp;
8a1da95f 10use strict;
7f7b3776 11use warnings;
8a1da95f 12
8d01fcd8 13our $VERSION = '1.73';
4cedf205 14our @ISA = ('Exporter');
7f7b3776 15our @EXPORT_OK = qw(mkmanifest
479d2113
MS
16 manicheck filecheck fullcheck skipcheck
17 manifind maniread manicopy maniadd
6dbcfe36 18 maniskip
479d2113 19 );
005c1a0e 20
7f7b3776
KE
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
7e4d7138
SH
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'} || '';
04721f73 44 $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i;
7e4d7138
SH
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}
005c1a0e 52
7f7b3776
KE
53our $Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
54our $Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
75e2e551 55 $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
7f7b3776
KE
56our $Quiet = 0;
57our $MANIFEST = 'MANIFEST';
479d2113 58
8d01fcd8 59our $DEFAULT_MSKIP = File::Spec->rel2abs(File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" ));
4e68a208 60
479d2113
MS
61
62=head1 NAME
63
4745c643 64ExtUtils::Manifest - Utilities to write and check a MANIFEST file
479d2113 65
9ec867d3
KE
66=head1 VERSION
67
8d01fcd8 68version 1.73
9ec867d3 69
479d2113
MS
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
4745c643 92...
479d2113 93
4745c643 94=head1 FUNCTIONS
479d2113 95
4745c643
SH
96ExtUtils::Manifest exports no functions by default. The following are
97exported on request:
479d2113 98
4745c643 99=head2 mkmanifest
479d2113
MS
100
101 mkmanifest();
102
103Writes all files in and below the current directory to your F<MANIFEST>.
6dbcfe36 104It works similar to the result of the Unix command
479d2113
MS
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
6dbcfe36 111Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.
479d2113
MS
112
113=cut
114
dedf98bc
MS
115sub _sort {
116 return sort { lc $a cmp lc $b } @_;
117}
118
005c1a0e
AD
119sub mkmanifest {
120 my $manimiss = 0;
0300da75 121 my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
005c1a0e 122 $read = {} if $manimiss;
864a5fa8 123 local *M;
a2fa79ff 124 my $bakbase = $MANIFEST;
7e4d7138 125 $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
a2fa79ff 126 rename $MANIFEST, "$bakbase.bak" unless $manimiss;
6dbcfe36 127 open M, "> $MANIFEST" or die "Could not open $MANIFEST: $!";
4cedf205 128 binmode M, ':raw';
6dbcfe36 129 my $skip = maniskip();
005c1a0e
AD
130 my $found = manifind();
131 my($key,$val,$file,%all);
f1387719 132 %all = (%$found, %$read);
7e4d7138
SH
133 $all{$MANIFEST} = ($Is_VMS_mode ? "$MANIFEST\t\t" : '') .
134 'This list of files'
84876ac5 135 if $manimiss; # add new MANIFEST to known file list
dedf98bc 136 foreach $file (_sort keys %all) {
f6d6199c
MS
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 }
005c1a0e 143 if ($Verbose){
cb1a09d0 144 warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
005c1a0e 145 }
8e07c86e 146 my $text = $all{$file};
db5fd395 147 $file = _unmacify($file);
005c1a0e
AD
148 my $tabs = (5 - (length($file)+1)/8);
149 $tabs = 1 if $tabs < 1;
8e07c86e 150 $tabs = 0 unless $text;
6dbcfe36
SP
151 if ($file =~ /\s/) {
152 $file =~ s/([\\'])/\\$1/g;
153 $file = "'$file'";
154 }
8e07c86e 155 print M $file, "\t" x $tabs, $text, "\n";
005c1a0e
AD
156 }
157 close M;
158}
159
04721f73 160# Geez, shouldn't this use File::Spec or File::Basename or something?
f6d6199c
MS
161# Why so careful about dependencies?
162sub clean_up_filename {
163 my $filename = shift;
164 $filename =~ s|^\./||;
165 $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
8a753a87
CB
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 }
f6d6199c
MS
174 return $filename;
175}
176
479d2113 177
4745c643 178=head2 manifind
479d2113
MS
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
005c1a0e 187sub manifind {
f6d6199c 188 my $p = shift || {};
f6d6199c
MS
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;
57b1a898 194 return if -d $_;
f6d6199c
MS
195 $found->{$name} = "";
196 };
197
04721f73 198 # We have to use "$File::Find::dir/$_" in preprocess, because
f6d6199c 199 # $File::Find::name is unavailable.
04721f73 200 # Also, it's okay to use / here, because MANIFEST files use Unix-style
f6d6199c 201 # paths.
a6580644 202 find({wanted => $wanted, follow_fast => 1},
f6d6199c
MS
203 $Is_MacOS ? ":" : ".");
204
205 return $found;
005c1a0e
AD
206}
207
479d2113 208
4745c643 209=head2 manicheck
479d2113
MS
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
2c91f887 215directory are in sync it silently returns an empty list.
479d2113
MS
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
005c1a0e
AD
221
222sub manicheck {
45bc4d3a 223 return _check_files();
005c1a0e
AD
224}
225
479d2113 226
4745c643 227=head2 filecheck
479d2113
MS
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
005c1a0e 240sub filecheck {
45bc4d3a 241 return _check_manifest();
005c1a0e
AD
242}
243
479d2113 244
4745c643 245=head2 fullcheck
479d2113
MS
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
4745c643 259=head2 skipcheck
479d2113
MS
260
261 my @skipped = skipcheck();
262
263lists all the files that are skipped due to your C<MANIFEST.SKIP>
264file.
265
266=cut
267
8e07c86e 268sub skipcheck {
45bc4d3a
JH
269 my($p) = @_;
270 my $found = manifind();
6dbcfe36 271 my $matches = maniskip();
45bc4d3a
JH
272
273 my @skipped = ();
dedf98bc 274 foreach my $file (_sort keys %$found){
45bc4d3a 275 if (&$matches($file)){
551c793c 276 warn "Skipping $file\n" unless $Quiet;
45bc4d3a
JH
277 push @skipped, $file;
278 next;
279 }
280 }
281
282 return @skipped;
8e07c86e
AD
283}
284
f6d6199c 285
45bc4d3a
JH
286sub _check_files {
287 my $p = shift;
39e571d4 288 my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
45bc4d3a
JH
289 my $read = maniread() || {};
290 my $found = manifind($p);
291
292 my(@missfile) = ();
dedf98bc 293 foreach my $file (_sort keys %$read){
45bc4d3a
JH
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 }
005c1a0e 304 }
45bc4d3a
JH
305
306 return @missfile;
307}
308
309
310sub _check_manifest {
311 my($p) = @_;
312 my $read = maniread() || {};
313 my $found = manifind($p);
6dbcfe36 314 my $skip = maniskip();
45bc4d3a
JH
315
316 my @missentry = ();
dedf98bc 317 foreach my $file (_sort keys %$found){
45bc4d3a
JH
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 }
005c1a0e 325 }
45bc4d3a
JH
326
327 return @missentry;
005c1a0e
AD
328}
329
45bc4d3a 330
4745c643 331=head2 maniread
479d2113
MS
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
005c1a0e
AD
343sub maniread {
344 my ($mfile) = @_;
15a074ca 345 $mfile ||= $MANIFEST;
005c1a0e
AD
346 my $read = {};
347 local *M;
6dbcfe36 348 unless (open M, "< $mfile"){
1c14aae0 349 warn "Problem opening $mfile: $!";
2530b651 350 return $read;
005c1a0e 351 }
2530b651 352 local $_;
005c1a0e 353 while (<M>){
2530b651 354 chomp;
1df8d179 355 next if /^\s*#/;
0e3309e2 356
6dbcfe36
SP
357 my($file, $comment);
358
359 # filename may contain spaces if enclosed in ''
360 # (in which case, \\ and \' are escapes)
9a7aaf57 361 if (($file, $comment) = /^'((?:\\[\\']|.+)+)'\s*(.*)/) {
6dbcfe36
SP
362 $file =~ s/\\([\\'])/$1/g;
363 }
364 else {
365 ($file, $comment) = /^(\S+)\s*(.*)/;
366 }
0e3309e2
MS
367 next unless $file;
368
2530b651
MS
369 if ($Is_MacOS) {
370 $file = _macify($file);
371 $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
372 }
7e4d7138 373 elsif ($Is_VMS_mode) {
2530b651
MS
374 require File::Basename;
375 my($base,$dir) = File::Basename::fileparse($file);
376 # Resolve illegal file specifications in the same way as tar
7e4d7138
SH
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;
04721f73 385 }
6d1b7e1c
CB
386 if( $Is_VMS_lc ) {
387 $file = lc($file);
388 $file = uc($file) if $file =~ /^MANIFEST(\.SKIP)?$/i;
389 }
2530b651 390 }
0e3309e2
MS
391
392 $read->{$file} = $comment;
005c1a0e
AD
393 }
394 close M;
395 $read;
396}
397
4745c643 398=head2 maniskip
6dbcfe36
SP
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
005c1a0e 411# returns an anonymous sub that decides if an argument matches
6dbcfe36 412sub maniskip {
005c1a0e 413 my @skip ;
6dbcfe36 414 my $mfile = shift || "$MANIFEST.SKIP";
1c14aae0
RGS
415 _check_mskip_directives($mfile) if -f $mfile;
416 local(*M, $_);
6dbcfe36 417 open M, "< $mfile" or open M, "< $DEFAULT_MSKIP" or return sub {0};
005c1a0e 418 while (<M>){
551c793c
SH
419 chomp;
420 s/\r//;
421 $_ =~ qr{^\s*(?:(?:'([^\\']*(?:\\.[^\\']*)*)')|([^#\s]\S*))?(?:(?:\s*)|(?:\s+(.*?)\s*))$};
422 #my $comment = $3;
423 my $filename = $2;
04721f73
FR
424 if ( defined($1) ) {
425 $filename = $1;
551c793c
SH
426 $filename =~ s/\\(['\\])/$1/g;
427 }
428 next if (not defined($filename) or not $filename);
429 push @skip, _macify($filename);
005c1a0e
AD
430 }
431 close M;
b3217f3b
SP
432 return sub {0} unless (scalar @skip > 0);
433
7e4d7138 434 my $opts = $Is_VMS_mode ? '(?i)' : '';
f6d6199c
MS
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
45bc4d3a 440 return sub { $_[0] =~ qr{$opts$regex} };
005c1a0e
AD
441}
442
1c14aae0
RGS
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;
6dbcfe36 454 unless (open M, "< $mfile") {
1c14aae0
RGS
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;
a2fa79ff 480 my $bakbase = $mfile;
7e4d7138 481 $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
a2fa79ff
CB
482 rename $mfile, "$bakbase.bak";
483 warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
6dbcfe36 484 unless (open M, "> $mfile") {
1c14aae0
RGS
485 warn "Problem opening $mfile: $!";
486 return;
487 }
4cedf205 488 binmode M, ':raw';
1c14aae0
RGS
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, $_);
6dbcfe36 503 unless (open M, "< $mskip") {
1c14aae0
RGS
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
4745c643 515=head2 manicopy
479d2113 516
a7d1454b
RGS
517 manicopy(\%src, $dest_dir);
518 manicopy(\%src, $dest_dir, $how);
479d2113 519
a7d1454b
RGS
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
04721f73
FR
525This function is useful for producing a directory tree identical to the
526intended distribution tree.
a7d1454b
RGS
527
528$how can be used to specify a different methods of "copying". Valid
479d2113
MS
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
04721f73 531symbolic link to make a tree without any symbolic link. C<cp> is the
479d2113
MS
532default.
533
534=cut
535
005c1a0e 536sub manicopy {
8e07c86e 537 my($read,$target,$how)=@_;
005c1a0e 538 croak "manicopy() called without target argument" unless defined $target;
15a074ca 539 $how ||= 'cp';
005c1a0e
AD
540 require File::Path;
541 require File::Basename;
57b1a898 542
7e4d7138 543 $target = VMS::Filespec::unixify($target) if $Is_VMS_mode;
553c0e07 544 File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
57b1a898 545 foreach my $file (keys %$read){
04721f73
FR
546 if ($Is_MacOS) {
547 if ($file =~ m!:!) {
548 my $dir = _maccat($target, $file);
db5fd395 549 $dir =~ s/[^:]+$//;
04721f73 550 File::Path::mkpath($dir,1,0755);
db5fd395
CN
551 }
552 cp_if_diff($file, _maccat($target, $file), $how);
553 } else {
7e4d7138 554 $file = VMS::Filespec::unixify($file) if $Is_VMS_mode;
db5fd395
CN
555 if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
556 my $dir = File::Basename::dirname($file);
7e4d7138 557 $dir = VMS::Filespec::unixify($dir) if $Is_VMS_mode;
db5fd395
CN
558 File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
559 }
560 cp_if_diff($file, "$target/$file", $how);
84876ac5 561 }
005c1a0e
AD
562 }
563}
564
565sub cp_if_diff {
8a1da95f 566 my($from, $to, $how)=@_;
6dbcfe36
SP
567 if (! -f $from) {
568 carp "$from not found";
569 return;
570 }
8e07c86e
AD
571 my($diff) = 0;
572 local(*F,*T);
57b1a898 573 open(F,"< $from\0") or die "Can't read $from: $!\n";
db5fd395 574 if (open(T,"< $to\0")) {
2530b651 575 local $_;
8e07c86e
AD
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 }
7292dc67 586 STRICT_SWITCH: {
15a074ca
AK
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 }
8e07c86e
AD
594 }
595}
596
8e07c86e
AD
597sub cp {
598 my ($srcFile, $dstFile) = @_;
a7d1454b
RGS
599 my ($access,$mod) = (stat $srcFile)[8,9];
600
79dd614e 601 copy($srcFile,$dstFile);
9607fc9c 602 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
1c14aae0 603 _manicopy_chmod($srcFile, $dstFile);
8e07c86e
AD
604}
605
a7d1454b 606
8e07c86e
AD
607sub ln {
608 my ($srcFile, $dstFile) = @_;
7e4d7138 609 # Fix-me - VMS can support links.
f0f13d0e 610 return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
8e07c86e 611 link($srcFile, $dstFile);
57b1a898 612
1c14aae0 613 unless( _manicopy_chmod($srcFile, $dstFile) ) {
57b1a898
MS
614 unlink $dstFile;
615 return;
4e6ea2c3
GS
616 }
617 1;
8e07c86e
AD
618}
619
a7d1454b
RGS
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 {
1c14aae0 624 my($srcFile, $dstFile) = @_;
57b1a898 625
1c14aae0
RGS
626 my $perm = 0444 | (stat $srcFile)[2] & 0700;
627 chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
a7d1454b 628}
57b1a898 629
7292dc67
RGS
630# Files that are often modified in the distdir. Don't hard link them.
631my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
4633a7c4
LW
632sub best {
633 my ($srcFile, $dstFile) = @_;
7292dc67
RGS
634
635 my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
636 if ($is_exception or !$Config{d_link} or -l $srcFile) {
4633a7c4
LW
637 cp($srcFile, $dstFile);
638 } else {
3dee4013 639 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
4633a7c4
LW
640 }
641}
642
db5fd395
CN
643sub _macify {
644 my($file) = @_;
645
646 return $file unless $Is_MacOS;
a7d1454b 647
db5fd395
CN
648 $file =~ s|^\./||;
649 if ($file =~ m|/|) {
650 $file =~ s|/+|:|g;
651 $file = ":$file";
652 }
a7d1454b 653
db5fd395
CN
654 $file;
655}
656
657sub _maccat {
658 my($f1, $f2) = @_;
a7d1454b 659
db5fd395 660 return "$f1/$f2" unless $Is_MacOS;
a7d1454b 661
db5fd395
CN
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;
5dca256e 671
db5fd395
CN
672 $file =~ s|^:||;
673 $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
674 $file =~ y|:|/|;
5dca256e 675
db5fd395
CN
676 $file;
677}
678
79dd614e 679
4745c643 680=head2 maniadd
79dd614e 681
479d2113 682 maniadd({ $file => $comment, ...});
79dd614e 683
1df8d179 684Adds an entry to an existing F<MANIFEST> unless its already there.
79dd614e 685
479d2113 686$file will be normalized (ie. Unixified). B<UNIMPLEMENTED>
79dd614e 687
479d2113 688=cut
79dd614e 689
479d2113
MS
690sub maniadd {
691 my($additions) = shift;
79dd614e 692
479d2113 693 _normalize($additions);
2530b651 694 _fix_manifest($MANIFEST);
79dd614e 695
479d2113 696 my $manifest = maniread();
1633525e 697 my @needed = grep !exists $manifest->{$_}, keys %$additions;
30361541 698 return 1 unless @needed;
1df8d179 699
04721f73 700 open(MANIFEST, ">>$MANIFEST") or
30361541 701 die "maniadd() could not open $MANIFEST: $!";
4cedf205 702 binmode MANIFEST, ':raw';
2c91f887 703
30361541 704 foreach my $file (_sort @needed) {
dedf98bc 705 my $comment = $additions->{$file} || '';
6dbcfe36
SP
706 if ($file =~ /\s/) {
707 $file =~ s/([\\'])/\\$1/g;
708 $file = "'$file'";
709 }
30361541 710 printf MANIFEST "%-40s %s\n", $file, $comment;
479d2113 711 }
30361541
JH
712 close MANIFEST or die "Error closing $MANIFEST: $!";
713
714 return 1;
479d2113 715}
79dd614e 716
2530b651 717
e4ac890e
SA
718# Make sure this MANIFEST is consistently written with native
719# newlines and has a terminal newline.
2530b651
MS
720sub _fix_manifest {
721 my $manifest_file = shift;
722
723 open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
e4ac890e
SA
724 local $/;
725 my @manifest = split /(\015\012|\012|\015)/, <MANIFEST>, -1;
2530b651 726 close MANIFEST;
e4ac890e
SA
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 }
2530b651 740
e4ac890e 741 if ( $must_rewrite ) {
f4ef3693 742 1 while unlink $MANIFEST; # avoid multiple versions on VMS
e4ac890e 743 open MANIFEST, ">", $MANIFEST or die "(must_rewrite=$must_rewrite) Could not open >$MANIFEST: $!";
4cedf205 744 binmode MANIFEST, ':raw';
e4ac890e
SA
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: $!";
2530b651
MS
749 }
750}
5dca256e 751
2530b651 752
479d2113
MS
753# UNIMPLEMENTED
754sub _normalize {
755 return;
756}
79dd614e 757
479d2113 758=head2 MANIFEST
79dd614e 759
5dca256e
RGS
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
479d2113 764Anything between white space and an end of line within a C<MANIFEST>
5dca256e 765file is considered to be a comment. Any line beginning with # is also
6dbcfe36
SP
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.
5dca256e
RGS
769
770 # this a comment
771 some/file
772 some/other/file comment about some/file
6dbcfe36 773 'some/third file' comment
79dd614e 774
79dd614e 775
479d2113 776=head2 MANIFEST.SKIP
79dd614e
PP
777
778The file MANIFEST.SKIP may contain regular expressions of files that
779should be ignored by mkmanifest() and filecheck(). The regular
15a074ca
AK
780expressions should appear one on each line. Blank lines and lines
781which start with C<#> are skipped. Use C<\#> if you need a regular
5dca256e
RGS
782expression to start with a C<#>.
783
784For example:
79dd614e 785
0b9c804f 786 # Version control files and dirs.
79dd614e 787 \bRCS\b
0b9c804f
MS
788 \bCVS\b
789 ,v$
479d2113 790 \B\.svn\b
0b9c804f
MS
791
792 # Makemaker generated files and dirs.
79dd614e
PP
793 ^MANIFEST\.
794 ^Makefile$
79dd614e
PP
795 ^blib/
796 ^MakeMaker-\d
797
0b9c804f
MS
798 # Temp, old and emacs backup files.
799 ~$
800 \.old$
801 ^#.*#$
cfcce72b 802 ^\.#
0b9c804f
MS
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
1c14aae0
RGS
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.
0b9c804f 828
479d2113 829=head2 EXPORT_OK
79dd614e
PP
830
831C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
832C<&maniread>, and C<&manicopy> are exportable.
833
479d2113 834=head2 GLOBAL VARIABLES
79dd614e
PP
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
81ff29e3 842C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
79dd614e
PP
843all functions act silently.
844
0b9c804f
MS
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
79dd614e
PP
849=head1 DIAGNOSTICS
850
851All diagnostic output is sent to C<STDERR>.
852
bbc7dcd2 853=over 4
79dd614e
PP
854
855=item C<Not in MANIFEST:> I<file>
856
45bc4d3a
JH
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>.
79dd614e
PP
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
0b9c804f
MS
879=head1 ENVIRONMENT
880
881=over 4
882
883=item B<PERL_MM_MANIFEST_DEBUG>
884
885Turns on debugging
886
887=back
888
79dd614e
PP
889=head1 SEE ALSO
890
891L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
892
893=head1 AUTHOR
894
a7d1454b
RGS
895Andreas Koenig C<andreas.koenig@anima.de>
896
f660499c
CBW
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.
79dd614e
PP
905
906=cut
479d2113
MS
907
9081;