aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Vilain <sam@vilain.net>2009-12-20 00:55:13 +1300
committerEric Wong <normalperson@yhbt.net>2009-12-21 02:32:48 -0800
commit7d944c3399c4145293d599e1ddc76d1ac0c1e118 (patch)
tree4850db3279150a4225b6d93c423c3f726aedee7d
parent1d144aa25edbb4dcda88abbaef8f336108b8d788 (diff)
downloadgit-7d944c3399c4145293d599e1ddc76d1ac0c1e118.tar.gz
git-7d944c3399c4145293d599e1ddc76d1ac0c1e118.tar.xz
git-svn: memoize conversion of SVN merge ticket info to git commit ranges
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. [ew: changed "next" to "return" for function exit] Signed-off-by: Sam Vilain <sam@vilain.net> Acked-by: Eric Wong <normalperson@yhbt.net>
-rwxr-xr-xgit-svn.perl91
1 files changed, 54 insertions, 37 deletions
diff --git a/git-svn.perl b/git-svn.perl
index a6f5061c3..1e106f064 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);
@@ -2994,6 +2995,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";
+ return;
+ }
+ 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 {
@@ -3008,44 +3058,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;