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