#!/usr/bin/perl
use strict;
+use Getopt::Long;
+
+my($no_cvs, $failures_only, $minor_updates);
+
+&Getopt::Long::Configure('bundling');
+GetOptions(
+ 'no-cvs|n' => \$no_cvs,
+ 'failures-only|f' => \$failures_only,
+ 'minor-updates|u' => \$minor_updates,
+) or &usage;
+
+my $interesting_fuzz = $minor_updates ? '\d' : '[2-9]';
chdir('patches') if -d 'patches';
EOT
close OUT;
-print "Using CVS to update the tmp/cvsdir copy of the source.\n";
-system qq|cvs -d "$root" co -d cvsdir rsync|;
+unless ($no_cvs) {
+ print "Using CVS to update the tmp/cvsdir copy of the source.\n";
+ system qq|cvs -d "$root" co -d cvsdir rsync|;
+}
@ARGV = glob('../*.diff') unless @ARGV;
$has_dependencies = 1;
print "\nApplying dependency patch $dep...\n";
if (system("patch -d cvsdir -p0 -b -Vt -Zf <../$dep") != 0) {
- print "Unable to cleanly apply depenency patch -- skipping $diff\n";
+ print "Unable to cleanly apply dependency patch -- skipping $diff\n";
+ system "rm -f cvsdir/*.rej cvsdir/*/*.rej";
&restore_cvsdir;
next DIFF;
}
close IN;
my $default = apply_patch($diff);
- if ($default eq 'N') {
- generate_new_patch($diff);
+ if ($default =~ s/^D,// || $default eq 'N') {
+ my $def = generate_new_patch($diff);
+ $default = 'U,N' if $default eq 'N' && $def eq 'E';
+ $default = 'N' if !$minor_updates && $default eq 'U,N';
}
PROMPT:
chdir('workdir') or die $!;
system $cmd;
chdir('..') or die $!;
- $default = 'D,E';
+ $default = 'D';
next;
}
if ($cmd eq 'A') {
close IN;
close OUT;
}
+ my $need_autoconf;
+ my $conf_opts;
+ open(IN, "../$diff") or die $!;
+ while (<IN>) {
+ if (!defined $conf_opts) {
+ $conf_opts = '' if /^---/;
+ if (m#^\s*\./configure( .+)#) {
+ $conf_opts = $1;
+ }
+ }
+ if (m#^--- orig/(configure\.in|/aclocal\.m4)#) {
+ $need_autoconf = 1;
+ last;
+ }
+ }
+ close IN;
chdir('workdir') or die $!;
- system "make gen; ./configure $CONF_OPTS; make";
+ system "autoconf; autoheader" if $need_autoconf;
+ system "make proto; ./configure $CONF_OPTS $conf_opts; make";
chdir('..') or die $!;
$default = '!make test';
next;
my($diff) = @_;
undef @new;
- my $def = 'N';
system "rsync -a --delete --exclude='*~' cvsdir/ workdir/";
print "\nApplying patch $diff...\n";
+ undef @rejects;
+ my($saw_failure, $saw_offset, $saw_fuzz);
open(IN, "patch -d workdir -p0 --no-backup-if-mismatch -Zf <../$diff |") or die $!;
while (<IN>) {
print $_;
} elsif (s/.* saving rejects to file //) {
push(@rejects, $_);
} elsif (/^Hunk #\d+ FAILED/) {
- $def = 'F,D,E';
- } elsif (/^Hunk #\d+ succeeded/) {
- $def = 'E' unless $def =~ /F/;
+ $saw_failure = 1;
+ } elsif (/^Hunk #\d+ succeeded at \d+( with fuzz $interesting_fuzz)?/o) {
+ $saw_fuzz ||= defined $1;
+ $saw_offset = 1;
}
}
close IN;
- $def;
+ return 'F,D,E' if $saw_failure;
+ return 'D,E' if $saw_fuzz && !$failures_only;
+ return 'D,U,N' if $saw_offset && !$failures_only;
+ 'N';
}
sub generate_new_patch
}
}
}
+
+sub usage
+{
+ die <<EOT;
+Usage: $0 [OPTS] [DIFF-FILE...]
+ -n, --no-cvs Don't update tmp/cvsdir at the start of the run
+ -u, --minor-updates Suggest 'U' for even minor changes in the diff
+EOT
+}