blame: dwim "blame --reverse OLD" as "blame --reverse OLD.."
Instead of always requiring both ends of a range, we could DWIM "OLD", which could be a misspelt "OLD..", to be a range that ends at the current commit. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Jun 14, 2016 at 11:41 UTC
e1d09701a4fa3a4d15dd005e2b698934e4ae9ae0
2 files changed
+41
-2
Documentation/blame-options.txt
+3
-2
@@ -28,12 +28,13 @@ include::line-range-format.txt[]
28
-S <revs-file>::
29
Use revisions from revs-file instead of calling linkgit:git-rev-list[1].
30
31
---reverse::
31
+--reverse <rev>..<rev>::
32
Walk history forward instead of backward. Instead of showing
33
the revision in which a line appeared, this shows the last
34
revision in which a line has existed. This requires a range of
35
revision like START..END where the path to blame exists in
36
- START.
36
+ START. `git blame --reverse START` is taken as `git blame
37
+ --reverse START..HEAD` for convenience.
38
39
-p::
40
--porcelain::
builtin/blame.c
+38
@@ -2447,6 +2447,41 @@ static char *prepare_final(struct scoreboard *sb)
2447
return xstrdup_or_null(name);
2448
}
2449
2450
+static const char *dwim_reverse_initial(struct scoreboard *sb)
2451
+{
2452
+ /*
2453
+ * DWIM "git blame --reverse ONE -- PATH" as
2454
+ * "git blame --reverse ONE..HEAD -- PATH" but only do so
2455
+ * when it makes sense.
2456
+ */
2457
+ struct object *obj;
2458
+ struct commit *head_commit;
2459
+ unsigned char head_sha1[20];
2460
+
2461
+ if (sb->revs->pending.nr != 1)
2462
+ return NULL;
2463
+
2464
+ /* Is that sole rev a committish? */
2465
+ obj = sb->revs->pending.objects[0].item;
2466
+ obj = deref_tag(obj, NULL, 0);
2467
+ if (obj->type != OBJ_COMMIT)
2468
+ return NULL;
2469
+
2470
+ /* Do we have HEAD? */
2471
+ if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL))
2472
+ return NULL;
2473
+ head_commit = lookup_commit_reference_gently(head_sha1, 1);
2474
+ if (!head_commit)
2475
+ return NULL;
2476
+
2477
+ /* Turn "ONE" into "ONE..HEAD" then */
2478
+ obj->flags |= UNINTERESTING;
2479
+ add_pending_object(sb->revs, &head_commit->object, "HEAD");
2480
+
2481
+ sb->final = (struct commit *)obj;
2482
+ return sb->revs->pending.objects[0].name;
2483
+}
2484
+
2485
static char *prepare_initial(struct scoreboard *sb)
2486
{
2487
int i;
@@ -2472,6 +2507,9 @@ static char *prepare_initial(struct scoreboard *sb)
2507
sb->final = (struct commit *) obj;
2508
final_commit_name = revs->pending.objects[i].name;
2509
}
2510
+
2511
+ if (!final_commit_name)
2512
+ final_commit_name = dwim_reverse_initial(sb);
2513
if (!final_commit_name)
2514
die("No commit to dig up from?");
2515
return xstrdup(final_commit_name);