git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add svn-compatible "blame" output format to git-svn
@ 2008-05-10 21:25 Steven Grimm
  2008-05-11  2:36 ` Junio C Hamano
  0 siblings, 1 reply; 6+ messages in thread
From: Steven Grimm @ 2008-05-10 21:25 UTC (permalink / raw)
  To: git

git-svn blame produces 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 blame.

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>
---

	I'd actually argue that the svn-compatible format should be the
	default one, with git-compatible available as an option, but if
	there are existing scripts that consume git-svn blame's output,
	I don't want to break them.

	I suspect there aren't any since git-svn blame is relatively new.

 Documentation/git-svn.txt |   11 ++++++++-
 git-svn.perl              |   51 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index f4ba105..8071347 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -168,9 +168,16 @@ Any other arguments are passed directly to `git log'
 'blame'::
        Show what revision and author last modified each line of a file. This is
        identical to `git blame', but SVN revision numbers are shown instead of git
-       commit hashes.
+       commit hashes. Changes that haven't been committed to SVN yet are
+       listed as SVN revision 0.
 +
-All arguments are passed directly to `git blame'.
+All arguments are passed directly to `git blame', except the following:
++
+--svn-format;;
+	Produce output in the same format as `svn blame'. In this mode,
+	uncommitted changes in the working copy are ignored (the version
+	of the file from the HEAD revision is annotated) and whitespace
+	characters in author names are replaced with underscores.
 
 --
 'find-rev'::
diff --git a/git-svn.perl b/git-svn.perl
index e47b1ea..9570deb 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -65,7 +65,8 @@ my ($_stdin, $_help, $_edit,
 	$_template, $_shared,
 	$_version, $_fetch_all, $_no_rebase,
 	$_merge, $_strategy, $_dry_run, $_local,
-	$_prefix, $_no_checkout, $_url, $_verbose);
+	$_prefix, $_no_checkout, $_url, $_verbose,
+	$_svn_format);
 $Git::SVN::_follow_parent = 1;
 my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
                     'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -188,7 +189,7 @@ my %cmd = (
 		    { 'url' => \$_url, } ],
 	'blame' => [ \&Git::SVN::Log::cmd_blame,
 	            "Show what revision and author last modified each line of a file",
-	            {} ],
+		    { 'svn-format' => \$_svn_format } ],
 );
 
 my $cmd;
@@ -4473,14 +4474,46 @@ sub cmd_blame {
 	config_pager();
 	run_pager();
 
-	my ($fh, $ctx) = command_output_pipe('blame', @_, $path);
-	while (my $line = <$fh>) {
-		if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
-			my (undef, $rev, undef) = ::cmt_metadata($1);
-			$rev = sprintf('%-10s', $rev);
-			$line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
+	my ($fh, $ctx, $rev);
+
+	if ($_svn_format) {
+		($fh, $ctx) = command_output_pipe('blame', @_, '-p', 'HEAD',
+						     '--', $path);
+		my ($sha1);
+		my %authors;
+		while (my $line = <$fh>) {
+			if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) {
+				$sha1 = $1;
+				(undef, $rev, undef) = ::cmt_metadata($1);
+				$rev = '0' if (!$rev);
+			}
+			elsif ($line =~ /^author (.*)/) {
+				$authors{$rev} = $1;
+				$authors{$rev} =~ s/\s/_/g;
+			}
+			elsif ($line =~ /^\t(.*)$/) {
+				printf("%6s %10s %s\n", $rev, $authors{$rev}, $1);
+			}
+		}
+	} else {
+		($fh, $ctx) = command_output_pipe('blame', @_, $path);
+		while (my $line = <$fh>) {
+			if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
+				# Uncommitted edits show up as a rev ID of
+				# all zeros, which we can't look up with
+				# cmt_metadata
+				if ($1 !~ /^0+$/) {
+					(undef, $rev, undef) =
+						::cmt_metadata($1);
+					$rev = '0' if (!$rev);
+				} else {
+					$rev = '0';
+				}
+				$rev = sprintf('%-10s', $rev);
+				$line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
+			}
+			print $line;
 		}
-		print $line;
 	}
 	command_close_pipe($fh, $ctx);
 }
-- 
1.5.5.49.gf43e2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add svn-compatible "blame" output format to git-svn
  2008-05-10 21:25 [PATCH] Add svn-compatible "blame" output format to git-svn Steven Grimm
