git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sam Vilain <sam@vilain.net>
To: git@vger.kernel.org
Cc: Eric Wong <normalperson@yhbt.net>,
	Andrew Myrick <amyrick@gmail.com>, Sam Vilain <sam@vilain.net>
Subject: [PATCH 2/5] git-svn: memoize conversion of SVN merge ticket info to git commit ranges
Date: Sun, 20 Dec 2009 05:33:52 +1300	[thread overview]
Message-ID: <1261240435-8948-3-git-send-email-sam@vilain.net> (raw)
In-Reply-To: <1261240435-8948-2-git-send-email-sam@vilain.net>

Each time the svn mergeinfo ticket changes, we look it up in the rev_map;
when there are a lot of merged branches, this will result in many repeated
lookups of the same information for subsequent commits.  Arrange the slow
part of the function so that it may be memoized, and memoize it.  The more
expensive revision walking operation can be memoized separately.

Signed-off-by: Sam Vilain <sam@vilain.net>
---
 git-svn.perl |   91 ++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 54 insertions(+), 37 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index a4b052c..3b17a83 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -1634,6 +1634,7 @@ use Carp qw/croak/;
 use File::Path qw/mkpath/;
 use File::Copy qw/copy/;
 use IPC::Open3;
+use Memoize;  # core since 5.8.0, Jul 2002
 
 my ($_gc_nr, $_gc_period);
 
@@ -2967,6 +2968,55 @@ sub find_extra_svk_parents {
 	}
 }
 
+sub lookup_svn_merge {
+	my $uuid = shift;
+	my $url = shift;
+	my $merge = shift;
+
+	my ($source, $revs) = split ":", $merge;
+	my $path = $source;
+	$path =~ s{^/}{};
+	my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
+	if ( !$gs ) {
+		warn "Couldn't find revmap for $url$source\n";
+		next;
+	}
+	my @ranges = split ",", $revs;
+	my ($tip, $tip_commit);
+	my @merged_commit_ranges;
+	# find the tip
+	for my $range ( @ranges ) {
+		my ($bottom, $top) = split "-", $range;
+		$top ||= $bottom;
+		my $bottom_commit =
+			$gs->rev_map_get($bottom, $uuid) ||
+			$gs->rev_map_get($bottom+1, $uuid);
+		my $top_commit;
+		for (; !$top_commit && $top >= $bottom; --$top) {
+			$top_commit =
+				$gs->rev_map_get($top, $uuid);
+		}
+
+		unless ($top_commit and $bottom_commit) {
+			warn "W:unknown path/rev in svn:mergeinfo "
+				."dirprop: $source:$range\n";
+			next;
+		}
+
+		push @merged_commit_ranges,
+			"$bottom_commit..$top_commit";
+
+		if ( !defined $tip or $top > $tip ) {
+			$tip = $top;
+			$tip_commit = $top_commit;
+		}
+	}
+	return ($tip_commit, @merged_commit_ranges);
+}
+BEGIN {
+	memoize 'lookup_svn_merge';
+}
+
 # note: this function should only be called if the various dirprops
 # have actually changed
 sub find_extra_svn_parents {
@@ -2981,44 +3031,11 @@ sub find_extra_svn_parents {
 	my @merge_tips;
 	my @merged_commit_ranges;
 	my $url = $self->rewrite_root || $self->{url};
+	my $uuid = $self->ra_uuid;
 	for my $merge ( @merges ) {
-		my ($source, $revs) = split ":", $merge;
-		my $path = $source;
-		$path =~ s{^/}{};
-		my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
-		if ( !$gs ) {
-			warn "Couldn't find revmap for $url$source\n";
-			next;
-		}
-		my @ranges = split ",", $revs;
-		my ($tip, $tip_commit);
-		# find the tip
-		for my $range ( @ranges ) {
-			my ($bottom, $top) = split "-", $range;
-			$top ||= $bottom;
-			my $bottom_commit =
-				$gs->rev_map_get($bottom, $self->ra_uuid) ||
-				$gs->rev_map_get($bottom+1, $self->ra_uuid);
-			my $top_commit;
-			for (; !$top_commit && $top >= $bottom; --$top) {
-				$top_commit =
-					$gs->rev_map_get($top, $self->ra_uuid);
-			}
-
-			unless ($top_commit and $bottom_commit) {
-				warn "W:unknown path/rev in svn:mergeinfo "
-					."dirprop: $source:$range\n";
-				next;
-			}
-
-			push @merged_commit_ranges,
-				"$bottom_commit..$top_commit";
-
-			if ( !defined $tip or $top > $tip ) {
-				$tip = $top;
-				$tip_commit = $top_commit;
-			}
-		}
+		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;
-- 
1.6.3.3

  reply	other threads:[~2009-12-19 16:34 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-19 16:33 Efficiency and correctness patches for git-svn mergeinfo support Sam Vilain
2009-12-19 16:33 ` [PATCH 1/5] git-svn: expand the svn mergeinfo test suite, highlighting some failures Sam Vilain
2009-12-19 16:33   ` Sam Vilain [this message]
2009-12-19 16:33     ` [PATCH 3/5] git-svn: fix some mistakes with interpreting SVN mergeinfo commit ranges Sam Vilain
2009-12-19 16:33       ` [PATCH 4/5] git-svn: exclude already merged tips using one rev-list call Sam Vilain
2009-12-19 16:33         ` [PATCH 5/5] git-svn: detect cherry-picks correctly Sam Vilain
2009-12-19 16:37     ` [PATCH 2/5] git-svn: memoize conversion of SVN merge ticket info to git commit ranges Sam Vilain
2009-12-20 21:24     ` Sam Vilain
2009-12-21 10:44       ` Eric Wong
2009-12-19 16:42 ` Efficiency and correctness patches for git-svn mergeinfo support Sam Vilain
2009-12-19 22:15 ` Andrew Myrick
2009-12-20 21:07   ` Sam Vilain
2009-12-20 22:03     ` Andrew Myrick

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1261240435-8948-3-git-send-email-sam@vilain.net \
    --to=sam@vilain.net \
    --cc=amyrick@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=normalperson@yhbt.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).