1 package ExtUtils::Manifest;
10 use vars qw($VERSION @ISA @EXPORT_OK
11 $Is_VMS $Debug $Verbose $Quiet $MANIFEST $found);
13 $VERSION = substr(q$Revision: 1.33 $, 10);
15 @EXPORT_OK = ('mkmanifest', 'manicheck', 'fullcheck', 'filecheck',
16 'skipcheck', 'maniread', 'manicopy');
18 $Is_VMS = $^O eq 'VMS';
19 if ($Is_VMS) { require File::Basename }
24 $MANIFEST = 'MANIFEST';
26 # Really cool fix from Ilya :)
27 unless (defined $Config{d_link}) {
34 my $read = maniread() or $manimiss++;
35 $read = {} if $manimiss;
37 rename $MANIFEST, "$MANIFEST.bak" unless $manimiss;
38 open M, ">$MANIFEST" or die "Could not open $MANIFEST: $!";
39 my $matches = _maniskip();
40 my $found = manifind();
41 my($key,$val,$file,%all);
42 %all = (%$found, %$read);
43 $all{$MANIFEST} = ($Is_VMS ? "$MANIFEST\t\t" : '') . 'This list of files'
44 if $manimiss; # add new MANIFEST to known file list
45 foreach $file (sort keys %all) {
46 next if &$matches($file);
48 warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
50 my $text = $all{$file};
51 ($file,$text) = split(/\s+/,$text,2) if $Is_VMS && $text;
52 my $tabs = (5 - (length($file)+1)/8);
53 $tabs = 1 if $tabs < 1;
54 $tabs = 0 unless $text;
55 print M $file, "\t" x $tabs, $text, "\n";
62 find(sub {return if -d $_;
63 (my $name = $File::Find::name) =~ s|./||;
64 warn "Debug: diskfile $name\n" if $Debug;
65 $name =~ s#(.*)\.$#\L$1# if $Is_VMS;
66 $found->{$name} = "";}, ".");
75 return @{(_manicheck(1))[0]};
79 return @{(_manicheck(2))[1]};
88 my $read = maniread();
89 my $found = manifind();
91 my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
92 my(@missfile,@missentry);
94 foreach $file (sort keys %$read){
95 warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
98 $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
99 $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
101 unless ( exists $found->{$file} ) {
102 warn "No such file: $file\n" unless $Quiet;
103 push @missfile, $file;
109 my $matches = _maniskip();
110 my $skipwarn = $arg & 4;
111 foreach $file (sort keys %$found){
112 if (&$matches($file)){
113 warn "Skipping $file\n" if $skipwarn;
116 warn "Debug: manicheck checking from disk $file\n" if $Debug;
117 unless ( exists $read->{$file} ) {
118 warn "Not in $MANIFEST: $file\n" unless $Quiet;
119 push @missentry, $file;
123 (\@missfile,\@missentry);
128 $mfile ||= $MANIFEST;
131 unless (open M, $mfile){
141 my($base,$dir) = File::Basename::fileparse($file);
142 # Resolve illegal file specifications in the same way as tar
144 my(@pieces) = split(/\./,$base);
145 if (@pieces > 2) { $base = shift(@pieces) . '.' . join('_',@pieces); }
146 my $okfile = "$dir$base";
147 warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
148 $read->{"\L$okfile"}=$_;
150 else { /^(\S+)\s*(.*)/ and $read->{$1}=$2; }
156 # returns an anonymous sub that decides if an argument matches
159 my $matches = sub {0};
161 $mfile ||= "$MANIFEST.SKIP";
163 return $matches unless -f $mfile;
164 open M, $mfile or return $matches;
172 my $opts = $Is_VMS ? 'oi ' : 'o ';
173 my $sub = "\$matches = "
174 . "sub { my(\$arg)=\@_; return 1 if "
175 . join (" || ", (map {s!/!\\/!g; "\$arg =~ m/$_/$opts"} @skip), 0)
178 print "Debug: $sub\n" if $Debug;
183 my($read,$target,$how)=@_;
184 croak "manicopy() called without target argument" unless defined $target;
187 require File::Basename;
189 $target = VMS::Filespec::unixify($target) if $Is_VMS;
190 File::Path::mkpath([ $target ],1,$Is_VMS ? undef : 0755);
191 foreach $file (keys %$read){
192 $file = VMS::Filespec::unixify($file) if $Is_VMS;
193 if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
194 my $dir = File::Basename::dirname($file);
195 $dir = VMS::Filespec::unixify($dir) if $Is_VMS;
196 File::Path::mkpath(["$target/$dir"],1,$Is_VMS ? undef : 0755);
198 cp_if_diff($file, "$target/$file", $how);
203 my($from, $to, $how)=@_;
204 -f $from or carp "$0: $from not found";
207 open(F,$from) or croak "Can't read $from: $!\n";
209 while (<F>) { $diff++,last if $_ ne <T>; }
210 $diff++ unless eof(T);
217 unlink($to) or confess "unlink $to: $!";
220 best($from,$to), last STRICT_SWITCH if $how eq 'best';
221 cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
222 ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
223 croak("ExtUtils::Manifest::cp_if_diff " .
224 "called with illegal how argument [$how]. " .
225 "Legal values are 'best', 'cp', and 'ln'.");
231 my ($srcFile, $dstFile) = @_;
232 my ($perm,$access,$mod) = (stat $srcFile)[2,8,9];
233 copy($srcFile,$dstFile);
234 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
236 chmod( 0444 | ( $perm & 0111 ? 0111 : 0 ), $dstFile );
240 my ($srcFile, $dstFile) = @_;
241 return &cp if $Is_VMS;
242 link($srcFile, $dstFile);
243 local($_) = $dstFile; # chmod a+r,go-w+X (except "X" only applies to u=x)
244 my $mode= 0444 | (stat)[2] & 0700;
245 if (! chmod( $mode | ( $mode & 0100 ? 0111 : 0 ), $_ )) {
253 my ($srcFile, $dstFile) = @_;
255 cp($srcFile, $dstFile);
257 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
267 ExtUtils::Manifest - utilities to write and check a MANIFEST file
271 require ExtUtils::Manifest;
273 ExtUtils::Manifest::mkmanifest;
275 ExtUtils::Manifest::manicheck;
277 ExtUtils::Manifest::filecheck;
279 ExtUtils::Manifest::fullcheck;
281 ExtUtils::Manifest::skipcheck;
283 ExtUtils::Manifest::manifind();
285 ExtUtils::Manifest::maniread($file);
287 ExtUtils::Manifest::manicopy($read,$target,$how);
291 mkmanifest() writes all files in and below the current directory to a
292 file named in the global variable $ExtUtils::Manifest::MANIFEST (which
293 defaults to C<MANIFEST>) in the current directory. It works similar to
297 but in doing so checks each line in an existing C<MANIFEST> file and
298 includes any comments that are found in the existing C<MANIFEST> file
299 in the new one. Anything between white space and an end of line within
300 a C<MANIFEST> file is considered to be a comment. Filenames and
301 comments are separated by one or more TAB characters in the
302 output. All files that match any regular expression in a file
303 C<MANIFEST.SKIP> (if such a file exists) are ignored.
305 manicheck() checks if all the files within a C<MANIFEST> in the
306 current directory really do exist. It only reports discrepancies and
307 exits silently if MANIFEST and the tree below the current directory
310 filecheck() finds files below the current directory that are not
311 mentioned in the C<MANIFEST> file. An optional file C<MANIFEST.SKIP>
312 will be consulted. Any file matching a regular expression in such a
313 file will not be reported as missing in the C<MANIFEST> file.
315 fullcheck() does both a manicheck() and a filecheck().
317 skipcheck() lists all the files that are skipped due to your
318 C<MANIFEST.SKIP> file.
320 manifind() returns a hash reference. The keys of the hash are the
321 files found below the current directory.
323 maniread($file) reads a named C<MANIFEST> file (defaults to
324 C<MANIFEST> in the current directory) and returns a HASH reference
325 with files being the keys and comments being the values of the HASH.
326 Blank lines and lines which start with C<#> in the C<MANIFEST> file
329 C<manicopy($read,$target,$how)> copies the files that are the keys in
330 the HASH I<%$read> to the named target directory. The HASH reference
331 $read is typically returned by the maniread() function. This
332 function is useful for producing a directory tree identical to the
333 intended distribution tree. The third parameter $how can be used to
334 specify a different methods of "copying". Valid values are C<cp>,
335 which actually copies the files, C<ln> which creates hard links, and
336 C<best> which mostly links the files but copies any symbolic link to
337 make a tree without any symbolic link. Best is the default.
341 The file MANIFEST.SKIP may contain regular expressions of files that
342 should be ignored by mkmanifest() and filecheck(). The regular
343 expressions should appear one on each line. Blank lines and lines
344 which start with C<#> are skipped. Use C<\#> if you need a regular
345 expression to start with a sharp character. A typical example:
358 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
359 C<&maniread>, and C<&manicopy> are exportable.
361 =head1 GLOBAL VARIABLES
363 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
364 results in both a different C<MANIFEST> and a different
365 C<MANIFEST.SKIP> file. This is useful if you want to maintain
366 different distributions for different audiences (say a user version
367 and a developer version including RCS).
369 C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
370 all functions act silently.
374 All diagnostic output is sent to C<STDERR>.
378 =item C<Not in MANIFEST:> I<file>
380 is reported if a file is found, that is missing in the C<MANIFEST>
381 file which is excluded by a regular expression in the file
384 =item C<No such file:> I<file>
386 is reported if a file mentioned in a C<MANIFEST> file does not
389 =item C<MANIFEST:> I<$!>
391 is reported if C<MANIFEST> could not be opened.
393 =item C<Added to MANIFEST:> I<file>
395 is reported by mkmanifest() if $Verbose is set and a file is added
396 to MANIFEST. $Verbose is set to 1 by default.
402 L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
406 Andreas Koenig <F<koenig@franz.ww.TU-Berlin.DE>>