@ 2008-05-11  2:36 ` Junio C Hamano
  2008-05-11  5:11   ` [PATCH v2] " Steven Grimm
  2008-05-11  6:36   ` [PATCH] " Teemu Likonen
  0 siblings, 2 replies; 6+ messages in thread
From: Junio C Hamano @ 2008-05-11  2:36 UTC (permalink / raw)
  To: Steven Grimm; +Cc: git

Steven Grimm <koreth@midwinter.com> writes:

> git-svn blame produces 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 blame.
>
> 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>
> ---
>
> 	I'd actually argue that the svn-compatible format should be the
> 	default one, with git-compatible available as an option.

I'd violently agree with it.

List, objections?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] Add svn-compatible "blame" output format to git-svn
  2008-05-11  2:36 ` Junio C Hamano
@ 2008-05-11  5:11   ` Steven Grimm
  2008-05-11  7:42     ` Eric Wong
  2008-05-11  6:36   ` [PATCH] " Teemu Likonen
  1 sibling, 1 reply; 6+ messages in thread
From: Steven Grimm @ 2008-05-11  5:11 UTC (permalink / raw)
  To: git

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>
---

	The svn-compatible format is now the default.

 Documentation/git-svn.txt |   15 +++++++++---
 git-svn.perl              |   55 ++++++++++++++++++++++++++++++++++++---------
 2 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index f4ba105..c6b56b4 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -166,11 +166,18 @@ environment). This command has the same behaviour.
 Any other arguments are passed directly to `git log'
 
 'blame'::
-       Show what revision and author last modified each line of a file. This is
-       identical to `git blame', but SVN revision numbers are shown instead of git
-       commit hashes.
+       Show what revision and author last modified each line of a file. The
+       output of this mode is format-compatible with the output of
+       `svn blame' by default. Like the SVN blame command,
+       local uncommitted changes in the working copy are ignored;
+       the version of the file in the HEAD revision is annotated. Unknown
+       arguments are passed directly to git-blame.
 +
-All arguments are passed directly to `git blame'.
+--git-format;;
+	Produce output in the same format as `git blame', but with
+	SVN revision numbers instead of git commit hashes. In this mode,
+	changes that haven't been committed to SVN (including local
+	working-copy edits) are shown as revision 0.
 
 --
 'find-rev'::
diff --git a/git-svn.perl b/git-svn.perl
index e47b1ea..77f880e 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -65,7 +65,8 @@ my ($_stdin, $_help, $_edit,
 	$_template, $_shared,
 	$_version, $_fetch_all, $_no_rebase,
 	$_merge, $_strategy, $_dry_run, $_local,
-	$_prefix, $_no_checkout, $_url, $_verbose);
+	$_prefix, $_no_checkout, $_url, $_verbose,
+	$_git_format);
 $Git::SVN::_follow_parent = 1;
 my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
                     'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -188,7 +189,7 @@ my %cmd = (
 		    { 'url' => \$_url, } ],
 	'blame' => [ \&Git::SVN::Log::cmd_blame,
 	            "Show what revision and author last modified each line of a file",
-	            {} ],
+		    { 'git-format' => \$_git_format } ],
 );
 
 my $cmd;
@@ -225,7 +226,7 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
 
 read_repo_config(\%opts);
-Getopt::Long::Configure('pass_through') if ($cmd && $cmd eq 'log');
+Getopt::Long::Configure('pass_through') if ($cmd && ($cmd eq 'log' || $cmd eq 'blame'));
 my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
                     'minimize-connections' => \$Git::SVN::Migration::_minimize,
                     'id|i=s' => \$Git::SVN::default_ref_id,
