Transformed shell script into perl script and improved it to allow
authorWayne Davison <wayned@samba.org>
Sat, 3 Jul 2004 21:20:11 +0000 (21:20 +0000)
committerWayne Davison <wayned@samba.org>
Sat, 3 Jul 2004 21:20:11 +0000 (21:20 +0000)
diffs to depend on other diffs.  Diffs are made locally now (not
using cvs) which makes them faster as well as making the date
header compatible with patch's -Z option (which we now use to
avoid useless changes to the diff headers).  Automatically exclude
generated files from the diff (such as proto.h).

verify-patches

index 6cc2c1721cea00eb947410bff0d917cd4bf9f81a..661f8a81ec54ba5a7aaf4139a54e5599424c8cbd 100755 (executable)
-#!/bin/sh
-
-[ -d patches ] && cd patches
-
-if [ ! -f verify-patches ]; then
-    echo "Please run this script from the root of the rsync dir"
-    echo "or from inside the patches subdir."
-    exit 1
-fi
-
-root=`cat ../CVS/Root`
-tmpdir=,tmp-for-patch-tests
-
-[ -d $tmpdir ] || mkdir $tmpdir
-cd $tmpdir || exit 1
-
-[ -d workdir ] || mkdir workdir
-echo "Using CVS to update the $tmpdir/cvsdir copy of the source."
-cvs -d "$root" co -d cvsdir rsync
-
-cd workdir || exit 1
-
-if [ -z "$1" ]; then
-    set -- ../../*.diff
-fi
-
-for xx in "${@}"; do
-    case "$xx" in
-    *gzip-rsyncable.diff) continue ;;
-    patches/*) xx=`echo $xx | sed 's:patches:../..:'` ;;
-    */*.diff) ;;
-    *.diff) xx=../../$xx ;;
-    *) continue ;;
-    esac
-    apply=y
-    while : ; do
-       echo -e "\n----------- $xx ------------"
-       if [ $apply = y ]; then
-           rsync -a --delete ../cvsdir/ .
-           patch -p0 <$xx | tee ,patch.output
-           new=''
-           for nn in `sed -n 's/^patching file //p' ,patch.output`; do
-               [ -f ../cvsdir/$nn ] || new="$new $nn"
-           done
-           if grep "^Hunk #[0-9]* FAILED" ,patch.output >/dev/null; then
-               default=F
-           elif grep "^Hunk #[0-9]* succeeded" ,patch.output >/dev/null; then
-               default=E
-           else
-               default=N
-           fi
-           apply=n
-       fi
-       echo -e "\nFix rejects, Edit both diffs, Update patch,"
-       echo -n "Apply patch again, Next, Quit: [$default] "
-       read ans
-       [ -z "$ans" ] && ans=$default
-       case "$ans" in
-       [Ee]*)
-           [ ! -z "$new" ] && cvs add $new
-           new=''
-           rm -f *.rej *.orig */*.rej */*.orig
-           sed '/^--- /,$ d' $xx >,new.patch
-           cvs diff -N |
-               egrep -v '^(diff -|===============|RCS file: |retrieving revision |Index: )' |
-               sed -e 's:^--- a/:--- :' -e 's:^+++ b/:+++ :' >>,new.patch
-           vim -d $xx ,new.patch
-           default=U
-           ;;
-       [Ff]*)
-           vim `sed -ne 's/.* saving rejects to file //p' ,patch.output`
-           default=E
-           ;;
-       [Uu]*)
-           if [ -f ,new.patch ]; then
-               cp -p ,new.patch $xx
-               echo -e "\nCopied ,new.patch to $xx"
-               default=A
-           else
-               echo -e "\n*** Edit the diffs first. ***"
-               default=E
-           fi
-           ;;
-       [Aa]*)
-           apply=y
-           ;;
-       [Nn]*)
-           break
-           ;;
-       [Qq]*)
-           exit 0
-           ;;
-       esac
-    done
-done
+#!/usr/bin/perl
+
+use strict;
+
+chdir('patches') if -d 'patches';
+
+if (!-f 'verify-patches') {
+    die <<EOT;
+Please run this script from the root of the rsync dir or
+from inside the patches subdir.
+EOT
+}
+
+$ENV{'TZ'} = 'GMT';
+
+my($has_dependencies, @new);
+
+END {
+    &restore_cvsdir;
+};
+
+my $root;
+open(IN, '../CVS/Root') or die $!;
+chomp($root = <IN>);
+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 <<EOT;
+proto.h
+configure
+config.h.in
+rsync.1
+rsyncd.conf.5
+EOT
+close OUT;
+
+print "Using CVS to update the $tmpdir/cvsdir copy of the source.\n";
+system qq|cvs -d "$root" co -d cvsdir rsync|;
+
+@ARGV = glob('../*.diff') unless @ARGV;
+
+DIFF:
+foreach my $diff (@ARGV) {
+    next unless $diff =~ /\.diff$/;
+    next if $diff =~ /gzip-rsyncable\.diff$/;
+    $diff =~ s#^(patches|\.\.)/##;
+
+    open(IN, "../$diff") or die $!;
+    while (<IN>) {
+       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 (<IN>) {
+               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 = <STDIN>;
+       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 (<IN>) {
+       last if /^--- /;
+       print OUT $_;
+    }
+    close IN;
+    open(IN, 'diff --exclude-from=exclude -upr cvsdir workdir |') or die $!;
+    while (<IN>) {
+       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);
+       }
+    }
+}