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 umask 0 unless $Is_VMS;
191 File::Path::mkpath([ $target ],1,$Is_VMS ? undef : 0755);
192 foreach $file (keys %$read){
193 $file = VMS::Filespec::unixify($file) if $Is_VMS;
194 if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
195 my $dir = File::Basename::dirname($file);
196 $dir = VMS::Filespec::unixify($dir) if $Is_VMS;
197 File::Path::mkpath(["$target/$dir"],1,$Is_VMS ? undef : 0755);
199 cp_if_diff($file, "$target/$file", $how);
204 my($from, $to, $how)=@_;
205 -f $from or carp "$0: $from not found";
208 open(F,$from) or croak "Can't read $from: $!\n";
210 while (<F>) { $diff++,last if $_ ne <T>; }
211 $diff++ unless eof(T);
218 unlink($to) or confess "unlink $to: $!";
221 best($from,$to), last STRICT_SWITCH if $how eq 'best';
222 cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
223 ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
224 croak("ExtUtils::Manifest::cp_if_diff " .
225 "called with illegal how argument [$how]. " .
226 "Legal values are 'best', 'cp', and 'ln'.");
232 my ($srcFile, $dstFile) = @_;
233 my ($perm,$access,$mod) = (stat $srcFile)[2,8,9];
234 copy($srcFile,$dstFile);
235 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
237 chmod( 0444 | ( $perm & 0111 ? 0111 : 0 ), $dstFile );
241 my ($srcFile, $dstFile) = @_;
242 return &cp if $Is_VMS;
243 link($srcFile, $dstFile);
244 local($_) = $dstFile; # chmod a+r,go-w+X (except "X" only applies to u=x)
245 my $mode= 0444 | (stat)[2] & 0700;
246 if (! chmod( $mode | ( $mode & 0100 ? 0111 : 0 ), $_ )) {
254 my ($srcFile, $dstFile) = @_;
256 cp($srcFile, $dstFile);
258 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
268 ExtUtils::Manifest - utilities to write and check a MANIFEST file
272 require ExtUtils::Manifest;
274 ExtUtils::Manifest::mkmanifest;
276 ExtUtils::Manifest::manicheck;
278 ExtUtils::Manifest::filecheck;
280 ExtUtils::Manifest::fullcheck;
282 ExtUtils::Manifest::skipcheck;
284 ExtUtils::Manifest::manifind();
286 ExtUtils::Manifest::maniread($file);
288 ExtUtils::Manifest::manicopy($read,$target,$how);
292 mkmanifest() writes all files in and below the current directory to a
293 file named in the global variable $ExtUtils::Manifest::MANIFEST (which
294 defaults to C<MANIFEST>) in the current directory. It works similar to
298 but in doing so checks each line in an existing C<MANIFEST> file and
299 includes any comments that are found in the existing C<MANIFEST> file
300 in the new one. Anything between white space and an end of line within
301 a C<MANIFEST> file is considered to be a comment. Filenames and
302 comments are separated by one or more TAB characters in the
303 output. All files that match any regular expression in a file
304 C<MANIFEST.SKIP> (if such a file exists) are ignored.
306 manicheck() checks if all the files within a C<MANIFEST> in the
307 current directory really do exist. It only reports discrepancies and
308 exits silently if MANIFEST and the tree below the current directory
311 filecheck() finds files below the current directory that are not
312 mentioned in the C<MANIFEST> file. An optional file C<MANIFEST.SKIP>
313 will be consulted. Any file matching a regular expression in such a
314 file will not be reported as missing in the C<MANIFEST> file.
316 fullcheck() does both a manicheck() and a filecheck().
318 skipcheck() lists all the files that are skipped due to your
319 C<MANIFEST.SKIP> file.
321 manifind() returns a hash reference. The keys of the hash are the
322 files found below the current directory.
324 maniread($file) reads a named C<MANIFEST> file (defaults to
325 C<MANIFEST> in the current directory) and returns a HASH reference
326 with files being the keys and comments being the values of the HASH.
327 Blank lines and lines which start with C<#> in the C<MANIFEST> file
330 C<manicopy($read,$target,$how)> copies the files that are the keys in
331 the HASH I<%$read> to the named target directory. The HASH reference
332 $read is typically returned by the maniread() function. This
333 function is useful for producing a directory tree identical to the
334 intended distribution tree. The third parameter $how can be used to
335 specify a different methods of "copying". Valid values are C<cp>,
336 which actually copies the files, C<ln> which creates hard links, and
337 C<best> which mostly links the files but copies any symbolic link to
338 make a tree without any symbolic link. Best is the default.
342 The file MANIFEST.SKIP may contain regular expressions of files that
343 should be ignored by mkmanifest() and filecheck(). The regular
344 expressions should appear one on each line. Blank lines and lines
345 which start with C<#> are skipped. Use C<\#> if you need a regular
346 expression to start with a sharp character. A typical example:
359 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
360 C<&maniread>, and C<&manicopy> are exportable.
362 =head1 GLOBAL VARIABLES
364 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
365 results in both a different C<MANIFEST> and a different
366 C<MANIFEST.SKIP> file. This is useful if you want to maintain
367 different distributions for different audiences (say a user version
368 and a developer version including RCS).
370 C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
371 all functions act silently.
375 All diagnostic output is sent to C<STDERR>.
379 =item C<Not in MANIFEST:> I<file>
381 is reported if a file is found, that is missing in the C<MANIFEST>
382 file which is excluded by a regular expression in the file
385 =item C<No such file:> I<file>
387 is reported if a file mentioned in a C<MANIFEST> file does not
390 =item C<MANIFEST:> I<$!>
392 is reported if C<MANIFEST> could not be opened.
394 =item C<Added to MANIFEST:> I<file>
396 is reported by mkmanifest() if $Verbose is set and a file is added
397 to MANIFEST. $Verbose is set to 1 by default.
403 L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
407 Andreas Koenig <F<koenig@franz.ww.TU-Berlin.DE>>