@@ -4468,19 +4469,51 @@ out:
 }
 
 sub cmd_blame {
-	my $path = shift;
+	my $path = pop;
 
 	config_pager();
 	run_pager();
 
-	my ($fh, $ctx) = command_output_pipe('blame', @_, $path);
-	while (my $line = <$fh>) {
-		if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
-			my (undef, $rev, undef) = ::cmt_metadata($1);
-			$rev = sprintf('%-10s', $rev);
-			$line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
+	my ($fh, $ctx, $rev);
+
+	if ($_git_format) {
+		($fh, $ctx) = command_output_pipe('blame', @_, $path);
+		while (my $line = <$fh>) {
+			if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
+				# Uncommitted edits show up as a rev ID of
+				# all zeros, which we can't look up with
+				# cmt_metadata
+				if ($1 !~ /^0+$/) {
+					(undef, $rev, undef) =
+						::cmt_metadata($1);
+					$rev = '0' if (!$rev);
+				} else {
+					$rev = '0';
+				}
+				$rev = sprintf('%-10s', $rev);
+				$line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
+			}
+			print $line;
+		}
+	} else {
+		($fh, $ctx) = command_output_pipe('blame', '-p', @_, 'HEAD',
+						  '--', $path);
+		my ($sha1);
+		my %authors;
+		while (my $line = <$fh>) {
+			if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) {
+				$sha1 = $1;
+				(undef, $rev, undef) = ::cmt_metadata($1);
+				$rev = '0' if (!$rev);
+			}
+			elsif ($line =~ /^author (.*)/) {
+				$authors{$rev} = $1;
+				$authors{$rev} =~ s/\s/_/g;
+			}
+			elsif ($line =~ /^\t(.*)$/) {
+				printf("%6s %10s %s\n", $rev, $authors{$rev}, $1);
+			}
 		}
-		print $line;
 	}
 	command_close_pipe($fh, $ctx);
 }
-- 
1.5.5.49.gf43e2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add svn-compatible "blame" output format to git-svn
  2008-05-11  2:36 ` Junio C Hamano
  2008-05-11  5:11   ` [PATCH v2] " Steven Grimm
@ 2008-05-11  6:36   ` Teemu Likonen
  2008-05-11 13:46     ` Tim Stoakes
  1 sibling, 1 reply; 6+ messages in thread
From: Teemu Likonen @ 2008-05-11  6:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Steven Grimm, git

Junio C Hamano wrote (2008-05-10 19:36 -0700):

> Steven Grimm <koreth@midwinter.com> writes:
> 
> > 	I'd actually argue that the svn-compatible format should be the
> > 	default one, with git-compatible available as an option.
> 
> I'd violently agree with it.

Me too!

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] Add svn-compatible "blame" output format to git-svn
  2008-05-11  5:11   ` [PATCH v2] " Steven Grimm
@ 2008-05-11  7:42     ` Eric Wong
  0 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2008-05-11  7:42 UTC (permalink / raw)
  To: Steven Grimm; +Cc: git, Junio C Hamano

Steven Grimm <koreth@midwinter.com> wrote:
> 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>

