From cfce3774e50b9d8024ad24e64332b087862a93c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Fri, 12 Nov 2021 13:15:41 +0100 Subject: [PATCH 1/3] Add support for passing options and specify filenames --- README.md | 14 ++++++++++++++ git-diff-blame | 45 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d007315..fc12beb 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,20 @@ Annotates each line in a diff hunk with author and commit information like blame. +## Usage + +```shell +git diff-blame [oldrev [newrev [options] [-- [file1] [file2] [file3] ...]]] +``` + +There is support for passing on options to `git diff` but they must be given +after `oldrev` and `newrev` if they are present. E.g. + +```shell +git diff-blame HEAD^ HEAD -w +git diff-blame --cached -- myfile.c +``` + ## Example: $ git diff-blame HEAD^ diff --git a/git-diff-blame b/git-diff-blame index faf7075..d766c30 100755 --- a/git-diff-blame +++ b/git-diff-blame @@ -7,6 +7,8 @@ # binary, for any purpose, commercial or non-commercial, and by any # means. +use List::Util qw(first); + sub parse_hunk_header { my ($line) = @_; my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) = @@ -27,12 +29,36 @@ $git_root =~ s/^\s+//; $git_root =~ s/\s+$//; chdir($git_root) or die "$!"; -my ($oldrev, $newrev) = @ARGV; -$oldrev ||= 'HEAD'; -if ($newrev) { - open($diff, '-|', 'git', '--no-pager', 'diff', $oldrev, $newrev) or die; +my ($oldrev, $newrev, @REST); + +# First check if file arguments are present. +my $index = first { $ARGV[$_] eq '--' } 0..$#ARGV; +if (defined $index) { + ($oldrev, $newrev) = @ARGV[0 .. $index-1]; + @REST = @ARGV[$index .. $#ARGV]; +} else { + ($oldrev, $newrev, @REST) = @ARGV; +} + +# Then check if any of the revisons accidentally were assigned git diff option values. +if (defined $newrev && $newrev =~ /^-/) { + unshift(@REST, $newrev); + $newrev = undef; +} + +if (defined $oldrev && $oldrev =~ /^-/) { + unshift(@REST, $oldrev); + $oldrev = undef; +} + +if (defined $oldrev) { + if (defined $newrev) { + open($diff, '-|', 'git', '--no-pager', 'diff', $oldrev, $newrev, @REST) or die; + } else { + open($diff, '-|', 'git', '--no-pager', 'diff', $oldrev, @REST) or die; + } } else { - open($diff, '-|', 'git', '--no-pager', 'diff', $oldrev) or die; + open($diff, '-|', 'git', '--no-pager', 'diff', @REST) or die; } my ($pre, $post); @@ -63,8 +89,13 @@ while (<$diff>) { my $o_end = $o_ofs + $o_cnt - 1; my $n_end = $n_ofs + $n_cnt - 1; if (!$create) { - open($pre, '-|', 'git', 'blame', '-M', "-L$o_ofs,$o_end", - $oldrev, '--', $prefilename) or die; + if ($oldrev) { + open($pre, '-|', 'git', 'blame', '-M', "-L$o_ofs,$o_end", + $oldrev, '--', $prefilename) or die; + } else { + open($pre, '-|', 'git', 'blame', '-M', "-L$o_ofs,$o_end", + 'HEAD', '--', $prefilename) or die; + } } if (!$delete) { if ($newrev) { From 56d8e9ef538ad1f05ea3d3308892a290c8d8f868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Tue, 8 Dec 2020 14:42:31 +0100 Subject: [PATCH 2/3] Fix "Use of uninitialized" warning https://github.com/dmnd/git-diff-blame/issues/7 --- git-diff-blame | 1 + 1 file changed, 1 insertion(+) diff --git a/git-diff-blame b/git-diff-blame index d766c30..4256855 100755 --- a/git-diff-blame +++ b/git-diff-blame @@ -20,6 +20,7 @@ sub parse_hunk_header { sub get_blame_prefix { my ($line) = @_; + return "" if not $line; $line =~ /^(\^?[0-9a-f]+\s+(\S+\s+)?\([^\)]+\))/ or die "bad blame output: $line"; return $1; } From 1876951b6ca08139477d6d150a61edeea711e181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20L=C3=B8vdal?= Date: Tue, 8 Dec 2020 14:59:13 +0100 Subject: [PATCH 3/3] Let "git-diff-blame 1234 1234" behave like "git-diff-blame 1234^ 1234" It is so much more convinient to just paste a commit id twice with the mouse and inject a space inbetween compared to having to enter ^ which require multifinger operation, as well as requireing eiter using your non-dominant hand to enter or requirering moving hand from mouse to keyboard and back to mouse. --- git-diff-blame | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/git-diff-blame b/git-diff-blame index 4256855..570b496 100755 --- a/git-diff-blame +++ b/git-diff-blame @@ -52,6 +52,11 @@ if (defined $oldrev && $oldrev =~ /^-/) { $oldrev = undef; } +# 123abc 123abc --> 123abc^ 123abc +if (defined $oldrev && defined $newrev && $oldrev eq $newrev) { + $oldrev = $oldrev . "^"; +} + if (defined $oldrev) { if (defined $newrev) { open($diff, '-|', 'git', '--no-pager', 'diff', $oldrev, $newrev, @REST) or die;