status: fix branch shown when not only bisecting

In 83c750acde (wt-status.*: better advice for git status added, 2012-06-05), git-status received new informative messages to describe the ongoing work in a worktree. These messages were enhanced in 0722c805d6 (status: show the branch name if possible in in-progress info, 2013-02-03), to show, if possible, the branch where the operation was initiated. Since then, we show incorrect information when several operations are in progress and one of them is bisect: $ git checkout -b foo $ GIT_SEQUENCE_EDITOR='echo break >' git rebase -i HEAD~ $ git checkout -b bar $ git bisect start $ git status ... You are currently editing a commit while rebasing branch 'bar' on '...'. You are currently bisecting, started from branch 'bar'. ... Note that we erroneously say "while rebasing branch 'bar'" when we should be referring to "foo". This must have gone unnoticed for so long because it must be unusual to start a bisection while another operation is in progress. And even less usual to involve different branches. It caught my attention reviewing a leak introduced in 8b87cfd000 (wt-status: move strbuf into read_and_strip_branch(), 2013-03-16). A simple change to deal with this situation can be to record in struct wt_status_state, the branch where the bisect starts separately from the branch related to other operations. Let's do it and so we'll be able to display correct information and we'll avoid the leak as well. Signed-off-by: Rubén Justo <rjusto@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Rubén Justo committed Sep 9, 2023 at 22:12 UTC 990adccbdf0d8d1056c49a5ed546e744f542ba8f
6 files changed +38 -8
branch.c
+2 -2
@@ -419,9 +419,9 @@ static void prepare_checked_out_branches(void)
419 wt_status_state_free_buffers(&state);
420
421 if (wt_status_check_bisect(wt, &state) &&
422 - state.branch) {
422 + state.bisecting_from) {
423 struct strbuf ref = STRBUF_INIT;
424 - strbuf_addf(&ref, "refs/heads/%s", state.branch);
424 + strbuf_addf(&ref, "refs/heads/%s", state.bisecting_from);
425 old = strmap_put(&current_checked_out_branches,
426 ref.buf,
427 xstrdup(wt->path));
ref-filter.c
+1 -1
@@ -1773,7 +1773,7 @@ char *get_head_description(void)
1773 state.detached_from);
1774 } else if (state.bisect_in_progress)
1775 strbuf_addf(&desc, _("(no branch, bisect started on %s)"),
1776 - state.branch);
1776 + state.bisecting_from);
1777 else if (state.detached_from) {
1778 if (state.detached_at)
1779 strbuf_addf(&desc, _("(HEAD detached at %s)"),
t/t7512-status-help.sh
+28
@@ -692,6 +692,34 @@ EOF
692 '
693
694
695 +test_expect_success 'status when bisecting while rebasing' '
696 + git reset --hard main &&
697 + test_when_finished "git rebase --abort" &&
698 + ONTO=$(git rev-parse --short HEAD^) &&
699 + FAKE_LINES="break" git rebase -i HEAD^ &&
700 + test_when_finished "git checkout -" &&
701 + git checkout -b bisect_while_rebasing &&
702 + test_when_finished "git bisect reset" &&
703 + git bisect start &&
704 + cat >expected <<EOF &&
705 +On branch bisect_while_rebasing
706 +Last command done (1 command done):
707 + break
708 +No commands remaining.
709 +You are currently editing a commit while rebasing branch '\''bisect'\'' on '\''$ONTO'\''.
710 + (use "git commit --amend" to amend the current commit)
711 + (use "git rebase --continue" once you are satisfied with your changes)
712 +
713 +You are currently bisecting, started from branch '\''bisect_while_rebasing'\''.
714 + (use "git bisect reset" to get back to the original branch)
715 +
716 +nothing to commit (use -u to show untracked files)
717 +EOF
718 + git status --untracked-files=no >actual &&
719 + test_cmp expected actual
720 +'
721 +
722 +
723 test_expect_success 'status when rebase --apply conflicts with statushints disabled' '
724 git reset --hard main &&
725 git checkout -b statushints_disabled &&
worktree.c
+2 -2
@@ -396,9 +396,9 @@ int is_worktree_being_bisected(const struct worktree *wt,
396
397 memset(&state, 0, sizeof(state));
398 found_bisect = wt_status_check_bisect(wt, &state) &&
399 - state.branch &&
399 + state.bisecting_from &&
400 skip_prefix(target, "refs/heads/", &target) &&
401 - !strcmp(state.branch, target);
401 + !strcmp(state.bisecting_from, target);
402 wt_status_state_free_buffers(&state);
403 return found_bisect;
404 }
wt-status.c
+4 -3
@@ -858,6 +858,7 @@ void wt_status_state_free_buffers(struct wt_status_state *state)
858 FREE_AND_NULL(state->branch);
859 FREE_AND_NULL(state->onto);
860 FREE_AND_NULL(state->detached_from);
861 + FREE_AND_NULL(state->bisecting_from);
862 }
863
864 static void wt_longstatus_print_unmerged(struct wt_status *s)
@@ -1565,10 +1566,10 @@ static void show_revert_in_progress(struct wt_status *s,
1566 static void show_bisect_in_progress(struct wt_status *s,
1567 const char *color)
1568 {
1568 - if (s->state.branch)
1569 + if (s->state.bisecting_from)
1570 status_printf_ln(s, color,
1571 _("You are currently bisecting, started from branch '%s'."),
1571 - s->state.branch);
1572 + s->state.bisecting_from);
1573 else
1574 status_printf_ln(s, color,
1575 _("You are currently bisecting."));
@@ -1729,7 +1730,7 @@ int wt_status_check_bisect(const struct worktree *wt,
1730
1731 if (!stat(worktree_git_path(wt, "BISECT_LOG"), &st)) {
1732 state->bisect_in_progress = 1;
1732 - state->branch = get_branch(wt, "BISECT_START");
1733 + state->bisecting_from = get_branch(wt, "BISECT_START");
1734 return 1;
1735 }
1736 return 0;
wt-status.h
+1
@@ -94,6 +94,7 @@ struct wt_status_state {
94 char *branch;
95 char *onto;
96 char *detached_from;
97 + char *bisecting_from;
98 struct object_id detached_oid;
99 struct object_id revert_head_oid;
100 struct object_id cherry_pick_head_oid;