> ---
> 
> 	The svn-compatible format is now the default.
> 
>  Documentation/git-svn.txt |   15 +++++++++---
>  git-svn.perl              |   55 ++++++++++++++++++++++++++++++++++++---------
>  2 files changed, 55 insertions(+), 15 deletions(-)
> 
> diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
> index f4ba105..c6b56b4 100644
> --- a/Documentation/git-svn.txt
> +++ b/Documentation/git-svn.txt
> @@ -166,11 +166,18 @@ environment). This command has the same behaviour.
>  Any other arguments are passed directly to `git log'
>  
>  'blame'::
> -       Show what revision and author last modified each line of a file. This is
> -       identical to `git blame', but SVN revision numbers are shown instead of git
> -       commit hashes.
> +       Show what revision and author last modified each line of a file. The
> +       output of this mode is format-compatible with the output of
> +       `svn blame' by default. Like the SVN blame command,
> +       local uncommitted changes in the working copy are ignored;
> +       the version of the file in the HEAD revision is annotated. Unknown
> +       arguments are passed directly to git-blame.
>  +
> -All arguments are passed directly to `git blame'.
> +--git-format;;
> +	Produce output in the same format as `git blame', but with
> +	SVN revision numbers instead of git commit hashes. In this mode,
> +	changes that haven't been committed to SVN (including local
> +	working-copy edits) are shown as revision 0.
>  
>  --
>  'find-rev'::
> diff --git a/git-svn.perl b/git-svn.perl
> index e47b1ea..77f880e 100755
> --- a/git-svn.perl
> +++ b/git-svn.perl
> @@ -65,7 +65,8 @@ my ($_stdin, $_help, $_edit,
>  	$_template, $_shared,
>  	$_version, $_fetch_all, $_no_rebase,
>  	$_merge, $_strategy, $_dry_run, $_local,
> -	$_prefix, $_no_checkout, $_url, $_verbose);
> +	$_prefix, $_no_checkout, $_url, $_verbose,
> +	$_git_format);
>  $Git::SVN::_follow_parent = 1;
>  my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
>                      'config-dir=s' => \$Git::SVN::Ra::config_dir,
> @@ -188,7 +189,7 @@ my %cmd = (
>  		    { 'url' => \$_url, } ],
>  	'blame' => [ \&Git::SVN::Log::cmd_blame,
>  	            "Show what revision and author last modified each line of a file",
> -	            {} ],
> +		    { 'git-format' => \$_git_format } ],
>  );
>  
>  my $cmd;
> @@ -225,7 +226,7 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
>  my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
>  
>  read_repo_config(\%opts);
> -Getopt::Long::Configure('pass_through') if ($cmd && $cmd eq 'log');
> +Getopt::Long::Configure('pass_through') if ($cmd && ($cmd eq 'log' || $cmd eq 'blame'));
>  my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
>                      'minimize-connections' => \$Git::SVN::Migration::_minimize,
>                      'id|i=s' => \$Git::SVN::default_ref_id,
> @@ -4468,19 +4469,51 @@ out:
>  }
>  
>  sub cmd_blame {
> -	my $path = shift;
> +	my $path = pop;
>  
>  	config_pager();
>  	run_pager();
>  
> -	my ($fh, $ctx) = command_output_pipe('blame', @_, $path);
> -	while (my $line = <$fh>) {
> -		if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
> -			my (undef, $rev, undef) = ::cmt_metadata($1);
> -			$rev = sprintf('%-10s', $rev);
> -			$line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
> +	my ($fh, $ctx, $rev);
> +
> +	if ($_git_format) {
> +		($fh, $ctx) = command_output_pipe('blame', @_, $path);
> +		while (my $line = <$fh>) {
> +			if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
> +				# Uncommitted edits show up as a rev ID of
> +				# all zeros, which we can't look up with
> +				# cmt_metadata
> +				if ($1 !~ /^0+$/) {
> +					(undef, $rev, undef) =
> +						::cmt_metadata($1);
> +					$rev = '0' if (!$rev);
> +				} else {
> +					$rev = '0';
> +				}
> +				$rev = sprintf('%-10s', $rev);
> +				$line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
> +			}
> +			print $line;
> +		}
> +	} else {
> +		($fh, $ctx) = command_output_pipe('blame', '-p', @_, 'HEAD',
> +						  '--', $path);
> +		my ($sha1);
> +		my %authors;
> +		while (my $line = <$fh>) {
> +			if ($line =~ /^([[:xdigit:]]{40})\s\d+\s\d+/) {
> +				$sha1 = $1;
> +				(undef, $rev, undef) = ::cmt_metadata($1);
> +				$rev = '0' if (!$rev);
> +			}
> +			elsif ($line =~ /^author (.*)/) {
> +				$authors{$rev} = $1;
> +				$authors{$rev} =~ s/\s/_/g;
> +			}
> +			elsif ($line =~ /^\t(.*)$/) {
> +				printf("%6s %10s %s\n", $rev, $authors{$rev}, $1);
> +			}
>  		}
> -		print $line;
>  	}
>  	command_close_pipe($fh, $ctx);
>  }
> -- 
> 1.5.5.49.gf43e2

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add svn-compatible "blame" output format to git-svn
  2008-05-11  6:36   ` [PATCH] " Teemu Likonen
@ 2008-05-11 13:46     ` Tim Stoakes
  0 siblings, 0 replies; 6+ messages in thread
From: Tim Stoakes @ 2008-05-11 13:46 UTC (permalink / raw)
  To: Teemu Likonen; +Cc: Junio C Hamano, Steven Grimm, git

Teemu Likonen(tlikonen@iki.fi)@110508-09:36:
> Junio C Hamano wrote (2008-05-10 19:36 -0700):
> 
> > Steven Grimm <koreth@midwinter.com> writes:
> > 
> > > 	I'd actually argue that the svn-compatible format should be the
> > > 	default one, with git-compatible available as an option.
> > 
> > I'd violently agree with it.
> 
> Me too!

Likewise, thanks for completing this code.

Tim

-- 
Tim Stoakes

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-05-11 14:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-10 21:25 [PATCH] Add svn-compatible "blame" output format to git-svn Steven Grimm
2008-05-11  2:36 ` Junio C Hamano
2008-05-11  5:11   ` [PATCH v2] " Steven Grimm
2008-05-11  7:42     ` Eric Wong
2008-05-11  6:36   ` [PATCH] " Teemu Likonen
2008-05-11 13:46     ` Tim Stoakes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).