threads / patch / 5827

patch, 6 partsgitweb: use blame --porcelain

Subject: [PATCH 6/6] gitweb: use blame --porcelain

## tl;dr

3 messages between Oct 5, 2006 and Oct 5, 2006. Diffs are folded; open one to read it.

replies: 2people: 1as markdown or json

Junio C Hamano· Oct 5, 2006, 21:07 UTC · lore

This makes gitweb (git_blame2) to use "blame --porcelain", which lets the caller to figure out which line in the original version each line comes from. Using this information, change the behaviour of clicking the line number to go to the line of the blame output for the original commit.

Before, clicking the line number meant "scoll up to show this line at the beginning of the page", which was not all that useful. The new behaviour lets you click on the line you are interested in to view the line in the context it was introduced, and keep digging deeper as you examine it.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 * I've tested this only very lightly but it seems to be quite
   pleasant to use.
 gitweb/gitweb.perl |   65 +++++++++++++++++++++++++++++++++++----------------
 1 files changed, 44 insertions(+), 21 deletions(-)
Show changes to gitweb/gitweb.perl +44 −21
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index d217187..29a56c3 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -971,6 +971,9 @@ sub parse_date {
 	$date{'hour_local'} = $hour;
 	$date{'minute_local'} = $min;
 	$date{'tz_local'} = $tz;
+	$date{'iso-tz'} = sprintf ("%04d-%02d-%02d %02d:%02d:%02d %s",
+				   1900+$year, $mon+1, $mday,
+				   $hour, $min, $sec, $tz);
 	return %date;
 }
 
@@ -2496,7 +2499,8 @@ sub git_blame2 {
 	if ($ftype !~ "blob") {
 		die_error("400 Bad Request", "Object is not a blob");
 	}
-	open ($fd, "-|", git_cmd(), "blame", '-l', '--', $file_name, $hash_base)
+	open ($fd, "-|", git_cmd(), "blame", '--porcelain', '--',
+	      $file_name, $hash_base)
 		or die_error(undef, "Open git-blame failed");
 	git_header_html();
 	my $formats_nav =
@@ -2520,33 +2524,52 @@ sub git_blame2 {
 <table class="blame">
 <tr><th>Commit</th><th>Line</th><th>Data</th></tr>
 HTML
-	while (<$fd>) {
-		my ($full_rev, $author, $date, $lineno, $data) =
-			/^([0-9a-f]{40}).*?\s\((.*?)\s+([-\d]+ [:\d]+ [-+\d]+)\s+(\d+)\)\s(.*)/;
+	my %metainfo = ();
+	while (1) {
+		$_ = <$fd>;
+		last unless defined $_;
+		my ($full_rev, $lineno, $orig_lineno, $group_size) =
+		    /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/;
+		if (!exists $metainfo{$full_rev}) {
+			$metainfo{$full_rev} = {};
+		}
+		my $meta = $metainfo{$full_rev};
+		while (<$fd>) {
+			last if (s/^\t//);
+			if (/^(\S+) (.*)$/) {
+				$meta->{$1} = $2;
+			}
+		}
+		my $data = $_;
 		my $rev = substr($full_rev, 0, 8);
-		my $print_c8 = 0;
-
-		if (!defined $last_rev) {
-			$last_rev = $full_rev;
-			$print_c8 = 1;
-		} elsif ($last_rev ne $full_rev) {
-			$last_rev = $full_rev;
+		my $author = $meta->{'author'};
+		my %date = parse_date($meta->{'author-time'},
+				      $meta->{'author-tz'});
+		my $date = $date{'iso-tz'};
+		if ($group_size) {
 			$current_color = ++$current_color % $num_colors;
-			$print_c8 = 1;
 		}
 		print "<tr class=\"$rev_color[$current_color]\">\n";
-		print "<td class=\"sha1\"";
-		if ($print_c8 == 1) {
+		if ($group_size) {
+			print "<td class=\"sha1\"";
 			print " title=\"$author, $date\"";
-		}
-		print ">";
-		if ($print_c8 == 1) {
-			print $cgi->a({-href => href(action=>"commit", hash=>$full_rev, file_name=>$file_name)},
+			print " rowspan=\"$group_size\"" if ($group_size > 1);
+			print ">";
+			print $cgi->a({-href => href(action=>"commit",
+						     hash=>$full_rev,
+						     file_name=>$file_name)},
 				      esc_html($rev));
+			print "</td>\n";
 		}
-		print "</td>\n";
-		print "<td class=\"linenr\"><a id=\"l$lineno\" href=\"#l$lineno\" class=\"linenr\">" .
-		      esc_html($lineno) . "</a></td>\n";
+		my $blamed = href(action => 'blame',
+				  file_name => $meta->{'filename'},
+				  hash_base => $full_rev);
+		print "<td class=\"linenr\">";
+		print $cgi->a({ -href => "$blamed#l$lineno",
+				-id => "l$lineno",
+				-class => "linenr" },
+			      esc_html($lineno));
+		print "</td>";
 		print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
 		print "</tr>\n";
 	}
-- 
1.4.2.3.g866f3
Junio C Hamano· Oct 5, 2006, 21:18 UTC · re: Junio C Hamano · lore

Re: [PATCH 6/6] gitweb: use blame --porcelain

Side note.

This change does not give any more information (other than the link to the corresponding line in the original version) than the current gitweb in "next", but "blame --porcelain" returns richer information than it used to be available, most notably the summary line. It might be interesting to enhance the title pop-up mechanism to show them on mouse-over, but I was too lazy ;-).

I've considered making the commit-8 link to link not to the commit page for the originating commit but to the corresponding line in the blame page for it, but opted to take over the line number link, which was serving far less useful purpose. Your keyboard has PgUp and PgDn to let you navigate within the same blame output.

As I noted in the log message for [3/6], I suspect that the curent implementation to show the original line number is unnecessarily inefficient. Improvement is much encouraged. Again, I am too lazy to look into it right now.

Junio C Hamano· Oct 5, 2006, 21:48 UTC · re: Junio C Hamano · lore

Re: [PATCH 6/6] gitweb: use blame --porcelain

Found a stupid typo...
Show changes to gitweb/gitweb.perl +1 −1
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index feb768f..8b97357 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -2589,7 +2589,7 @@ HTML
 				  file_name => $meta->{'filename'},
 				  hash_base => $full_rev);
 		print "<td class=\"linenr\">";
-		print $cgi->a({ -href => "$blamed#l$lineno",
+		print $cgi->a({ -href => "$blamed#l$orig_lineno",
 				-id => "l$lineno",
 				-class => "linenr" },
 			      esc_html($lineno));

← back to recent threads