diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2013-03-13 18:42:52 +0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-03-16 22:11:02 -0700 |
commit | b397ea4863a143e97cb9da76c6c18cc555537d64 (patch) | |
tree | 3b3c8fdaca654e980e4dc108b0d8674c4220c9fa /wt-status.c | |
parent | 3b691cccb02e660002a7ff414ad21ddac932dc6c (diff) | |
download | git-b397ea4863a143e97cb9da76c6c18cc555537d64.tar.gz |
status: show more info than "currently not on any branch"
When a remote ref or a tag is checked out, HEAD is automatically
detached. There is no user-friendly way to find out what ref is
checked out in this case. This patch digs in reflog for this
information and shows "HEAD detached from origin/master" or "HEAD
detached at v1.8.0" instead of "currently not on any branch".
When it cannot figure out the original ref, it shows an abbreviated
SHA-1. "Currently not on any branch" would never display (unless
reflog is pruned to near empty that the last checkout entry is lost).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'wt-status.c')
-rw-r--r-- | wt-status.c | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/wt-status.c b/wt-status.c index 40dced3ef9..32a51e1323 100644 --- a/wt-status.c +++ b/wt-status.c @@ -999,7 +999,73 @@ got_nothing: return NULL; } -void wt_status_get_state(struct wt_status_state *state) +struct grab_1st_switch_cbdata { + int found; + struct strbuf buf; + unsigned char nsha1[20]; +}; + +static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1, + const char *email, unsigned long timestamp, int tz, + const char *message, void *cb_data) +{ + struct grab_1st_switch_cbdata *cb = cb_data; + const char *target = NULL, *end; + + if (prefixcmp(message, "checkout: moving from ")) + return 0; + message += strlen("checkout: moving from "); + target = strstr(message, " to "); + if (!target) + return 0; + target += strlen(" to "); + strbuf_reset(&cb->buf); + hashcpy(cb->nsha1, nsha1); + for (end = target; *end && *end != '\n'; end++) + ; + strbuf_add(&cb->buf, target, end - target); + cb->found = 1; + return 1; +} + +static void wt_status_get_detached_from(struct wt_status_state *state) +{ + struct grab_1st_switch_cbdata cb; + struct commit *commit; + unsigned char sha1[20]; + char *ref = NULL; + + strbuf_init(&cb.buf, 0); + if (for_each_reflog_ent_reverse("HEAD", grab_1st_switch, &cb) <= 0) { + strbuf_release(&cb.buf); + return; + } + + if (dwim_ref(cb.buf.buf, cb.buf.len, sha1, &ref) == 1 && + /* sha1 is a commit? match without further lookup */ + (!hashcmp(cb.nsha1, sha1) || + /* perhaps sha1 is a tag, try to dereference to a commit */ + ((commit = lookup_commit_reference_gently(sha1, 1)) != NULL && + !hashcmp(cb.nsha1, commit->object.sha1)))) { + int ofs; + if (!prefixcmp(ref, "refs/tags/")) + ofs = strlen("refs/tags/"); + else if (!prefixcmp(ref, "refs/remotes/")) + ofs = strlen("refs/remotes/"); + else + ofs = 0; + state->detached_from = xstrdup(ref + ofs); + } else + state->detached_from = + xstrdup(find_unique_abbrev(cb.nsha1, DEFAULT_ABBREV)); + hashcpy(state->detached_sha1, cb.nsha1); + + free(ref); + strbuf_release(&cb.buf); +} + +void wt_status_get_state(struct wt_status_state *state, + int get_detached_from) { struct stat st; @@ -1029,6 +1095,9 @@ void wt_status_get_state(struct wt_status_state *state) state->bisect_in_progress = 1; state->branch = read_and_strip_branch("BISECT_START"); } + + if (get_detached_from) + wt_status_get_detached_from(state); } static void wt_status_print_state(struct wt_status *s, @@ -1054,7 +1123,8 @@ void wt_status_print(struct wt_status *s) struct wt_status_state state; memset(&state, 0, sizeof(state)); - wt_status_get_state(&state); + wt_status_get_state(&state, + s->branch && !strcmp(s->branch, "HEAD")); if (s->branch) { const char *on_what = _("On branch "); @@ -1062,9 +1132,19 @@ void wt_status_print(struct wt_status *s) if (!prefixcmp(branch_name, "refs/heads/")) branch_name += 11; else if (!strcmp(branch_name, "HEAD")) { - branch_name = ""; branch_status_color = color(WT_STATUS_NOBRANCH, s); - on_what = _("Not currently on any branch."); + if (state.detached_from) { + unsigned char sha1[20]; + branch_name = state.detached_from; + if (!get_sha1("HEAD", sha1) && + !hashcmp(sha1, state.detached_sha1)) + on_what = _("HEAD detached at "); + else + on_what = _("HEAD detached from "); + } else { + branch_name = ""; + on_what = _("Not currently on any branch."); + } } status_printf(s, color(WT_STATUS_HEADER, s), ""); status_printf_more(s, branch_status_color, "%s", on_what); @@ -1076,6 +1156,7 @@ void wt_status_print(struct wt_status *s) wt_status_print_state(s, &state); free(state.branch); free(state.onto); + free(state.detached_from); if (s->is_initial) { status_printf_ln(s, color(WT_STATUS_HEADER, s), ""); |