Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perl-5.8.0 / lib / 5.8.0 / ExtUtils / Manifest.pm
CommitLineData
86530b38
AT
1package ExtUtils::Manifest;
2
3require Exporter;
4use Config;
5use File::Basename;
6use File::Copy 'copy';
7use File::Find;
8use File::Spec;
9use Carp;
10use strict;
11
12use vars qw($VERSION @ISA @EXPORT_OK
13 $Is_MacOS $Is_VMS
14 $Debug $Verbose $Quiet $MANIFEST $DEFAULT_MSKIP);
15
16$VERSION = 1.43;
17@ISA=('Exporter');
18@EXPORT_OK = qw(mkmanifest
19 manicheck filecheck fullcheck skipcheck
20 manifind maniread manicopy maniadd
21 );
22
23$Is_MacOS = $^O eq 'MacOS';
24$Is_VMS = $^O eq 'VMS';
25require VMS::Filespec if $Is_VMS;
26
27$Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
28$Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
29 $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
30$Quiet = 0;
31$MANIFEST = 'MANIFEST';
32
33$DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
34
35
36=head1 NAME
37
38ExtUtils::Manifest - utilities to write and check a MANIFEST file
39
40=head1 SYNOPSIS
41
42 use ExtUtils::Manifest qw(...funcs to import...);
43
44 mkmanifest();
45
46 my @missing_files = manicheck;
47 my @skipped = skipcheck;
48 my @extra_files = filecheck;
49 my($missing, $extra) = fullcheck;
50
51 my $found = manifind();
52
53 my $manifest = maniread();
54
55 manicopy($read,$target);
56
57 maniadd({$file => $comment, ...});
58
59
60=head1 DESCRIPTION
61
62=head2 Functions
63
64ExtUtils::Manifest exports no functions by default. The following are
65exported on request
66
67=over 4
68
69=item mkmanifest
70
71 mkmanifest();
72
73Writes all files in and below the current directory to your F<MANIFEST>.
74It works similar to
75
76 find . > MANIFEST
77
78All files that match any regular expression in a file F<MANIFEST.SKIP>
79(if it exists) are ignored.
80
81Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>. Lines
82from the old F<MANIFEST> file is preserved, including any comments
83that are found in the existing F<MANIFEST> file in the new one.
84
85=cut
86
87sub _sort {
88 return sort { lc $a cmp lc $b } @_;
89}
90
91sub mkmanifest {
92 my $manimiss = 0;
93 my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
94 $read = {} if $manimiss;
95 local *M;
96 rename $MANIFEST, "$MANIFEST.bak" unless $manimiss;
97 open M, ">$MANIFEST" or die "Could not open $MANIFEST: $!";
98 my $skip = _maniskip();
99 my $found = manifind();
100 my($key,$val,$file,%all);
101 %all = (%$found, %$read);
102 $all{$MANIFEST} = ($Is_VMS ? "$MANIFEST\t\t" : '') . 'This list of files'
103 if $manimiss; # add new MANIFEST to known file list
104 foreach $file (_sort keys %all) {
105 if ($skip->($file)) {
106 # Policy: only remove files if they're listed in MANIFEST.SKIP.
107 # Don't remove files just because they don't exist.
108 warn "Removed from $MANIFEST: $file\n" if $Verbose and exists $read->{$file};
109 next;
110 }
111 if ($Verbose){
112 warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
113 }
114 my $text = $all{$file};
115 ($file,$text) = split(/\s+/,$text,2) if $Is_VMS && $text;
116 $file = _unmacify($file);
117 my $tabs = (5 - (length($file)+1)/8);
118 $tabs = 1 if $tabs < 1;
119 $tabs = 0 unless $text;
120 print M $file, "\t" x $tabs, $text, "\n";
121 }
122 close M;
123}
124
125# Geez, shouldn't this use File::Spec or File::Basename or something?
126# Why so careful about dependencies?
127sub clean_up_filename {
128 my $filename = shift;
129 $filename =~ s|^\./||;
130 $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
131 return $filename;
132}
133
134
135=item manifind
136
137 my $found = manifind();
138
139returns a hash reference. The keys of the hash are the files found
140below the current directory.
141
142=cut
143
144sub manifind {
145 my $p = shift || {};
146 my $found = {};
147
148 my $wanted = sub {
149 my $name = clean_up_filename($File::Find::name);
150 warn "Debug: diskfile $name\n" if $Debug;
151 return if -d $_;
152
153 if( $Is_VMS ) {
154 $name =~ s#(.*)\.$#\L$1#;
155 $name = uc($name) if $name =~ /^MANIFEST(\.SKIP)?$/i;
156 }
157 $found->{$name} = "";
158 };
159
160 # We have to use "$File::Find::dir/$_" in preprocess, because
161 # $File::Find::name is unavailable.
162 # Also, it's okay to use / here, because MANIFEST files use Unix-style
163 # paths.
164 find({wanted => $wanted},
165 $Is_MacOS ? ":" : ".");
166
167 return $found;
168}
169
170
171=item manicheck
172
173 my @missing_files = manicheck();
174
175checks if all the files within a C<MANIFEST> in the current directory
176really do exist. If C<MANIFEST> and the tree below the current
177directory are in sync it silently returns an empty list.
178Otherwise it returns a list of files which are listed in the
179C<MANIFEST> but missing from the directory, and by default also
180outputs these names to STDERR.
181
182=cut
183
184sub manicheck {
185 return _check_files();
186}
187
188
189=item filecheck
190
191 my @extra_files = filecheck();
192
193finds files below the current directory that are not mentioned in the
194C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
195consulted. Any file matching a regular expression in such a file will
196not be reported as missing in the C<MANIFEST> file. The list of any
197extraneous files found is returned, and by default also reported to
198STDERR.
199
200=cut
201
202sub filecheck {
203 return _check_manifest();
204}
205
206
207=item fullcheck
208
209 my($missing, $extra) = fullcheck();
210
211does both a manicheck() and a filecheck(), returning then as two array
212refs.
213
214=cut
215
216sub fullcheck {
217 return [_check_files()], [_check_manifest()];
218}
219
220
221=item skipcheck
222
223 my @skipped = skipcheck();
224
225lists all the files that are skipped due to your C<MANIFEST.SKIP>
226file.
227
228=cut
229
230sub skipcheck {
231 my($p) = @_;
232 my $found = manifind();
233 my $matches = _maniskip();
234
235 my @skipped = ();
236 foreach my $file (_sort keys %$found){
237 if (&$matches($file)){
238 warn "Skipping $file\n";
239 push @skipped, $file;
240 next;
241 }
242 }
243
244 return @skipped;
245}
246
247
248sub _check_files {
249 my $p = shift;
250 my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
251 my $read = maniread() || {};
252 my $found = manifind($p);
253
254 my(@missfile) = ();
255 foreach my $file (_sort keys %$read){
256 warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
257 if ($dosnames){
258 $file = lc $file;
259 $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
260 $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
261 }
262 unless ( exists $found->{$file} ) {
263 warn "No such file: $file\n" unless $Quiet;
264 push @missfile, $file;
265 }
266 }
267
268 return @missfile;
269}
270
271
272sub _check_manifest {
273 my($p) = @_;
274 my $read = maniread() || {};
275 my $found = manifind($p);
276 my $skip = _maniskip();
277
278 my @missentry = ();
279 foreach my $file (_sort keys %$found){
280 next if $skip->($file);
281 warn "Debug: manicheck checking from disk $file\n" if $Debug;
282 unless ( exists $read->{$file} ) {
283 my $canon = $Is_MacOS ? "\t" . _unmacify($file) : '';
284 warn "Not in $MANIFEST: $file$canon\n" unless $Quiet;
285 push @missentry, $file;
286 }
287 }
288
289 return @missentry;
290}
291
292
293=item maniread
294
295 my $manifest = maniread();
296 my $manifest = maniread($manifest_file);
297
298reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
299directory) and returns a HASH reference with files being the keys and
300comments being the values of the HASH. Blank lines and lines which
301start with C<#> in the C<MANIFEST> file are discarded.
302
303=cut
304
305sub maniread {
306 my ($mfile) = @_;
307 $mfile ||= $MANIFEST;
308 my $read = {};
309 local *M;
310 unless (open M, $mfile){
311 warn "$mfile: $!";
312 return $read;
313 }
314 local $_;
315 while (<M>){
316 chomp;
317 next if /^\s*#/;
318
319 my($file, $comment) = /^(\S+)\s*(.*)/;
320 next unless $file;
321
322 if ($Is_MacOS) {
323 $file = _macify($file);
324 $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
325 }
326 elsif ($Is_VMS) {
327 require File::Basename;
328 my($base,$dir) = File::Basename::fileparse($file);
329 # Resolve illegal file specifications in the same way as tar
330 $dir =~ tr/./_/;
331 my(@pieces) = split(/\./,$base);
332 if (@pieces > 2) { $base = shift(@pieces) . '.' . join('_',@pieces); }
333 my $okfile = "$dir$base";
334 warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
335 $file = $okfile;
336 $file = lc($file) unless $file =~ /^MANIFEST(\.SKIP)?$/;
337 }
338
339 $read->{$file} = $comment;
340 }
341 close M;
342 $read;
343}
344
345# returns an anonymous sub that decides if an argument matches
346sub _maniskip {
347 my @skip ;
348 my $mfile = "$MANIFEST.SKIP";
349 local(*M,$_);
350 open M, $mfile or open M, $DEFAULT_MSKIP or return sub {0};
351 while (<M>){
352 chomp;
353 next if /^#/;
354 next if /^\s*$/;
355 push @skip, _macify($_);
356 }
357 close M;
358 my $opts = $Is_VMS ? '(?i)' : '';
359
360 # Make sure each entry is isolated in its own parentheses, in case
361 # any of them contain alternations
362 my $regex = join '|', map "(?:$_)", @skip;
363
364 return sub { $_[0] =~ qr{$opts$regex} };
365}
366
367=item manicopy
368
369 manicopy(\%src, $dest_dir);
370 manicopy(\%src, $dest_dir, $how);
371
372Copies the files that are the keys in %src to the $dest_dir. %src is
373typically returned by the maniread() function.
374
375 manicopy( maniread(), $dest_dir );
376
377This function is useful for producing a directory tree identical to the
378intended distribution tree.
379
380$how can be used to specify a different methods of "copying". Valid
381values are C<cp>, which actually copies the files, C<ln> which creates
382hard links, and C<best> which mostly links the files but copies any
383symbolic link to make a tree without any symbolic link. C<cp> is the
384default.
385
386=cut
387
388sub manicopy {
389 my($read,$target,$how)=@_;
390 croak "manicopy() called without target argument" unless defined $target;
391 $how ||= 'cp';
392 require File::Path;
393 require File::Basename;
394
395 $target = VMS::Filespec::unixify($target) if $Is_VMS;
396 File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
397 foreach my $file (keys %$read){
398 if ($Is_MacOS) {
399 if ($file =~ m!:!) {
400 my $dir = _maccat($target, $file);
401 $dir =~ s/[^:]+$//;
402 File::Path::mkpath($dir,1,0755);
403 }
404 cp_if_diff($file, _maccat($target, $file), $how);
405 } else {
406 $file = VMS::Filespec::unixify($file) if $Is_VMS;
407 if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
408 my $dir = File::Basename::dirname($file);
409 $dir = VMS::Filespec::unixify($dir) if $Is_VMS;
410 File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
411 }
412 cp_if_diff($file, "$target/$file", $how);
413 }
414 }
415}
416
417sub cp_if_diff {
418 my($from, $to, $how)=@_;
419 -f $from or carp "$0: $from not found";
420 my($diff) = 0;
421 local(*F,*T);
422 open(F,"< $from\0") or die "Can't read $from: $!\n";
423 if (open(T,"< $to\0")) {
424 local $_;
425 while (<F>) { $diff++,last if $_ ne <T>; }
426 $diff++ unless eof(T);
427 close T;
428 }
429 else { $diff++; }
430 close F;
431 if ($diff) {
432 if (-e $to) {
433 unlink($to) or confess "unlink $to: $!";
434 }
435 STRICT_SWITCH: {
436 best($from,$to), last STRICT_SWITCH if $how eq 'best';
437 cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
438 ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
439 croak("ExtUtils::Manifest::cp_if_diff " .
440 "called with illegal how argument [$how]. " .
441 "Legal values are 'best', 'cp', and 'ln'.");
442 }
443 }
444}
445
446sub cp {
447 my ($srcFile, $dstFile) = @_;
448 my ($access,$mod) = (stat $srcFile)[8,9];
449
450 copy($srcFile,$dstFile);
451 utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
452 _manicopy_chmod($dstFile);
453}
454
455
456sub ln {
457 my ($srcFile, $dstFile) = @_;
458 return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
459 link($srcFile, $dstFile);
460
461 unless( _manicopy_chmod($dstFile) ) {
462 unlink $dstFile;
463 return;
464 }
465 1;
466}
467
468# 1) Strip off all group and world permissions.
469# 2) Let everyone read it.
470# 3) If the owner can execute it, everyone can.
471sub _manicopy_chmod {
472 my($file) = shift;
473
474 my $perm = 0444 | (stat $file)[2] & 0700;
475 chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $file );
476}
477
478sub best {
479 my ($srcFile, $dstFile) = @_;
480 if (!$Config{d_link} or -l $srcFile) {
481 cp($srcFile, $dstFile);
482 } else {
483 ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
484 }
485}
486
487sub _macify {
488 my($file) = @_;
489
490 return $file unless $Is_MacOS;
491
492 $file =~ s|^\./||;
493 if ($file =~ m|/|) {
494 $file =~ s|/+|:|g;
495 $file = ":$file";
496 }
497
498 $file;
499}
500
501sub _maccat {
502 my($f1, $f2) = @_;
503
504 return "$f1/$f2" unless $Is_MacOS;
505
506 $f1 .= ":$f2";
507 $f1 =~ s/([^:]:):/$1/g;
508 return $f1;
509}
510
511sub _unmacify {
512 my($file) = @_;
513
514 return $file unless $Is_MacOS;
515
516 $file =~ s|^:||;
517 $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
518 $file =~ y|:|/|;
519
520 $file;
521}
522
523
524=item maniadd
525
526 maniadd({ $file => $comment, ...});
527
528Adds an entry to an existing F<MANIFEST> unless its already there.
529
530$file will be normalized (ie. Unixified). B<UNIMPLEMENTED>
531
532=cut
533
534sub maniadd {
535 my($additions) = shift;
536
537 _normalize($additions);
538 _fix_manifest($MANIFEST);
539
540 my $manifest = maniread();
541 my @needed = grep { !exists $manifest->{$_} } keys %$additions;
542 return 1 unless @needed;
543
544 open(MANIFEST, ">>$MANIFEST") or
545 die "maniadd() could not open $MANIFEST: $!";
546
547 foreach my $file (_sort @needed) {
548 my $comment = $additions->{$file} || '';
549 printf MANIFEST "%-40s %s\n", $file, $comment;
550 }
551 close MANIFEST or die "Error closing $MANIFEST: $!";
552
553 return 1;
554}
555
556
557# Sometimes MANIFESTs are missing a trailing newline. Fix this.
558sub _fix_manifest {
559 my $manifest_file = shift;
560
561 open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
562
563 # Yes, we should be using seek(), but I'd like to avoid loading POSIX
564 # to get SEEK_*
565 my @manifest = <MANIFEST>;
566 close MANIFEST;
567
568 unless( $manifest[-1] =~ /\n\z/ ) {
569 open MANIFEST, ">>$MANIFEST" or die "Could not open $MANIFEST: $!";
570 print MANIFEST "\n";
571 close MANIFEST;
572 }
573}
574
575
576# UNIMPLEMENTED
577sub _normalize {
578 return;
579}
580
581
582=back
583
584=head2 MANIFEST
585
586Anything between white space and an end of line within a C<MANIFEST>
587file is considered to be a comment. Filenames and comments are
588separated by one or more TAB characters in the output.
589
590
591=head2 MANIFEST.SKIP
592
593The file MANIFEST.SKIP may contain regular expressions of files that
594should be ignored by mkmanifest() and filecheck(). The regular
595expressions should appear one on each line. Blank lines and lines
596which start with C<#> are skipped. Use C<\#> if you need a regular
597expression to start with a sharp character. A typical example:
598
599 # Version control files and dirs.
600 \bRCS\b
601 \bCVS\b
602 ,v$
603 \B\.svn\b
604
605 # Makemaker generated files and dirs.
606 ^MANIFEST\.
607 ^Makefile$
608 ^blib/
609 ^MakeMaker-\d
610
611 # Temp, old and emacs backup files.
612 ~$
613 \.old$
614 ^#.*#$
615 ^\.#
616
617If no MANIFEST.SKIP file is found, a default set of skips will be
618used, similar to the example above. If you want nothing skipped,
619simply make an empty MANIFEST.SKIP file.
620
621
622=head2 EXPORT_OK
623
624C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
625C<&maniread>, and C<&manicopy> are exportable.
626
627=head2 GLOBAL VARIABLES
628
629C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
630results in both a different C<MANIFEST> and a different
631C<MANIFEST.SKIP> file. This is useful if you want to maintain
632different distributions for different audiences (say a user version
633and a developer version including RCS).
634
635C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
636all functions act silently.
637
638C<$ExtUtils::Manifest::Debug> defaults to 0. If set to a true value,
639or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
640produced.
641
642=head1 DIAGNOSTICS
643
644All diagnostic output is sent to C<STDERR>.
645
646=over 4
647
648=item C<Not in MANIFEST:> I<file>
649
650is reported if a file is found which is not in C<MANIFEST>.
651
652=item C<Skipping> I<file>
653
654is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
655
656=item C<No such file:> I<file>
657
658is reported if a file mentioned in a C<MANIFEST> file does not
659exist.
660
661=item C<MANIFEST:> I<$!>
662
663is reported if C<MANIFEST> could not be opened.
664
665=item C<Added to MANIFEST:> I<file>
666
667is reported by mkmanifest() if $Verbose is set and a file is added
668to MANIFEST. $Verbose is set to 1 by default.
669
670=back
671
672=head1 ENVIRONMENT
673
674=over 4
675
676=item B<PERL_MM_MANIFEST_DEBUG>
677
678Turns on debugging
679
680=back
681
682=head1 SEE ALSO
683
684L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
685
686=head1 AUTHOR
687
688Andreas Koenig C<andreas.koenig@anima.de>
689
690Currently maintained by Michael G Schwern C<schwern@pobox.com>
691
692=cut
693
6941;