summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Boris Byk <boris.byk@gmail.com>2009-04-11 00:32:41 +0400
committerLibravatar Eric Wong <normalperson@yhbt.net>2009-04-11 17:55:04 -0700
commit6ea420328885603087b3f1df42683c911d1b3f29 (patch)
tree86656df55b76a85be6a7d0c636aaab08289166d9
parentgit-svn: add fetch --parent option (diff)
downloadtgif-6ea420328885603087b3f1df42683c911d1b3f29.tar.xz
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 <boris.byk@gmail.com> Acked-by: Eric Wong <normalperson@yhbt.net>
-rwxr-xr-xgit-svn.perl54
1 files changed, 50 insertions, 4 deletions
diff --git a/git-svn.perl b/git-svn.perl
index cb718b8519..50a398b3e7 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;