Skip to content

Instantly share code, notes, and snippets.

@jrudolph
Created March 17, 2010 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrudolph/335471 to your computer and use it in GitHub Desktop.
Save jrudolph/335471 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl -w
# This is derived from the script posted by Thomas Rast in this mailing list post:
# http://n2.nabble.com/Blamming-a-diff-between-two-commits-td2340836.html
sub parse_hunk_header {
my ($line) = @_;
my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) =
$line =~ /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
$o_cnt = 1 unless defined $o_cnt;
$n_cnt = 1 unless defined $n_cnt;
return ($o_ofs, $o_cnt, $n_ofs, $n_cnt);
}
sub get_blame_prefix {
my ($line) = @_;
$line =~ /^(\^?[0-9a-f]+[^\(]+\([^\)]+\))/ or die "bad blame output: $line";
return $1;
}
my ($newrev) = @ARGV;
my $oldrev = "$newrev^";
open($diff, '-|', 'git', '--no-pager', 'diff', '-U0', '--diff-filter=MD', $oldrev, $newrev) or die;
my ($pre, $post);
my $filename;
print "Commit $newrev\n";
while (<$diff>) {
if (m{^diff --git ./(.*) ./\1$}) {
$filename = $1;
} elsif (m{^(\+\+\+|---) ./$filename$}) {
# ignore
} elsif (m{^@@ }) {
my ($o_ofs, $o_cnt, $n_ofs, $n_cnt)
= parse_hunk_header($_);
my $o_end = $o_ofs + $o_cnt;
my $n_end = $n_ofs + $n_cnt;
open($pre, '-|', 'git', 'blame', "-L$o_ofs,$o_end", $oldrev,'-w','-C','-M','-f',
'--', $filename) or die "$oldrev..$newrev";
} elsif (m{^ }) {
print get_blame_prefix(scalar <$pre>), "\t", $_;
scalar <$post>; # discard
} elsif (m{^\-}) {
print get_blame_prefix(scalar <$pre>), "\t", $_;
}
}
print "\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment