@matheusbsbs / matheus-bagliano / commits / 6ea4203288
Fork 0

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>

Boris Byk committed Apr 11, 2009 at 00:32 UTC 6ea420328885603087b3f1df42683c911d1b3f29
1 file changed +50 -4
git-svn.perl
+50 -4
@@ -47,7 +47,8 @@ BEGIN {
47 # import functions from Git into our packages, en masse
48 no strict 'refs';
49 foreach (qw/command command_oneline command_noisy command_output_pipe
50 - command_input_pipe command_close_pipe/) {
50 + command_input_pipe command_close_pipe
51 + command_bidi_pipe command_close_bidi_pipe/) {
52 for my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher
53 Git::SVN::Migration Git::SVN::Log Git::SVN),
54 __PACKAGE__) {
@@ -1264,6 +1265,40 @@ sub cmt_metadata {
1265 command(qw/cat-file commit/, shift)))[-1]);
1266 }
1267
1268 +sub cmt_sha2rev_batch {
1269 + my %s2r;
1270 + my ($pid, $in, $out, $ctx) = command_bidi_pipe(qw/cat-file --batch/);
1271 + my $list = shift;
1272 +
1273 + foreach my $sha (@{$list}) {
1274 + my $first = 1;
1275 + my $size = 0;
1276 + print $out $sha, "\n";
1277 +
1278 + while (my $line = <$in>) {
1279 + if ($first && $line =~ /^[[:xdigit:]]{40}\smissing$/) {
1280 + last;
1281 + } elsif ($first &&
1282 + $line =~ /^[[:xdigit:]]{40}\scommit\s(\d+)$/) {
1283 + $first = 0;
1284 + $size = $1;
1285 + next;
1286 + } elsif ($line =~ /^(git-svn-id: )/) {
1287 + my (undef, $rev, undef) =
1288 + extract_metadata($line);
1289 + $s2r{$sha} = $rev;
1290 + }
1291 +
1292 + $size -= length($line);
1293 + last if ($size == 0);
1294 + }
1295 + }
1296 +
1297 + command_close_bidi_pipe($pid, $in, $out, $ctx);
1298 +
1299 + return \%s2r;
1300 +}
1301 +
1302 sub working_head_info {
1303 my ($head, $refs) = @_;
1304 my @args = ('log', '--no-color', '--first-parent', '--pretty=medium');
@@ -5001,11 +5036,22 @@ sub cmd_blame {
5036 '--', $path);
5037 my ($sha1);
5038 my %authors;
5039 + my @buffer;
5040 + my %dsha; #distinct sha keys
5041 +
5042 while (my $line = <$fh>) {
5043 + push @buffer, $line;
5044 + if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) {
5045 + $dsha{$1} = 1;
5046 + }
5047 + }
5048 +
5049 + my $s2r = ::cmt_sha2rev_batch([keys %dsha]);
5050 +
5051 + foreach my $line (@buffer) {
5052 if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) {
5006 - $sha1 = $1;
5007 - (undef, $rev, undef) = ::cmt_metadata($1);
5008 - $rev = '0' if (!$rev);
5053 + $rev = $s2r->{$1};
5054 + $rev = '0' if (!$rev)
5055 }
5056 elsif ($line =~ /^author (.*)/) {
5057 $authors{$rev} = $1;