📄 manifest.pm
字号:
package ExtUtils::Manifest;require Exporter;use Config;use File::Basename;use File::Copy 'copy';use File::Find;use File::Spec;use Carp;use strict;use vars qw($VERSION @ISA @EXPORT_OK $Is_MacOS $Is_VMS $Debug $Verbose $Quiet $MANIFEST $DEFAULT_MSKIP);$VERSION = '1.51_01';@ISA=('Exporter');@EXPORT_OK = qw(mkmanifest manicheck filecheck fullcheck skipcheck manifind maniread manicopy maniadd );$Is_MacOS = $^O eq 'MacOS';$Is_VMS = $^O eq 'VMS';require VMS::Filespec if $Is_VMS;$Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;$Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ? $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;$Quiet = 0;$MANIFEST = 'MANIFEST';$DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );=head1 NAMEExtUtils::Manifest - utilities to write and check a MANIFEST file=head1 SYNOPSIS use ExtUtils::Manifest qw(...funcs to import...); mkmanifest(); my @missing_files = manicheck; my @skipped = skipcheck; my @extra_files = filecheck; my($missing, $extra) = fullcheck; my $found = manifind(); my $manifest = maniread(); manicopy($read,$target); maniadd({$file => $comment, ...});=head1 DESCRIPTION=head2 FunctionsExtUtils::Manifest exports no functions by default. The following areexported on request=over 4=item mkmanifest mkmanifest();Writes all files in and below the current directory to your F<MANIFEST>.It works similar to find . > MANIFESTAll files that match any regular expression in a file F<MANIFEST.SKIP>(if it exists) are ignored.Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>. Linesfrom the old F<MANIFEST> file is preserved, including any commentsthat are found in the existing F<MANIFEST> file in the new one.=cutsub _sort { return sort { lc $a cmp lc $b } @_;}sub mkmanifest { my $manimiss = 0; my $read = (-r 'MANIFEST' && maniread()) or $manimiss++; $read = {} if $manimiss; local *M; my $bakbase = $MANIFEST; $bakbase =~ s/\./_/g if $Is_VMS; # avoid double dots rename $MANIFEST, "$bakbase.bak" unless $manimiss; open M, ">$MANIFEST" or die "Could not open $MANIFEST: $!"; my $skip = _maniskip(); my $found = manifind(); my($key,$val,$file,%all); %all = (%$found, %$read); $all{$MANIFEST} = ($Is_VMS ? "$MANIFEST\t\t" : '') . 'This list of files' if $manimiss; # add new MANIFEST to known file list foreach $file (_sort keys %all) { if ($skip->($file)) { # Policy: only remove files if they're listed in MANIFEST.SKIP. # Don't remove files just because they don't exist. warn "Removed from $MANIFEST: $file\n" if $Verbose and exists $read->{$file}; next; } if ($Verbose){ warn "Added to $MANIFEST: $file\n" unless exists $read->{$file}; } my $text = $all{$file}; $file = _unmacify($file); my $tabs = (5 - (length($file)+1)/8); $tabs = 1 if $tabs < 1; $tabs = 0 unless $text; print M $file, "\t" x $tabs, $text, "\n"; } close M;}# Geez, shouldn't this use File::Spec or File::Basename or something? # Why so careful about dependencies?sub clean_up_filename { my $filename = shift; $filename =~ s|^\./||; $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS; return $filename;}=item manifind my $found = manifind();returns a hash reference. The keys of the hash are the files foundbelow the current directory.=cutsub manifind { my $p = shift || {}; my $found = {}; my $wanted = sub { my $name = clean_up_filename($File::Find::name); warn "Debug: diskfile $name\n" if $Debug; return if -d $_; if( $Is_VMS ) { $name =~ s#(.*)\.$#\L$1#; $name = uc($name) if $name =~ /^MANIFEST(\.SKIP)?$/i; } $found->{$name} = ""; }; # We have to use "$File::Find::dir/$_" in preprocess, because # $File::Find::name is unavailable. # Also, it's okay to use / here, because MANIFEST files use Unix-style # paths. find({wanted => $wanted}, $Is_MacOS ? ":" : "."); return $found;}=item manicheck my @missing_files = manicheck();checks if all the files within a C<MANIFEST> in the current directoryreally do exist. If C<MANIFEST> and the tree below the currentdirectory are in sync it silently returns an empty list.Otherwise it returns a list of files which are listed in theC<MANIFEST> but missing from the directory, and by default alsooutputs these names to STDERR.=cutsub manicheck { return _check_files();}=item filecheck my @extra_files = filecheck();finds files below the current directory that are not mentioned in theC<MANIFEST> file. An optional file C<MANIFEST.SKIP> will beconsulted. Any file matching a regular expression in such a file willnot be reported as missing in the C<MANIFEST> file. The list of anyextraneous files found is returned, and by default also reported toSTDERR.=cutsub filecheck { return _check_manifest();}=item fullcheck my($missing, $extra) = fullcheck();does both a manicheck() and a filecheck(), returning then as two arrayrefs.=cutsub fullcheck { return [_check_files()], [_check_manifest()];}=item skipcheck my @skipped = skipcheck();lists all the files that are skipped due to your C<MANIFEST.SKIP>file.=cutsub skipcheck { my($p) = @_; my $found = manifind(); my $matches = _maniskip(); my @skipped = (); foreach my $file (_sort keys %$found){ if (&$matches($file)){ warn "Skipping $file\n"; push @skipped, $file; next; } } return @skipped;}sub _check_files { my $p = shift; my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0); my $read = maniread() || {}; my $found = manifind($p); my(@missfile) = (); foreach my $file (_sort keys %$read){ warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug; if ($dosnames){ $file = lc $file; $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge; $file =~ s=((\w|-)+)=substr ($1,0,8)=ge; } unless ( exists $found->{$file} ) { warn "No such file: $file\n" unless $Quiet; push @missfile, $file; } } return @missfile;}sub _check_manifest { my($p) = @_; my $read = maniread() || {}; my $found = manifind($p); my $skip = _maniskip(); my @missentry = (); foreach my $file (_sort keys %$found){ next if $skip->($file); warn "Debug: manicheck checking from disk $file\n" if $Debug; unless ( exists $read->{$file} ) { my $canon = $Is_MacOS ? "\t" . _unmacify($file) : ''; warn "Not in $MANIFEST: $file$canon\n" unless $Quiet; push @missentry, $file; } } return @missentry;}=item maniread my $manifest = maniread(); my $manifest = maniread($manifest_file);reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the currentdirectory) and returns a HASH reference with files being the keys andcomments being the values of the HASH. Blank lines and lines whichstart with C<#> in the C<MANIFEST> file are discarded.=cutsub maniread { my ($mfile) = @_; $mfile ||= $MANIFEST; my $read = {}; local *M; unless (open M, $mfile){ warn "Problem opening $mfile: $!"; return $read; } local $_; while (<M>){ chomp; next if /^\s*#/; my($file, $comment) = /^(\S+)\s*(.*)/; next unless $file; if ($Is_MacOS) { $file = _macify($file); $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge; } elsif ($Is_VMS) { require File::Basename; my($base,$dir) = File::Basename::fileparse($file); # Resolve illegal file specifications in the same way as tar $dir =~ tr/./_/; my(@pieces) = split(/\./,$base); if (@pieces > 2) { $base = shift(@pieces) . '.' . join('_',@pieces); } my $okfile = "$dir$base"; warn "Debug: Illegal name $file changed to $okfile\n" if $Debug; $file = $okfile; $file = lc($file) unless $file =~ /^MANIFEST(\.SKIP)?$/; } $read->{$file} = $comment; } close M; $read;}# returns an anonymous sub that decides if an argument matchessub _maniskip { my @skip ; my $mfile = "$MANIFEST.SKIP"; _check_mskip_directives($mfile) if -f $mfile; local(*M, $_); open M, $mfile or open M, $DEFAULT_MSKIP or return sub {0}; while (<M>){ chomp; s/\r//; next if /^#/; next if /^\s*$/; push @skip, _macify($_); } close M; return sub {0} unless (scalar @skip > 0); my $opts = $Is_VMS ? '(?i)' : ''; # Make sure each entry is isolated in its own parentheses, in case # any of them contain alternations my $regex = join '|', map "(?:$_)", @skip; return sub { $_[0] =~ qr{$opts$regex} };}# checks for the special directives# #!include_default# #!include /path/to/some/manifest.skip# in a custom MANIFEST.SKIP for, for including# the content of, respectively, the default MANIFEST.SKIP# and an external manifest.skip filesub _check_mskip_directives { my $mfile = shift; local (*M, $_); my @lines = (); my $flag = 0; unless (open M, $mfile) { warn "Problem opening $mfile: $!"; return; } while (<M>) { if (/^#!include_default\s*$/) { if (my @default = _include_mskip_file()) { push @lines, @default; warn "Debug: Including default MANIFEST.SKIP\n" if $Debug; $flag++; } next; } if (/^#!include\s+(.*)\s*$/) { my $external_file = $1; if (my @external = _include_mskip_file($external_file)) { push @lines, @external; warn "Debug: Including external $external_file\n" if $Debug; $flag++; } next; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -