git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [tig PATCH] fix off-by-one on parent selection

From
Jeff King <peff@peff.net>
Date
May 23, 2010, 07:55 UTC
Message-ID
<20100523075503.GA24598@coredump.intra.peff.net>
In-Reply-To
<20100523074051.GA16730@coredump.intra.peff.net>
On Sun, May 23, 2010 at 03:40:52AM -0400, Jeff King wrote:
> Now try "tig blame new". For all of the lines but the first, blaming the
> parent gets you the correct "The selected commit has no parents". But
> parent-blaming the first line will correctly re-blame using the filename
> "old".
By the way, there is one minor bug remaining after this patch:
Show 11 quoted lines
>  	case REQ_PARENT:
>  		if (check_blame_commit(blame, TRUE) &&
> -		    select_commit_parent(blame->commit->id, opt_ref,
> -					 blame->commit->filename)) {
> -			string_copy(opt_file, blame->commit->filename);
> +		    select_commit_parent(blame->commit->id, opt_ref) &&
> +		    follow_parent_rename(blame->commit->id, opt_ref,
> +					 blame->commit->filename, opt_file)) {
>  			setup_blame_parent_line(view, blame);
>  			open_view(view, REQ_VIEW_BLAME, OPEN_REFRESH);
>  		}

We may write some new filename into opt_file in the follow_parent_rename call, but setup_blame_parent_line always diffs the original file. Which means we lose the line position when following a rename.

We need to do the equivalent of:
  git diff -U0 \
    opt_ref:opt_file \
    blame->commit->id:blame->commit->filename

IOW, to blame directly between the two blobs. Sadly, I don't think there is a plumbing command to do this, so we are stuck using regular "git diff", which may have surprises in the config.

The patch below works for my simple tests. I think we probably want to be doing this anyway for the multiple-parent case. I didn't test, but I don't think that diff-tree invocation is going to produce any output for a merge commit.

diff --git a/tig.c b/tig.c
index cfa26ce..4388c2f 100644
--- a/tig.c
+++ b/tig.c
@@ -5177,15 +5177,21 @@ check_blame_commit(struct blame *blame, bool check_null_id)
 static void
 setup_blame_parent_line(struct view *view, struct blame *blame)
 {
+	char from[SIZEOF_REF+SIZEOF_STR];
+	char to[SIZEOF_REF+SIZEOF_STR];
 	const char *diff_tree_argv[] = {
-		"git", "diff-tree", "-U0", blame->commit->id,
-			"--", blame->commit->filename, NULL
+		"git", "diff", "--no-textconv", "--no-extdiff", "--no-color",
+		"-U0", from, to, "--", NULL
 	};
 	struct io io = {};
 	int parent_lineno = -1;
 	int blamed_lineno = -1;
 	char *line;
 
+	snprintf(from, sizeof(from), "%s:%s", opt_ref, opt_file);
+	snprintf(to, sizeof(to), "%s:%s", blame->commit->id,
+		 blame->commit->filename);
+
 	if (!io_run(&io, diff_tree_argv, NULL, IO_RD))
 		return;
 
Previous: Jeff KingNext: Jonas Fonseca
Message 4 of 9 in “fix off-by-one on parent selection”
  1. fix off-by-one on parent selectionJeff King, May 10, 2010
  2. Jonas FonsecaMay 22, 2010
  3. Jeff KingMay 23, 2010
  4. Jeff KingMay 23, 2010
  5. Improve parent blame to detect renames by using the previous informationJonas Fonseca, Jun 5, 2010
  6. Jonas FonsecaJun 5, 2010
  7. Jeff KingJun 6, 2010
  8. Jonas FonsecaJun 9, 2010
  9. Jonas FonsecaJun 10, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.