blame: handle --first-parent

The revision.c options-parser will parse "--first-parent" for us, but the blame code does not actually respect it, as we simply iterate over the whole list returned by first_scapegoat(). We can fix this by returning a truncated parent list. Note that we could technically also do so by limiting the return value of num_scapegoats(), but that is less robust. We would rely on nobody ever looking at the "next" pointer from the returned list. Combining "--reverse" with "--first-parent" is more complicated, and will probably involve cooperation from revision.c. Since the desired semantics are not even clear, let's punt on this for now, but explicitly disallow it to avoid confusing users (this is not really a regression, since it did something nonsensical before). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Sep 15, 2015 at 06:05 UTC 95a4fb0eac20de024fed242a7c9227af86334202
2 files changed +14 -1
builtin/blame.c
+10 -1
@@ -1365,8 +1365,15 @@ static void pass_whole_blame(struct scoreboard *sb,
1365 */
1366 static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit)
1367 {
1368 - if (!reverse)
1368 + if (!reverse) {
1369 + if (revs->first_parent_only &&
1370 + commit->parents &&
1371 + commit->parents->next) {
1372 + free_commit_list(commit->parents->next);
1373 + commit->parents->next = NULL;
1374 + }
1375 return commit->parents;
1376 + }
1377 return lookup_decoration(&revs->children, &commit->object);
1378 }
1379
@@ -2677,6 +2684,8 @@ parse_done:
2684 }
2685 else if (contents_from)
2686 die("--contents and --children do not blend well.");
2687 + else if (revs.first_parent_only)
2688 + die("combining --first-parent and --reverse is not supported");
2689 else {
2690 final_commit_name = prepare_initial(&sb);
2691 sb.commits.compare = compare_commits_by_reverse_commit_date;
t/annotate-tests.sh
+4
@@ -111,6 +111,10 @@ test_expect_success 'blame 2 authors + 2 merged-in authors' '
111 check_count A 2 B 1 B1 2 B2 1
112 '
113
114 +test_expect_success 'blame --first-parent blames merge for branch1' '
115 + check_count --first-parent A 2 B 1 "A U Thor" 2 B2 1
116 +'
117 +
118 test_expect_success 'blame ancestor' '
119 check_count -h master A 2 B 2
120 '