NOTE: This patch has been committed.
ben/ChangeLog addition:
2005-02-07 Ben Wing <ben(a)xemacs.org>
* cvs-merge-diff:
* cvs-merge-diff (Value):
* cvs-merge-diff (sort_dot_pound_files):
* cvs-merge-diff (getfile):
Add -debug option and output debug info if so.
Correctly handle (as much as possible) the case where the
repository file was removed in the local workspace and
changed in the repository revisions being merged in.
xemacs-builds source patch:
Diff command: bash -ci "cvs-diff --show-c-function -no-changelog "
Files affected: ben/cvs-merge-diff
Index: ben/cvs-merge-diff
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs-builds/ben/cvs-merge-diff,v
retrieving revision 1.2
diff -u -p -r1.2 cvs-merge-diff
--- ben/cvs-merge-diff 2004/11/13 23:01:09 1.2
+++ ben/cvs-merge-diff 2005/02/07 13:30:26
@@ -4,7 +4,7 @@ eval 'exec perl -w -S $0 ${1+"$@"}' # Po
### cvs-merge-diff --- Show the diff between various versions of a file
-## Copyright (C) 2001, 2003, 2004 Ben Wing.
+## Copyright (C) 2001, 2003, 2004, 2005 Ben Wing.
## Author: Ben Wing <ben(a)xemacs.org>
## Maintainer: Ben Wing <ben(a)xemacs.org>
@@ -82,13 +82,15 @@ be the same as (1), (3), (8), or any oth
my @SAVE_ARGV = @ARGV;
my %options;
-GetDiffOptions (\%options, 'from=s', 'to=s',);
+GetDiffOptions (\%options, 'from=s', 'to=s', 'debug');
die $usage if $options{"help"};
+my $debug = $options{"debug"} || defined $ENV{VERBOSE} || defined $ENV{DEBUG};
+
# extract options, but eliminate -from=X, -to=X
-my @OPTIONS = grep (!/(-|--|\+)(from|to)=/,
+my @OPTIONS = grep (!/(-|--|\+)(debug|from=|to=)/,
@SAVE_ARGV[0 .. (@SAVE_ARGV - @ARGV - 1)]);
# eliminate -from X, -to X
@@ -115,9 +117,13 @@ die $usage unless (defined ($spec1) and
$spec1 =~ /^([zabcd]|([0-9]+))$/i and
$spec2 =~ /^([zabcd]|([0-9]+))$/i);
-my ($filez, $filea, $fileb, $filec, $filed, $filetmp);
+my ($filez, $filea, $fileb, $filec, $filed, $filetmp, $killedthis);
my $cvsstatus = `cvs status $file`;
+print "`cvs status file`:\n$cvsstatus" if $debug;
+
+my ($name, $path) = fileparse ($file);
+
# To find the various versions:
# B = look for files named .#FILE(.[0-9]+)+ and take the most recent one.
@@ -130,31 +136,80 @@ my $cvsstatus = `cvs status $file`;
die "File $file unknown to CVS" if $cvsstatus =~ /Status: Unknown/;
-if ($spec1 =~ /c/i || $spec2 =~ /c/i) {
- ($filec) = ($cvsstatus =~ /Working revision:\s*([0-9.]+)$/m);
-}
+sub Value { return defined $_[0] ? $_[0] : "(undefined)"; }
+
+if ($spec1 =~ /[bc]/i || $spec2 =~ /[bc]/i) {
+ ($killedthis, $filec) = ($cvsstatus =~ /Working revision:\s*(-?)([0-9.]+)$/m);
+ die "Can't parse working revision?" if !$filec;
+
+ if ($killedthis)
+ {
+ $filea = $filec;
+ print "Revision A (common ancestor): " . Value($filea) . "\n"
if $debug;
+ ($filec) = ($cvsstatus =~ /Repository revision:\s*([0-9.]+)\s/);
+
+ die "Can't parse repository revision?" if !$filec;
+
+ print "Revision C (repository change merged in): " . Value($filec) .
"\n"
+ if $debug;
+
+ print <<EOF;
+WARNING: File has been removed in this repository.
+
+Impossible to determine repository change merged into workspace.
+Assuming current repository revision $filec as merged revision.
+It may also be impossible to determine the common ancestor, if
+multiple merges have occurred in this workspace, since deletion
+of the file. Assuming revision $filea as common ancestor. If
+these values are wrong, then they err on the conservative side
+(i.e. being too early for the common ancestor and too late for
+the merged revision), so diffs between them will show all the
+actual diffs and possibly some extra ones.
+
+EOF
+ }
+ else
+ {
+ print "Revision C (repository change merged in): " . Value($filec) .
"\n"
+ if $debug;
+ }
+ }
-sub sort_dot_pound_files { -M $a <=> -M $b; }
+sub sort_dot_pound_files { -M "$path$a" <=> -M "$path$b"; }
if ($spec1 =~ /[baz]/i || $spec2 =~ /[baz]/i) {
- opendir DIR, ".";
- my @files = grep /^\.\#$file(.[0-9]+)+/, readdir DIR;
- closedir DIR;
- @files = sort sort_dot_pound_files @files;
- $fileb = $files[0];
- die "No merge in progress on $file" if !$fileb;
- ($filea = $fileb) =~ s/^\.\#$file.//;
+ if (!$killedthis)
+ {
+ opendir DIR, $path;
+ my @files = grep /^\.\#$name(.[0-9]+)+/, readdir DIR;
+ closedir DIR;
+ print "Found dot-files: @files\n" if $debug;
+ @files = sort sort_dot_pound_files @files;
+ $fileb = $files[0];
+ print "File B (pre-merge in this workspace): " . Value($fileb) .
"\n"
+ if $debug;
+ die "No merge in progress on $file" if !$fileb;
+ ($filea = $fileb) =~ s/^\.\#$name.//;
+ print "Revision A (common ancestor): " . Value($filea) . "\n"
if $debug;
+ $fileb = "$path$fileb";
+ }
+ else
+ {
+ $fileb = "/dev/null";
+ }
($filez = $filea) =~ s/(\d+)$/$1-1/e;
if ($filez =~ /\.0$/) {
$filez =~ s/\.\d+\.\d+$//;
}
+ print "Revision Z (common ancestor's parent): " . Value($filez) .
"\n"
+ if $debug;
}
sub getfile {
return $filea if ($_[0] =~ /a/i);
return $fileb if ($_[0] =~ /b/i);
return $filec if ($_[0] =~ /c/i);
- return $file if ($_[0] =~ /d/i);
+ return "$path$name" if ($_[0] =~ /d/i);
return $filez if ($_[0] =~ /z/i);
($filetmp = $filec) =~ s/(\d+)$/$1-$_[0]/e, return $filetmp
if ($_[0] =~ /[0-9]/i);
@@ -171,20 +226,26 @@ my $spec2_is_rev = $spec2 =~ /([azc]|[0-
if ($spec1_is_rev && $spec2_is_rev) {
# We are diffing two repository revisions.
+ print "Executing: cvs diff -u @OPTIONS -r $file1 -r $file2 $file\n" if
$debug;
system "cvs diff -u @OPTIONS -r $file1 -r $file2 $file";
} elsif (!$spec1_is_rev && !$spec2_is_rev) {
# We are diffing two real files.
+ print "Executing: diff -u @OPTIONS $file1 $file2\n" if $debug;
system "diff -u @OPTIONS $file1 $file2";
} else {
# We are diffing a repository revision and a real file. Fetch the
# repository revision.
- my $tmpfile = "/tmp/$file.$$";
+ my $tmpfile = "/tmp/$name.$$";
if ($spec1_is_rev) {
+ print "Executing: cvs update -p -r $file1 $file > $tmpfile\n" if
$debug;
system "cvs update -p -r $file1 $file > $tmpfile";
+ print "diff -u @OPTIONS $tmpfile $file2\n" if $debug;
system "diff -u @OPTIONS $tmpfile $file2";
system "rm $tmpfile";
} else {
+ print "cvs update -p -r $file2 $file > $tmpfile\n" if $debug;
system "cvs update -p -r $file2 $file > $tmpfile";
+ print "diff -u @OPTIONS $file1 $tmpfile\n" if $debug;
system "diff -u @OPTIONS $file1 $tmpfile";
system "rm $tmpfile";
}