git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 4/5] git-svn: exclude already merged tips using one rev-list call

From
Sam Vilain <sam@vilain.net>
Date
Dec 19, 2009, 16:33 UTC
Message-ID
<1261240435-8948-5-git-send-email-sam@vilain.net>
In-Reply-To
<1261240435-8948-4-git-send-email-sam@vilain.net>

The old function would have to check all mentioned merge tips, every time that the mergeinfo ticket changed. This involved 1-2 rev-list operation for each listed mergeinfo line. If there are a lot of feature branches being merged into a trunk, this makes for a very expensive operation for detecting the new parents on every merge.

This new version first uses a single 'rev-list' to figure out which commit ranges are already reachable from the parents. This is used to eliminate the already merged branches from the list.

Signed-off-by: Sam Vilain <sam@vilain.net>
---
 git-svn.perl |   52 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 9cf4a3e..7a790d7 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -3011,6 +3011,41 @@ BEGIN {
 	memoize 'lookup_svn_merge';
 }
 
+sub parents_exclude {
+	my $parents = shift;
+	my @commits = @_;
+	return unless @commits;
+
+	my @excluded;
+	my $excluded;
+	do {
+		my @cmd = ('rev-list', "-1", @commits, "--not", @$parents );
+		$excluded = command_oneline(@cmd);
+		if ( $excluded ) {
+			my @new;
+			my $found;
+			for my $commit ( @commits ) {
+				if ( $commit eq $excluded ) {
+					push @excluded, $commit;
+					$found++;
+					last;
+				}
+				else {
+					push @new, $commit;
+				}
+			}
+			die "saw commit '$excluded' in rev-list output, "
+				."but we didn't ask for that commit (wanted: @commits --not @$parents)"
+					unless $found;
+			@commits = @new;
+		}
+	}
+		while ($excluded and @commits);
+
+	return @excluded;
+}
+
+
 # note: this function should only be called if the various dirprops
 # have actually changed
 sub find_extra_svn_parents {
@@ -3023,23 +3058,32 @@ sub find_extra_svn_parents {
 	# are now marked as merge, we can add the tip as a parent.
 	my @merges = split "\n", $mergeinfo;
 	my @merge_tips;
-	my @merged_commit_ranges;
 	my $url = $self->rewrite_root || $self->{url};
 	my $uuid = $self->ra_uuid;
+	my %ranges;
 	for my $merge ( @merges ) {
 		my ($tip_commit, @ranges) =
 			lookup_svn_merge( $uuid, $url, $merge );
-		push @merged_commit_ranges, @ranges;
 		unless (!$tip_commit or
 				grep { $_ eq $tip_commit } @$parents ) {
 			push @merge_tips, $tip_commit;
+			$ranges{$tip_commit} = \@ranges;
 		} else {
 			push @merge_tips, undef;
 		}
 	}
+
+	my %excluded = map { $_ => 1 }
+		parents_exclude($parents, grep { defined } @merge_tips);
+
+	# check merge tips for new parents
+	my @new_parents;
 	for my $merge_tip ( @merge_tips ) {
 		my $spec = shift @merges;
-		next unless $merge_tip;
+		next unless $merge_tip and $excluded{$merge_tip};
+
+		my $ranges = $ranges{$merge_tip};
+
 		my @cmd = ('rev-list', "-1", $merge_tip,
 			   "--not", @$parents );
 		my ($msg_fh, $ctx) = command_output_pipe(@cmd);
@@ -3049,7 +3093,7 @@ sub find_extra_svn_parents {
 		}
 		command_close_pipe($msg_fh, $ctx);
 		if ( $new ) {
-			push @cmd, @merged_commit_ranges;
+			push @cmd, @$ranges;
 			my ($msg_fh, $ctx) = command_output_pipe(@cmd);
 			my $unmerged;
 			while ( <$msg_fh> ) {
-- 
1.6.3.3
Previous: Sam VilainNext: Sam Vilain
Message 5 of 13 in “Efficiency and correctness patches for git-svn mergeinfo support”
  1. Sam VilainDec 19, 2009
  2. 1/5 git-svn: expand the svn mergeinfo test suite, highlighting some failuresSam Vilain, Dec 19, 2009
  3. 2/5 git-svn: memoize conversion of SVN merge ticket info to git commit rangesSam Vilain, Dec 19, 2009
  4. 3/5 git-svn: fix some mistakes with interpreting SVN mergeinfo commit rangesSam Vilain, Dec 19, 2009
  5. 4/5 git-svn: exclude already merged tips using one rev-list callSam Vilain, Dec 19, 2009
  6. 5/5 git-svn: detect cherry-picks correctly.Sam Vilain, Dec 19, 2009
  7. Sam VilainDec 19, 2009
  8. Sam VilainDec 20, 2009
  9. Eric WongDec 21, 2009
  10. Sam VilainDec 19, 2009
  11. Andrew MyrickDec 19, 2009
  12. Sam VilainDec 20, 2009
  13. Andrew MyrickDec 20, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.