summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--TODO3
-rw-r--r--manual.txt3
-rw-r--r--tig.c60
4 files changed, 64 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 6109737b..d8e1468a 100644
--- 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 082c6378..1b887286 100644
--- 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.
diff --git a/manual.txt b/manual.txt
index 87f94925..fe4d311b 100644
--- a/manual.txt
+++ b/manual.txt
@@ -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 7997091c..095e9c6e 100644
--- 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");