summaryrefslogtreecommitdiff
path: root/Porting/patchls
diff options
context:
space:
mode:
Diffstat (limited to 'Porting/patchls')
-rw-r--r--Porting/patchls101
1 files changed, 73 insertions, 28 deletions
diff --git a/Porting/patchls b/Porting/patchls
index b3e968de4b..f4de529f46 100644
--- a/Porting/patchls
+++ b/Porting/patchls
@@ -18,18 +18,19 @@ use Text::Tabs qw(expand unexpand);
use strict;
sub usage {
-die qq{
-
+die q{
patchls [options] patchfile [ ... ]
- -i Invert: for each patched file list which patch files patch it
- -h no filename headers (like grep), only the listing
- -l no listing (like grep), only the filename headers
- -c Categorise the patch and sort by category (perl specific)
- -m print formatted Meta-information (Subject,From,Msg-ID etc)
- -p N strip N levels of directory Prefix (like patch), else automatic
- -v more verbose (-d for noisy debugging)
-
+ -i Invert: for each patched file list which patch files patch it.
+ -h no filename headers (like grep), only the listing.
+ -l no listing (like grep), only the filename headers.
+ -c Categorise the patch and sort by category (perl specific).
+ -m print formatted Meta-information (Subject,From,Msg-ID etc).
+ -p N strip N levels of directory Prefix (like patch), else automatic.
+ -v more verbose (-d for noisy debugging).
+ -f F only list patches which patch files matching regexp F
+ (F has $ appended unless it contains a /).
+ -I just gather and display summary Information about the patches.
}
}
@@ -43,20 +44,23 @@ $::opt_i = 0;
$::opt_h = 0;
$::opt_l = 0;
$::opt_c = 0;
+$::opt_f = '';
+$::opt_I = 0;
usage unless @ARGV;
-getopts("mihlvcp:") or usage;
+getopts("mihlvcp:f:I") or usage;
my %cat_title = (
- 'TEST' => 'TESTS',
+ 'BUILD' => 'BUILD PROCESS',
+ 'CORE' => 'CORE LANGUAGE',
'DOC' => 'DOCUMENTATION',
- 'UTIL' => 'UTILITIES',
- 'PORT' => 'PORTABILITY',
'LIB' => 'LIBRARY AND EXTENSIONS',
- 'CORE' => 'CORE LANGUAGE',
- 'BUILD' => 'BUILD PROCESS',
- 'OTHER' => 'OTHER',
+ 'PORT1' => 'PORTABILITY - WIN32',
+ 'PORT2' => 'PORTABILITY - OTHER',
+ 'TEST' => 'TESTS',
+ 'UTIL' => 'UTILITIES',
+ 'OTHER' => 'OTHER CHANGES',
);
my %ls;
@@ -94,10 +98,10 @@ foreach my $argv (@ARGV) {
unless (/^([-+*]{3}) / || /^(Index):/) {
# not an interesting patch line but possibly meta-information
next unless $::opt_m;
- $ls->{From}{$1}=1 if /^From: (.*\S)/i;
- $ls->{Title}{$1}=1 if /^Subject: (?:Re: )?(.*\S)/i;
- $ls->{'Msg-ID'}{$1}=1 if /^Message-Id: (.*\S)/i;
- $ls->{Date}{$1}=1 if /^Date: (.*\S)/i;
+ $ls->{From}{$1}=1 if /^From:\s+(.*\S)/i;
+ $ls->{Title}{$1}=1 if /^Subject:\s+(?:Re: )?(.*\S)/i;
+ $ls->{'Msg-ID'}{$1}=1 if /^Message-Id:\s+(.*\S)/i;
+ $ls->{Date}{$1}=1 if /^Date:\s+(.*\S)/i;
next;
}
$type = $1;
@@ -141,6 +145,41 @@ my @ls = sort {
$a->{category} cmp $b->{category} || $a->{in} cmp $b->{in}
} values %ls;
+if ($::opt_f) { # filter out patches based on -f <regexp>
+ my $out;
+ $::opt_f .= '$' unless $::opt_f =~ m:/:;
+ @ls = grep {
+ my @out = keys %{$_->{out}};
+ my $match = 0;
+ for $out (@out) {
+ ++$match if $out =~ m/$::opt_f/o;
+ }
+ $match;
+ } @ls;
+}
+
+if ($::opt_I) {
+ my $n_patches = 0;
+ my($in,$out);
+ my %all_out;
+ foreach $in (@ls) {
+ next unless $in->{is_in};
+ ++$n_patches;
+ my @outs = keys %{$in->{out}};
+ @all_out{@outs} = ($in->{in}) x @outs;
+ }
+ my @all_out = sort keys %all_out;
+ my @missing = grep { ! -f $_ } @all_out;
+ print "$n_patches patch files patch ".@all_out." files (".@missing." missing)\n";
+ if ($::opt_v and @missing) {
+ print "Missing files:\n";
+ foreach $out (@missing) {
+ printf " %-20s\t%s\n", $out, $all_out{$out};
+ }
+ }
+ exit 0+@missing;
+}
+
unless ($::opt_c and $::opt_m) {
foreach $ls (@ls) {
next unless ($::opt_i) ? $ls->{is_out} : $ls->{is_in};
@@ -151,7 +190,8 @@ else {
my $c = '';
foreach $ls (@ls) {
next unless ($::opt_i) ? $ls->{is_out} : $ls->{is_in};
- print "\n $cat_title{$ls->{category}}\n" if $ls->{category} ne $c;
+ print "\n ------ $cat_title{$ls->{category}} ------\n"
+ if $ls->{category} ne $c;
$c = $ls->{category};
unless ($::opt_i) {
list_files_by_patch($ls);
@@ -194,6 +234,8 @@ sub add_file {
sub trim_name { # reduce/tidy file paths from diff lines
my $name = shift;
$name = "$name ($in)" if $name eq "/dev/null";
+ $name =~ s:\\:/:g; # adjust windows paths
+ $name =~ s://:/:g; # simplify (and make win \\share into absolute path)
if (defined $::opt_p) {
# strip on -p levels of directory prefix
my $dc = $::opt_p;
@@ -202,7 +244,7 @@ sub trim_name { # reduce/tidy file paths from diff lines
else { # try to strip off leading path to perl directory
# if absolute path, strip down to any *perl* directory first
$name =~ s:^/.*?perl.*?/::i;
- $name =~ s:.*perl[-_]?5\.[-_a-z0-9.]+/::i;
+ $name =~ s:.*perl[-_]?5?[._]?[-_a-z0-9.+]*/::i;
$name =~ s:^\./::;
}
return $name;
@@ -239,7 +281,9 @@ sub list_files_by_patch {
sub my_wrap {
- return expand(wrap(@_));
+ my $txt = eval { expand(wrap(@_)) }; # die's on long lines!
+ return $txt unless $@;
+ return expand("@_");
}
@@ -253,17 +297,18 @@ sub categorize_files {
$c{TEST} += 5,next if m:^t/:;
$c{DOC} += 5,next if m:^pod/:;
$c{UTIL} += 10,next if m:^(utils|x2p|h2pl)/:;
- $c{PORT} += 15,next
- if m:^(cygwin32|os2|plan9|qnx|vms|win32)/:
+ $c{PORT1}+= 15,next if m:^win32:;
+ $c{PORT2} += 15,next
+ if m:^(cygwin32|os2|plan9|qnx|vms)/:
or m:^(hints|Porting|ext/DynaLoader)/:
or m:^README\.:;
$c{LIB} += 10,next
if m:^(lib|ext)/:;
$c{'CORE'} += 15,next
- if m:^[^/]+[\._]([chH]|sym)$:;
+ if m:^[^/]+[\._]([chH]|sym|pl)$:;
$c{BUILD} += 10,next
if m:^[A-Z]+$: or m:^[^/]+\.SH$:
- or m:^(install|configure):i;
+ or m:^(install|configure|configpm):i;
print "Couldn't categorise $_\n" if $::opt_v;
$c{OTHER} += 1;
}