From: Boris Byk Date: Fri, 10 Apr 2009 20:32:41 +0000 (+0400) Subject: git-svn: speed up blame command X-Git-Tag: v1.6.3-rc0~16 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=6ea420328885603087b3f1df42683c911d1b3f29;p=git.git git-svn: speed up blame command 'git svn blame' now uses the 'git cat-file --batch' command to speed up resolving SVN revision number out of commit SHA by removing fork+exec overhead. [ew: enforced 80-column line wrap] Signed-off-by: Boris Byk Acked-by: Eric Wong --- diff --git a/git-svn.perl b/git-svn.perl index cb718b851..50a398b3e 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -47,7 +47,8 @@ BEGIN { # import functions from Git into our packages, en masse no strict 'refs'; foreach (qw/command command_oneline command_noisy command_output_pipe - command_input_pipe command_close_pipe/) { + command_input_pipe command_close_pipe + command_bidi_pipe command_close_bidi_pipe/) { for my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher Git::SVN::Migration Git::SVN::Log Git::SVN), __PACKAGE__) { @@ -1264,6 +1265,40 @@ sub cmt_metadata { command(qw/cat-file commit/, shift)))[-1]); } +sub cmt_sha2rev_batch { + my %s2r; + my ($pid, $in, $out, $ctx) = command_bidi_pipe(qw/cat-file --batch/); + my $list = shift; + + foreach my $sha (@{$list}) { + my $first = 1; + my $size = 0; + print $out $sha, "\n"; + + while (my $line = <$in>) { + if ($first && $line =~ /^[[:xdigit:]]{40}\smissing$/) { + last; + } elsif ($first && + $line =~ /^[[:xdigit:]]{40}\scommit\s(\d+)$/) { + $first = 0; + $size = $1; + next; + } elsif ($line =~ /^(git-svn-id: )/) { + my (undef, $rev, undef) = + extract_metadata($line); + $s2r{$sha} = $rev; + } + + $size -= length($line); + last if ($size == 0); + } + } + + command_close_bidi_pipe($pid, $in, $out, $ctx); + + return \%s2r; +} + sub working_head_info { my ($head, $refs) = @_; my @args = ('log', '--no-color', '--first-parent', '--pretty=medium'); @@ -5001,11 +5036,22 @@ sub cmd_blame { '--', $path); my ($sha1); my %authors; + my @buffer; + my %dsha; #distinct sha keys + while (my $line = <$fh>) { + push @buffer, $line; + if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) { + $dsha{$1} = 1; + } + } + + my $s2r = ::cmt_sha2rev_batch([keys %dsha]); + + foreach my $line (@buffer) { if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) { - $sha1 = $1; - (undef, $rev, undef) = ::cmt_metadata($1); - $rev = '0' if (!$rev); + $rev = $s2r->{$1}; + $rev = '0' if (!$rev) } elsif ($line =~ /^author (.*)/) { $authors{$rev} = $1;