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}) {
33 my $read = maniread() or $manimiss++;
34 $read = {} if $manimiss;
36 rename $MANIFEST, "$MANIFEST.bak" unless $manimiss;
37 open M, ">$MANIFEST" or die "Could not open $MANIFEST: $!";
38 my $matches = _maniskip();
39 my $found = manifind();
40 my($key,$val,$file,%all);
41 %all = (%$found, %$read);
42 $all{$MANIFEST} = ($Is_VMS ? "$MANIFEST\t\t" : '') . 'This list of files'
43 if $manimiss; # add new MANIFEST to known file list
44 foreach $file (sort keys %all) {
45 next if &$matches($file);
47 warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
49 my $text = $all{$file};
50 ($file,$text) = split(/\s+/,$text,2) if $Is_VMS && $text;
51 my $tabs = (5 - (length($file)+1)/8);
52 $tabs = 1 if $tabs < 1;
53 $tabs = 0 unless $text;
54 print M $file, "\t" x $tabs, $text, "\n";
61 find(sub {return if -d $_;
62 (my $name = $File::Find::name) =~ s|./||;
63 warn "Debug: diskfile $name\n" if $Debug;
64 $name =~ s#(.*)\.$#\L$1# if $Is_VMS;
65 $found->{$name} = "";}, ".");
74 return @{(_manicheck(1))[0]};
78 return @{(_manicheck(2))[1]};
87 my $read = maniread();
88 my $found = manifind();
90 my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
91 my(@missfile,@missentry);
93 foreach $file (sort keys %$read){
94 warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
97 $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
98 $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
100 unless ( exists $found->{$file} ) {
101 warn "No such file: $file\n" unless $Quiet;
102 push @missfile, $file;
108 my $matches = _maniskip();
109 my $skipwarn = $arg & 4;
110 foreach $file (sort keys %$found){
111 if (&$matches($file)){
112 warn "Skipping $file\n" if $skipwarn;
115 warn "Debug: manicheck checking from disk $file\n" if $Debug;
116 unless ( exists $read->{$file} ) {
117 warn "Not in $MANIFEST: $file\n" unless $Quiet;
118 push @missentry, $file;
122 (\@missfile,\@missentry);
127 $mfile ||= $MANIFEST;
130 unless (open M, $mfile){
140 my($base,$dir) = File::Basename::fileparse($file);
141 # Resolve illegal file specifications in the same way as tar
143 my(@pieces) = split(/\./,$base);
144 if (@pieces > 2) { $base = shift(@pieces) . '.' . join('_',@pieces); }
145 my $okfile = "$dir$base";
146 warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
147 $read->{"\L$okfile"}=$_;
149 else { /^(\S+)\s*(.*)/ and $read->{$1}=$2; }
155 # returns an anonymous sub that decides if an argument matches
158 my $matches = sub {0};
160 $mfile ||= "$MANIFEST.SKIP";
162 return $matches unless -f $mfile;
163 open M, $mfile or return $matches;
171 my $opts = $Is_VMS ? 'oi ' : 'o ';
172 my $sub = "\$matches = "
173 . "sub { my(\$arg)=\@_; return 1 if "
174 . join (" || ", (map {s!/!\\/!g; "\$arg =~ m/$_/$opts"} @skip), 0)
177 print "Debug: $sub\n" if $Debug;
182 my($read,$target,$how)=@_;
183 croak "manicopy() called without target argument" unless defined $target;
186 require File::Basename;
188 $target = VMS::Filespec::unixify($target) if $Is_VMS;
189 umask 0 unless $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 chmod( $mode | ( $mode & 0100 ? 0111 : 0 ), $_ );
249 my ($srcFile, $dstFile) = @_;
251 cp($srcFile, $dstFile);
253 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
263 ExtUtils::Manifest - utilities to write and check a MANIFEST file
267 C<require ExtUtils::Manifest;>
269 C<ExtUtils::Manifest::mkmanifest;>
271 C<ExtUtils::Manifest::manicheck;>
273 C<ExtUtils::Manifest::filecheck;>
275 C<ExtUtils::Manifest::fullcheck;>
277 C<ExtUtils::Manifest::skipcheck;>
279 C<ExtUtild::Manifest::manifind();>
281 C<ExtUtils::Manifest::maniread($file);>
283 C<ExtUtils::Manifest::manicopy($read,$target,$how);>
287 Mkmanifest() writes all files in and below the current directory to a
288 file named in the global variable $ExtUtils::Manifest::MANIFEST (which
289 defaults to C<MANIFEST>) in the current directory. It works similar to
293 but in doing so checks each line in an existing C<MANIFEST> file and
294 includes any comments that are found in the existing C<MANIFEST> file
295 in the new one. Anything between white space and an end of line within
296 a C<MANIFEST> file is considered to be a comment. Filenames and
297 comments are seperated by one or more TAB characters in the
298 output. All files that match any regular expression in a file
299 C<MANIFEST.SKIP> (if such a file exists) are ignored.
301 Manicheck() checks if all the files within a C<MANIFEST> in the
302 current directory really do exist. It only reports discrepancies and
303 exits silently if MANIFEST and the tree below the current directory
306 Filecheck() finds files below the current directory that are not
307 mentioned in the C<MANIFEST> file. An optional file C<MANIFEST.SKIP>
308 will be consulted. Any file matching a regular expression in such a
309 file will not be reported as missing in the C<MANIFEST> file.
311 Fullcheck() does both a manicheck() and a filecheck().
313 Skipcheck() lists all the files that are skipped due to your
314 C<MANIFEST.SKIP> file.
316 Manifind() retruns a hash reference. The keys of the hash are the
317 files found below the current directory.
319 Maniread($file) reads a named C<MANIFEST> file (defaults to
320 C<MANIFEST> in the current directory) and returns a HASH reference
321 with files being the keys and comments being the values of the HASH.
322 Blank lines and lines which start with C<#> in the C<MANIFEST> file
325 I<Manicopy($read,$target,$how)> copies the files that are the keys in
326 the HASH I<%$read> to the named target directory. The HASH reference
327 I<$read> is typically returned by the maniread() function. This
328 function is useful for producing a directory tree identical to the
329 intended distribution tree. The third parameter $how can be used to
330 specify a different methods of "copying". Valid values are C<cp>,
331 which actually copies the files, C<ln> which creates hard links, and
332 C<best> which mostly links the files but copies any symbolic link to
333 make a tree without any symbolic link. Best is the default.
337 The file MANIFEST.SKIP may contain regular expressions of files that
338 should be ignored by mkmanifest() and filecheck(). The regular
339 expressions should appear one on each line. Blank lines and lines
340 which start with C<#> are skipped. Use C<\#> if you need a regular
341 expression to start with a sharp character. A typical example:
354 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
355 C<&maniread>, and C<&manicopy> are exportable.
357 =head1 GLOBAL VARIABLES
359 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
360 results in both a different C<MANIFEST> and a different
361 C<MANIFEST.SKIP> file. This is useful if you want to maintain
362 different distributions for different audiences (say a user version
363 and a developer version including RCS).
365 C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
366 all functions act silently.
370 All diagnostic output is sent to C<STDERR>.
374 =item C<Not in MANIFEST:> I<file>
376 is reported if a file is found, that is missing in the C<MANIFEST>
377 file which is excluded by a regular expression in the file
380 =item C<No such file:> I<file>
382 is reported if a file mentioned in a C<MANIFEST> file does not
385 =item C<MANIFEST:> I<$!>
387 is reported if C<MANIFEST> could not be opened.
389 =item C<Added to MANIFEST:> I<file>
391 is reported by mkmanifest() if $Verbose is set and a file is added
392 to MANIFEST. $Verbose is set to 1 by default.
398 L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
402 Andreas Koenig <F<koenig@franz.ww.TU-Berlin.DE>>