@matheusbsbs / matheus-bagliano / commits / ea020cbd6a
Fork 0

git-svn: exclude already merged tips using one rev-list call

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> Acked-by: Eric Wong <normalperson@yhbt.net>

Sam Vilain committed Dec 20, 2009 at 05:25 UTC ea020cbd6aeb769d95e5c2dbffee4c81d6f92796
1 file changed +48 -4
git-svn.perl
+48 -4
@@ -3038,6 +3038,41 @@ BEGIN {
3038 memoize 'lookup_svn_merge';
3039 }
3040
3041 +sub parents_exclude {
3042 + my $parents = shift;
3043 + my @commits = @_;
3044 + return unless @commits;
3045 +
3046 + my @excluded;
3047 + my $excluded;
3048 + do {
3049 + my @cmd = ('rev-list', "-1", @commits, "--not", @$parents );
3050 + $excluded = command_oneline(@cmd);
3051 + if ( $excluded ) {
3052 + my @new;
3053 + my $found;
3054 + for my $commit ( @commits ) {
3055 + if ( $commit eq $excluded ) {
3056 + push @excluded, $commit;
3057 + $found++;
3058 + last;
3059 + }
3060 + else {
3061 + push @new, $commit;
3062 + }
3063 + }
3064 + die "saw commit '$excluded' in rev-list output, "
3065 + ."but we didn't ask for that commit (wanted: @commits --not @$parents)"
3066 + unless $found;
3067 + @commits = @new;
3068 + }
3069 + }
3070 + while ($excluded and @commits);
3071 +
3072 + return @excluded;
3073 +}
3074 +
3075 +
3076 # note: this function should only be called if the various dirprops
3077 # have actually changed
3078 sub find_extra_svn_parents {
@@ -3050,23 +3085,32 @@ sub find_extra_svn_parents {
3085 # are now marked as merge, we can add the tip as a parent.
3086 my @merges = split "\n", $mergeinfo;
3087 my @merge_tips;
3053 - my @merged_commit_ranges;
3088 my $url = $self->rewrite_root || $self->{url};
3089 my $uuid = $self->ra_uuid;
3090 + my %ranges;
3091 for my $merge ( @merges ) {
3092 my ($tip_commit, @ranges) =
3093 lookup_svn_merge( $uuid, $url, $merge );
3059 - push @merged_commit_ranges, @ranges;
3094 unless (!$tip_commit or
3095 grep { $_ eq $tip_commit } @$parents ) {
3096 push @merge_tips, $tip_commit;
3097 + $ranges{$tip_commit} = \@ranges;
3098 } else {
3099 push @merge_tips, undef;
3100 }
3101 }
3102 +
3103 + my %excluded = map { $_ => 1 }
3104 + parents_exclude($parents, grep { defined } @merge_tips);
3105 +
3106 + # check merge tips for new parents
3107 + my @new_parents;
3108 for my $merge_tip ( @merge_tips ) {
3109 my $spec = shift @merges;
3069 - next unless $merge_tip;
3110 + next unless $merge_tip and $excluded{$merge_tip};
3111 +
3112 + my $ranges = $ranges{$merge_tip};
3113 +
3114 my @cmd = ('rev-list', "-1", $merge_tip,
3115 "--not", @$parents );
3116 my ($msg_fh, $ctx) = command_output_pipe(@cmd);
@@ -3076,7 +3120,7 @@ sub find_extra_svn_parents {
3120 }
3121 command_close_pipe($msg_fh, $ctx);
3122 if ( $new ) {
3079 - push @cmd, @merged_commit_ranges;
3123 + push @cmd, @$ranges;
3124 my ($msg_fh, $ctx) = command_output_pipe(@cmd);
3125 my $unmerged;
3126 while ( <$msg_fh> ) {