Subject: Re: [spf:guess,iffy,mismatch] Re: [PATCH/RFC 2/2] git-svn: Don't allow missing commit parent to stop git-svn

From: Sam Vilain <[email-masked]>
Date: Thu, 22 Apr 2010 11:45:11 +1200

Michael Olson wrote:
> Interestingly, I see people reporting the same problem in the thread
> "git svn clone of subversion's own code failing".  So it's not just
> related to patch 1/2 of this series.  At least that thread has a
> public-facing repo so the problem should be easier to reproduce for
> a real fix.

Oh, right ... I remember that issue now. I'm currently testing the
below change to see if it breaks the test suite; any issues and I'll
post an update.

Subject: [PATCH] git-svn: deal with svn cherry-picks with non-linear history

The expression 'BASE^..TIP' is only defined when BASE has parents.  It
actually does what it intends only when it has one parent.

Allow for more complicated revision list arguments than a range by
splitting any space-containing arguments on the way into _rev_list,
and check the parents of the bottom commit so that we may use the
correct revision list specifier.
---
 git-svn.perl |   22 +++++++++++++++++++---
 1 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 2c86ea2..a82ca1a 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -3063,8 +3063,24 @@ sub lookup_svn_merge {
 			next;
 		}
 
-		push @merged_commit_ranges,
-			"$bottom_commit^..$top_commit";
+		# how many parents does $bottom_commit have?
+		my @parents = split / /, command_oneline(
+			qw(rev-list --parents -1 -m),
+			$bottom_commit,
+		       );
+		shift @parents;
+
+		if ( @parents == 1 ) {
+			push @merged_commit_ranges,
+				"$bottom_commit^..$top_commit";
+		}
+		elsif ( @parents ) {
+			push @merged_commit_ranges,
+				"$top_commit --not @parents";
+		}
+		else {
+			push @merged_commit_ranges, $top_commit;
+		}
 
 		if ( !defined $tip or $top > $tip ) {
 			$tip = $top;
@@ -3094,7 +3110,7 @@ sub check_cherry_pick {
 	my %commits = map { $_ => 1 }
 		_rev_list("--no-merges", $tip, "--not", $base);
 	for my $range ( @ranges ) {
-		delete @commits{_rev_list($range)};
+		delete @commits{_rev_list(split " ", $range)};
 	}
 	for my $commit (keys %commits) {
 		if (has_no_changes($commit)) {
-- 
1.7.0.2