#!/usr/bin/perl use strict; chdir('patches') if -d 'patches'; if (!-f 'verify-patches') { die <); close IN; my $tmpdir = ',tmp-for-patch-tests'; mkdir($tmpdir, 0777) unless -d $tmpdir; chdir($tmpdir) or die "Unable to chdir to $tmpdir"; mkdir('workdir') unless -d 'workdir'; open(OUT, '>exclude') or die $!; print OUT <) { last if /^--- /; if (/^Depends-On-Patch: (\S+.diff)$/) { my $dep = $1; $has_dependencies = 1; print "\nApplying dependency patch $dep\n"; if (system("patch -d cvsdir -p0 -b -Vt -Z <../$dep") != 0) { print "Unable to cleanly apply depenency patch -- skipping $diff\n"; &restore_cvsdir; next DIFF; } } } close IN; my $apply = 1; my(@rejects, $default); while (1) { print "\n----------- $diff ------------\n"; if ($apply) { undef @new; $default = 'N'; system "rsync -a --delete cvsdir/ workdir"; open(IN, "patch -d workdir -p0 --no-backup-if-mismatch -Z <../$diff |") or die $!; while () { print $_; chomp; if (s/^patching file //) { push(@new, $_) unless -f "cvsdir/$_"; } elsif (s/.* saving rejects to file //) { push(@rejects, $_); } elsif (/^Hunk #\d+ FAILED/) { $default = 'F'; } elsif (/^Hunk #\d+ succeeded/) { $default = 'E' unless $default eq 'F'; } } close IN; if ($default eq 'N') { generate_new_patch($diff); if (system("diff ../$diff new.patch >/dev/null") == 0) { print "\n(New patch is identical to old.)\n"; } } $apply = 0; } print "\nFix rejects, Edit both diffs, Update patch,\n", "Apply patch again, Next, Quit: [$default] "; my $ans = ; chomp $ans; $ans = $default unless $ans =~ s/^(\w)/$1/; if ($ans =~ /E/i) { generate_new_patch($diff); chdir('workdir') or die $!; system "vim -d ../../$diff ../new.patch"; chdir('..') or die $!; $default = 'U'; } elsif ($ans =~ /F/i) { chdir('workdir') or die $!; system "vim @rejects"; chdir('..') or die $!; $default = 'E'; } elsif ($ans =~ /U/i) { system "cp -p new.patch ../$diff"; print "\nUpdated $diff from new.patch\n"; $default = 'A'; } elsif ($ans =~ /A/i) { $apply = 1; } elsif ($ans =~ /N/i) { last; } elsif ($ans =~ /Q/i) { exit; } } &restore_cvsdir; } exit; sub generate_new_patch { my($diff) = @_; foreach (@new) { system "touch -r workdir/$_ cvsdir/$_"; } open(IN, "../$diff") or die $!; open(OUT, '>new.patch') or die $!; while () { last if /^--- /; print OUT $_; } close IN; open(IN, 'diff --exclude-from=exclude -upr cvsdir workdir |') or die $!; while () { next if /^(diff -|Index: |Only in )/; s#^\Q--- cvsdir/\E#--- orig/#; s#^\Q+++ workdir/\E#+++ #; s#(\.000000000)? \+0000$##; print OUT $_; } close IN; close OUT; foreach (@new) { unlink("cvsdir/$_"); } } sub restore_cvsdir { return unless $has_dependencies; $has_dependencies = 0; foreach (glob('*.~[1-9]~'), glob('*/*.~[1-9]~')) { my $fn; ($fn = $_) =~ s/\.~1~$//; if ($fn eq $_) { unlink($_); } elsif (-r $fn) { rename($_, $fn); } else { unlink($_); unlink($fn); } } }