diff --git a/bisect.h b/bisect.h index 1015aeb8ea..ee3fd65f3b 100644 --- a/bisect.h +++ b/bisect.h @@ -62,6 +62,15 @@ enum bisect_error { BISECT_INTERNAL_SUCCESS_MERGE_BASE = -11 }; +/* + * Stores how many good/bad commits we have stored for a bisect. nr_bad can + * only be 0 or 1. + */ +struct bisect_state { + unsigned int nr_good; + unsigned int nr_bad; +}; + enum bisect_error bisect_next_all(struct repository *r, const char *prefix); int estimate_bisect_steps(int all); diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 8b2b259ff0..fa8024a864 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -329,12 +329,12 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd) return 0; } -static int mark_good(const char *refname, const struct object_id *oid, - int flag, void *cb_data) +static int inc_nr(const char *refname, const struct object_id *oid, + int flag, void *cb_data) { - int *m_good = (int *)cb_data; - *m_good = 0; - return 1; + unsigned int *nr = (unsigned int *)cb_data; + (*nr)++; + return 0; } static const char need_bad_and_good_revision_warning[] = @@ -384,23 +384,48 @@ static int decide_next(const struct bisect_terms *terms, vocab_good, vocab_bad, vocab_good, vocab_bad); } -static int bisect_next_check(const struct bisect_terms *terms, - const char *current_term) +static void bisect_status(struct bisect_state *state, + const struct bisect_terms *terms) { - int missing_good = 1, missing_bad = 1; char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad); char *good_glob = xstrfmt("%s-*", terms->term_good); if (ref_exists(bad_ref)) - missing_bad = 0; + state->nr_bad = 1; - for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/", - (void *) &missing_good); + for_each_glob_ref_in(inc_nr, good_glob, "refs/bisect/", + (void *) &state->nr_good); free(good_glob); free(bad_ref); +} - return decide_next(terms, current_term, missing_good, missing_bad); +static void bisect_print_status(const struct bisect_terms *terms) +{ + struct bisect_state state = { 0 }; + + bisect_status(&state, terms); + + /* If we had both, we'd already be started, and shouldn't get here. */ + if (state.nr_good && state.nr_bad) + return; + + if (!state.nr_good && !state.nr_bad) + printf(_("status: waiting for both good and bad commits\n")); + else if (state.nr_good) + printf(Q_("status: waiting for bad commit, %d good commit known\n", + "status: waiting for bad commit, %d good commits known\n", + state.nr_good), state.nr_good); + else + printf(_("status: waiting for good commit(s), bad commit known\n")); +} + +static int bisect_next_check(const struct bisect_terms *terms, + const char *current_term) +{ + struct bisect_state state = { 0 }; + bisect_status(&state, terms); + return decide_next(terms, current_term, !state.nr_good, !state.nr_bad); } static int get_terms(struct bisect_terms *terms) @@ -606,8 +631,10 @@ static enum bisect_error bisect_next(struct bisect_terms *terms, const char *pre static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char *prefix) { - if (bisect_next_check(terms, NULL)) + if (bisect_next_check(terms, NULL)) { + bisect_print_status(terms); return BISECT_OK; + } return bisect_next(terms, prefix); } diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 5382e5d216..686f6d5c7f 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -1025,4 +1025,22 @@ test_expect_success 'bisect visualize with a filename with dash and space' ' git bisect visualize -p -- "-hello 2" ' +test_expect_success 'bisect state output with multiple good commits' ' + git bisect reset && + git bisect start >output && + grep "waiting for both good and bad commits" output && + git bisect good "$HASH1" >output && + grep "waiting for bad commit, 1 good commit known" output && + git bisect good "$HASH2" >output && + grep "waiting for bad commit, 2 good commits known" output +' + +test_expect_success 'bisect state output with bad commit' ' + git bisect reset && + git bisect start >output && + grep "waiting for both good and bad commits" output && + git bisect bad "$HASH4" >output && + grep -F "waiting for good commit(s), bad commit known" output +' + test_done