@matheusbsbs / matheus-bagliano / commits / 4be4038153
Fork 0

Add svn-compatible "blame" output format to git-svn

git-svn blame produced output in the format of git blame; in environments where there are scripts that read the output of svn blame, it's useful to be able to use them with the output of git-svn. The git-compatible format is still available using the new "--git-format" option. This also fixes a bug in the initial git-svn blame implementation; it was bombing out on uncommitted local changes. Signed-off-by: Steven Grimm <koreth@midwinter.com> Acked-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Steven Grimm committed May 10, 2008 at 22:11 UTC 4be403815321976bc2ee4c6677799abb06b153aa
2 files changed +55 -15
Documentation/git-svn.txt
+11 -4
@@ -166,11 +166,18 @@ environment). This command has the same behaviour.
166 Any other arguments are passed directly to `git log'
167
168 'blame'::
169 - Show what revision and author last modified each line of a file. This is
170 - identical to `git blame', but SVN revision numbers are shown instead of git
171 - commit hashes.
169 + Show what revision and author last modified each line of a file. The
170 + output of this mode is format-compatible with the output of
171 + `svn blame' by default. Like the SVN blame command,
172 + local uncommitted changes in the working copy are ignored;
173 + the version of the file in the HEAD revision is annotated. Unknown
174 + arguments are passed directly to git-blame.
175 +
173 -All arguments are passed directly to `git blame'.
176 +--git-format;;
177 + Produce output in the same format as `git blame', but with
178 + SVN revision numbers instead of git commit hashes. In this mode,
179 + changes that haven't been committed to SVN (including local
180 + working-copy edits) are shown as revision 0.
181
182 --
183 'find-rev'::
git-svn.perl
+44 -11
@@ -65,7 +65,8 @@ my ($_stdin, $_help, $_edit,
65 $_template, $_shared,
66 $_version, $_fetch_all, $_no_rebase,
67 $_merge, $_strategy, $_dry_run, $_local,
68 - $_prefix, $_no_checkout, $_url, $_verbose);
68 + $_prefix, $_no_checkout, $_url, $_verbose,
69 + $_git_format);
70 $Git::SVN::_follow_parent = 1;
71 my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
72 'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -188,7 +189,7 @@ my %cmd = (
189 { 'url' => \$_url, } ],
190 'blame' => [ \&Git::SVN::Log::cmd_blame,
191 "Show what revision and author last modified each line of a file",
191 - {} ],
192 + { 'git-format' => \$_git_format } ],
193 );
194
195 my $cmd;
@@ -225,7 +226,7 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
226 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
227
228 read_repo_config(\%opts);
228 -Getopt::Long::Configure('pass_through') if ($cmd && $cmd eq 'log');
229 +Getopt::Long::Configure('pass_through') if ($cmd && ($cmd eq 'log' || $cmd eq 'blame'));
230 my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
231 'minimize-connections' => \$Git::SVN::Migration::_minimize,
232 'id|i=s' => \$Git::SVN::default_ref_id,
@@ -4468,19 +4469,51 @@ out:
4469 }
4470
4471 sub cmd_blame {
4471 - my $path = shift;
4472 + my $path = pop;
4473
4474 config_pager();
4475 run_pager();
4476
4476 - my ($fh, $ctx) = command_output_pipe('blame', @_, $path);
4477 - while (my $line = <$fh>) {
4478 - if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
4479 - my (undef, $rev, undef) = ::cmt_metadata($1);
4480 - $rev = sprintf('%-10s', $rev);
4481 - $line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
4477 + my ($fh, $ctx, $rev);
4478 +
4479 + if ($_git_format) {
4480 + ($fh, $ctx) = command_output_pipe('blame', @_, $path);
4481 + while (my $line = <$fh>) {
4482 + if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
4483 + # Uncommitted edits show up as a rev ID of
4484 + # all zeros, which we can't look up with
4485 + # cmt_metadata
4486 + if ($1 !~ /^0+$/) {
4487 + (undef, $rev, undef) =
4488 + ::cmt_metadata($1);
4489 + $rev = '0' if (!$rev);
4490 + } else {
4491 + $rev = '0';
4492 + }
4493 + $rev = sprintf('%-10s', $rev);
4494 + $line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
4495 + }
4496 + print $line;
4497 + }
4498 + } else {
4499 + ($fh, $ctx) = command_output_pipe('blame', '-p', @_, 'HEAD',
4500 + '--', $path);
4501 + my ($sha1);
4502 + my %authors;
4503 + while (my $line = <$fh>) {
4504 + if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) {
4505 + $sha1 = $1;
4506 + (undef, $rev, undef) = ::cmt_metadata($1);
4507 + $rev = '0' if (!$rev);
4508 + }
4509 + elsif ($line =~ /^author (.*)/) {
4510 + $authors{$rev} = $1;
4511 + $authors{$rev} =~ s/\s/_/g;
4512 + }
4513 + elsif ($line =~ /^\t(.*)$/) {
4514 + printf("%6s %10s %s\n", $rev, $authors{$rev}, $1);
4515 + }
4516 }
4483 - print $line;
4517 }
4518 command_close_pipe($fh, $ctx);
4519 }