File Coverage

blib/lib/ExtUtils/Manifest.pm
Criterion Covered Total %
statement 254 315 80.6
branch 102 186 54.8
condition 19 49 38.7
subroutine 32 37 86.4
pod 10 15 66.6
total 417 602 69.2


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