Code

Add support for loading blame for parent commits
authorJonas Fonseca <fonseca@diku.dk>
Thu, 15 Jan 2009 21:41:58 +0000 (22:41 +0100)
committerJonas Fonseca <fonseca@diku.dk>
Tue, 27 Jan 2009 23:15:57 +0000 (00:15 +0100)
Requested by Jeff King in <20080410040213.GA29618@sigill.intra.peff.net>

NEWS
TODO
manual.txt
tig.c

diff --git a/NEWS b/NEWS
index 6109737b4b05f31a9e0897da398a89ca5beb7bb3..d8e1468ab2267ffe97cc9829137729d43466aebf 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,8 @@ Improvements:
  - Tree view: annotate entries with commit information.
  - Tree & blob view: open any blob in an editor.
  - Stage & main view: restore view position when reloading.
+ - Blame view: load blame for parent commit. For merge commits the parent
+   is queried. Bound to ',' by default via the existing "parent" action.
 
 Bug fixes:
 
diff --git a/TODO b/TODO
index 082c63787fd936e26fa1b04c9e545f2ba8a4883b..1b887286f6db2d1562d4dd1b3b9fae7fd07b0e02 100644 (file)
--- a/TODO
+++ b/TODO
@@ -28,6 +28,3 @@ Features that should be explored.
 
  - Blame view: Allow names in the author column to be abbreviated to
    initials. Will optimize screen usage for the blame view.
-
- - Blame view: make it possible to jump/load blame for parents. Idea by
-   Jeff King.
index 87f949250f165211d9b3d97942e049286192578c..fe4d311be4c5f0a30de3199ed7d1825325101ef3 100644 (file)
@@ -345,7 +345,8 @@ Up  This key is "context sensitive" and will move the cursor one \
        to display it.
 Down   Similar to 'Up' but will move down.
 ','    Move to parent. In the tree view, this means switch to the parent \
-       directory.
+       directory. In the blame view it will load blame for the parent \
+       commit. For merges the parent is queried.
 -----------------------------------------------------------------------------
 
 [[cursor-nav]]
diff --git a/tig.c b/tig.c
index 7997091c04e332843fac86ec69ad42658c3fb4d3..095e9c6e92e11dbd41c86e73b5569afdb914cdb4 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -3337,6 +3337,60 @@ parse_author_line(char *ident, char *author, size_t authorsize, struct tm *tm)
        }
 }
 
+static enum input_status
+select_commit_parent_handler(void *data, char *buf, int c)
+{
+       size_t parents = *(size_t *) data;
+       int parent = 0;
+
+       if (!isdigit(c))
+               return INPUT_SKIP;
+
+       if (*buf)
+               parent = atoi(buf) * 10;
+       parent += c - '0';
+
+       if (parent > parents)
+               return INPUT_SKIP;
+       return INPUT_OK;
+}
+
+static bool
+select_commit_parent(const char *id, char rev[SIZEOF_REV])
+{
+       char buf[SIZEOF_STR * 4];
+       const char *revlist_argv[] = {
+               "git", "rev-list", "-1", "--parents", id, NULL
+       };
+       int parents;
+
+       if (!run_io_buf(revlist_argv, buf, sizeof(buf)) ||
+           !*chomp_string(buf) ||
+           (parents = (strlen(buf) / 40) - 1) < 0) {
+               report("Failed to get parent information");
+               return FALSE;
+
+       } else if (parents == 0) {
+               report("The selected commit has no parents");
+               return FALSE;
+       }
+
+       if (parents > 1) {
+               char prompt[SIZEOF_STR];
+               char *result;
+
+               if (!string_format(prompt, "Which parent? [1..%d] ", parents))
+                       return FALSE;
+               result = prompt_input(prompt, select_commit_parent_handler, &parents);
+               if (!result)
+                       return FALSE;
+               parents = atoi(result);
+       }
+
+       string_copy_rev(rev, &buf[41 * parents]);
+       return TRUE;
+}
+
 /*
  * Pager backend
  */
@@ -4365,6 +4419,12 @@ blame_request(struct view *view, enum request request, struct line *line)
                }
                break;
 
+       case REQ_PARENT:
+               if (check_blame_commit(blame) &&
+                   select_commit_parent(blame->commit->id, opt_ref))
+                       open_view(view, REQ_VIEW_BLAME, OPEN_REFRESH);
+               break;
+
        case REQ_ENTER:
                if (!blame->commit) {
                        report("No commit loaded yet");