Code

Blame view: add guesstimation of line number when blaming parent commit
authorJonas Fonseca <fonseca@diku.dk>
Sat, 7 Feb 2009 15:22:56 +0000 (16:22 +0100)
committerJonas Fonseca <fonseca@diku.dk>
Sat, 7 Feb 2009 21:45:43 +0000 (22:45 +0100)
... by looking through the commit's diff for the hunk which introduced
the line. Also, try to set the filename properly.

tig.c

diff --git a/tig.c b/tig.c
index fb6231f256fbbfbcbb1545dc7caaa6d0a69dd3c1..04a44db37ec0d11dfe33e5bda4be1b83fb3da151 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -4413,6 +4413,42 @@ check_blame_commit(struct blame *blame)
        return FALSE;
 }
 
+static void
+setup_blame_parent_line(struct view *view, struct blame *blame)
+{
+       const char *diff_tree_argv[] = {
+               "git", "diff-tree", "-U0", blame->commit->id,
+                       "--", blame->commit->filename, NULL
+       };
+       struct io io = {};
+       int parent_lineno = -1;
+       int blamed_lineno = -1;
+       char *line;
+
+       if (!run_io(&io, diff_tree_argv, NULL, IO_RD))
+               return;
+
+       while ((line = io_get(&io, '\n', TRUE))) {
+               if (*line == '@') {
+                       char *pos = strchr(line, '+');
+
+                       parent_lineno = atoi(line + 4);
+                       if (pos)
+                               blamed_lineno = atoi(pos + 1);
+
+               } else if (*line == '+' && parent_lineno != -1) {
+                       if (blame->lineno == blamed_lineno - 1 &&
+                           !strcmp(blame->text, line + 1)) {
+                               view->lineno = parent_lineno ? parent_lineno - 1 : 0;
+                               break;
+                       }
+                       blamed_lineno++;
+               }
+       }
+
+       done_io(&io);
+}
+
 static enum request
 blame_request(struct view *view, enum request request, struct line *line)
 {
@@ -4432,8 +4468,11 @@ blame_request(struct view *view, enum request request, struct line *line)
 
        case REQ_PARENT:
                if (check_blame_commit(blame) &&
-                   select_commit_parent(blame->commit->id, opt_ref))
+                   select_commit_parent(blame->commit->id, opt_ref)) {
+                       string_copy(opt_file, blame->commit->filename);
+                       setup_blame_parent_line(view, blame);
                        open_view(view, REQ_VIEW_BLAME, OPEN_REFRESH);
+               }
                break;
 
        case REQ_ENTER: