diff --git a/bisect.c b/bisect.c index d5e830410f..0864e2a21b 100644 --- a/bisect.c +++ b/bisect.c @@ -980,6 +980,12 @@ void read_bisect_terms(const char **read_bad, const char **read_good) * the bisection process finished successfully. * In this case the calling function or command should not turn a * BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND return code into an error or a non zero exit code. + * + * Checking BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND + * in bisect_helper::bisect_next() and only transforming it to 0 at + * the end of bisect_helper::cmd_bisect__helper() helps bypassing + * all the code related to finding a commit to test. + * * If no_checkout is non-zero, the bisection process does not * checkout the trial commit but instead simply updates BISECT_HEAD. */ @@ -1064,6 +1070,8 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix, int "Bisecting: %d revisions left to test after this %s\n", nr), nr, steps_msg); free(steps_msg); + /* Clean up objects used, as they will be reused. */ + clear_commit_marks_all(ALL_REV_FLAGS); return bisect_checkout(bisect_rev, no_checkout); } diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index ec4996282e..796bd21155 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -8,6 +8,7 @@ #include "run-command.h" #include "prompt.h" #include "quote.h" +#include "revision.h" static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS") static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV") @@ -19,9 +20,6 @@ static GIT_PATH_FUNC(git_path_head_name, "head-name") static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") static const char * const git_bisect_helper_usage[] = { - N_("git bisect--helper --next-all [--no-checkout]"), - N_("git bisect--helper --write-terms "), - N_("git bisect--helper --bisect-clean-state"), N_("git bisect--helper --bisect-reset []"), N_("git bisect--helper --bisect-write [--no-log] "), N_("git bisect--helper --bisect-check-and-set-terms "), @@ -29,6 +27,10 @@ static const char * const git_bisect_helper_usage[] = { N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"), N_("git bisect--helper --bisect-start [--term-{old,good}= --term-{new,bad}=]" "[--no-checkout] [ [...]] [--] [...]"), + N_("git bisect--helper --bisect-next"), + N_("git bisect--helper --bisect-auto-next"), + N_("git bisect--helper --bisect-state (bad|new) []"), + N_("git bisect--helper --bisect-state (good|old) [...]"), NULL }; @@ -55,6 +57,8 @@ static void set_terms(struct bisect_terms *terms, const char *bad, static const char vocab_bad[] = "bad|new"; static const char vocab_good[] = "good|old"; +static int bisect_autostart(struct bisect_terms *terms); + /* * Check whether the string `term` belongs to the set of strings * included in the variable arguments. @@ -74,6 +78,28 @@ static int one_of(const char *term, ...) return res; } +static int write_in_file(const char *path, const char *mode, const char *format,...) +{ + FILE *fp = NULL; + va_list args; + int res = 0; + + if (!strcmp(mode, "a") && !strcmp(mode, "w")) + return error(_("wrong writing mode '%s'"), mode); + fp = fopen(path, mode); + if (!fp) + return error_errno(_("cannot open file '%s' in mode '%s'"), path, mode); + va_start(args, format); + res = vfprintf(fp, format, args); + va_end(args); + if (!res) { + fclose(fp); + return error_errno(_("could not write to file '%s'"), path); + } + + return fclose(fp); +} + static int check_term_format(const char *term, const char *orig_term) { int res; @@ -104,7 +130,6 @@ static int check_term_format(const char *term, const char *orig_term) static int write_terms(const char *bad, const char *good) { - FILE *fp = NULL; int res; if (!strcmp(bad, good)) @@ -113,12 +138,8 @@ static int write_terms(const char *bad, const char *good) if (check_term_format(bad, "bad") || check_term_format(good, "good")) return -1; - fp = fopen(git_path_bisect_terms(), "w"); - if (!fp) - return error_errno(_("could not open the file BISECT_TERMS")); + res = write_in_file(git_path_bisect_terms(), "w", "%s\n%s\n", bad, good); - res = fprintf(fp, "%s\n%s\n", bad, good); - res |= fclose(fp); return (res < 0) ? -1 : 0; } @@ -421,11 +442,156 @@ finish: return res; } -static int bisect_start(struct bisect_terms *terms, int no_checkout, +static int register_good_ref(const char *refname, + const struct object_id *oid, int flags, + void *cb_data) +{ + struct argv_array *rev_argv = cb_data; + + argv_array_push(rev_argv, oid_to_hex(oid)); + return 0; +} + +static void prepare_rev_argv(struct bisect_terms *terms, struct argv_array *rev_argv) +{ + char *term_good = xstrfmt("%s-*", terms->term_good); + + argv_array_pushl(rev_argv, "skipped_commits", "refs/bisect/bad", "--not", NULL); + for_each_glob_ref_in(register_good_ref, term_good, "refs/bisect/", rev_argv); + + free(term_good); +} + +static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs) +{ + int res = 0; + struct argv_array rev_argv = ARGV_ARRAY_INIT; + + prepare_rev_argv(terms, &rev_argv); + + /* + * It is important to reset the flags used by revision walks + * as the previous call to bisect_next_all() in turn + * sets up a revision walk. + */ + reset_revision_walk(); + init_revisions(revs, NULL); + rev_argv.argc = setup_revisions(rev_argv.argc, rev_argv.argv, revs, NULL); + if (prepare_revision_walk(revs)) + res = error(_("revision walk setup failed\n")); + + argv_array_clear(&rev_argv); + return res; +} + +static int process_skipped_commits(FILE *fp, struct bisect_terms *terms, struct rev_info *revs) +{ + struct commit *commit; + struct pretty_print_context pp = {0}; + + if (fprintf(fp, "# only skipped commits left to test\n") < 0) + return error_errno(_("failed to write to '%s'"), git_path_bisect_log()); + + while ((commit = get_revision(revs)) != NULL) { + struct strbuf commit_name = STRBUF_INIT; + format_commit_message(commit, "%s", + &commit_name, &pp); + fprintf(fp, "# possible first %s commit: [%s] %s\n", + terms->term_bad, oid_to_hex(&commit->object.oid), + commit_name.buf); + strbuf_release(&commit_name); + } + + /* + * Reset the flags used by revision walks in case + * there is another revision walk after this one. + */ + reset_revision_walk(); + + return 0; +} + +static int bisect_skipped_commits(struct bisect_terms *terms) +{ + int res = 0; + FILE *fp = NULL; + struct rev_info revs; + + fp = fopen(git_path_bisect_log(), "a"); + if (!fp) + return error_errno(_("could not open '%s' for appending"), + git_path_bisect_log()); + + res = prepare_revs(terms, &revs); + + if (!res) + res = process_skipped_commits(fp, terms, &revs); + + fclose(fp); + return res; +} + +static int bisect_successful(struct bisect_terms *terms) +{ + struct object_id oid; + struct commit *commit; + struct pretty_print_context pp = {0}; + struct strbuf commit_name = STRBUF_INIT; + char *bad_ref = xstrfmt("refs/bisect/%s",terms->term_bad); + int res; + + read_ref(bad_ref, &oid); + printf("%s\n", bad_ref); + commit = lookup_commit_reference(the_repository, &oid); + format_commit_message(commit, "%s", &commit_name, &pp); + + res = write_in_file(git_path_bisect_log(), "a", "# first %s commit: [%s] %s\n", + terms->term_bad, oid_to_hex(&oid), + commit_name.buf); + + strbuf_release(&commit_name); + free(bad_ref); + return res; +} + +static enum bisect_error bisect_next(struct bisect_terms *terms, const char *prefix) +{ + int no_checkout; + enum bisect_error res; + + bisect_autostart(terms); + if (bisect_next_check(terms, terms->term_good)) + return BISECT_FAILED; + + no_checkout = file_exists(git_path_bisect_head()); + + /* Perform all bisection computation, display and checkout */ + res = bisect_next_all(the_repository, prefix, no_checkout); + + if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) { + res = bisect_successful(terms); + return res ? res : BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND; + } else if (res == BISECT_ONLY_SKIPPED_LEFT) { + res = bisect_skipped_commits(terms); + return res ? res : BISECT_ONLY_SKIPPED_LEFT; + } + return res; +} + +static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char *prefix) +{ + if (bisect_next_check(terms, NULL)) + return BISECT_OK; + + return bisect_next(terms, prefix); +} + +static enum bisect_error bisect_start(struct bisect_terms *terms, int no_checkout, const char **argv, int argc) { int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0; - int flags, pathspec_pos, res = 0; + int flags, pathspec_pos; + enum bisect_error res = BISECT_OK; struct string_list revs = STRING_LIST_INIT_DUP; struct string_list states = STRING_LIST_INIT_DUP; struct strbuf start_head = STRBUF_INIT; @@ -483,9 +649,12 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, return error(_("unrecognized option: '%s'"), arg); } else { char *commit_id = xstrfmt("%s^{commit}", arg); - if (get_oid(commit_id, &oid) && has_double_dash) - die(_("'%s' does not appear to be a valid " - "revision"), arg); + if (get_oid(commit_id, &oid) && has_double_dash) { + error(_("'%s' does not appear to be a valid " + "revision"), arg); + free(commit_id); + return BISECT_FAILED; + } string_list_append(&revs, oid_to_hex(&oid)); free(commit_id); @@ -563,12 +732,12 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, * Get rid of any old bisect state. */ if (bisect_clean_state()) - return -1; + return BISECT_FAILED; /* - * In case of mistaken revs or checkout error, or signals received, + * In case of mistaken revs or checkout error, * "bisect_auto_next" below may exit or misbehave. - * We have to trap this to be able to clean up using + * We have to handle this to be able to clean up using * "bisect_clean_state". */ @@ -584,7 +753,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, } if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR)) { - res = -1; + res = BISECT_FAILED; goto finish; } } @@ -596,52 +765,153 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, for (i = 0; i < states.nr; i++) if (bisect_write(states.items[i].string, revs.items[i].string, terms, 1)) { - res = -1; + res = BISECT_FAILED; goto finish; } if (must_write_terms && write_terms(terms->term_bad, terms->term_good)) { - res = -1; + res = BISECT_FAILED; goto finish; } res = bisect_append_log_quoted(argv); if (res) - res = -1; + res = BISECT_FAILED; finish: string_list_clear(&revs, 0); string_list_clear(&states, 0); strbuf_release(&start_head); strbuf_release(&bisect_names); + if (res) + return res; + + res = bisect_auto_next(terms, NULL); + /* + * In case of mistaken revs or checkout error, or signals received, + * "bisect_auto_next" below may exit or misbehave. + * We have to handle this to be able to clean up using + * "bisect_clean_state". + * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE is special code + * that indicates special success. + * -> bisect_start() + * . res = bisect_auto_next() + * -> bisect_auto_next() + * . return bisect_next() + * -> bisect_next() + * . res = bisect_next_all() + * -> bisect_next_all() + * . res = check_good_are_ancestors_of_bad() + * -> check_good_are_ancestors_of_bad() + * . res = check_merge_bases() + * -> check_merge_bases() + * . res = BISECT_INTERNAL_SUCCESS_MERGE_BASE + */ + if (res && res != BISECT_INTERNAL_SUCCESS_MERGE_BASE) + bisect_clean_state(); return res; } +static int bisect_autostart(struct bisect_terms *terms) +{ + const char *yesno; + + if (!is_empty_or_missing_file(git_path_bisect_start())) + return 0; + + fprintf(stderr, _("You need to start by \"git bisect " + "start\"\n")); + + if (!isatty(STDIN_FILENO)) + return 1; + + /* + * TRANSLATORS: Make sure to include [Y] and [n] in your + * translation. The program will only accept English input + * at this point. + */ + yesno = git_prompt(_("Do you want me to do it for you " + "[Y/n]? "), PROMPT_ECHO); + if (starts_with(yesno, _("n")) || starts_with(yesno, _("N"))) + return 1; + + return bisect_start(terms, 0, NULL, 0); +} + +static int bisect_head(struct object_id *oid) +{ + if (!file_exists(git_path_bisect_head())) + return get_oid("HEAD", oid); + + return get_oid("BISECT_HEAD", oid); +} + +static enum bisect_error bisect_state(struct bisect_terms *terms, const char **argv, + int argc) +{ + const char *state; + const char *hex; + int i; + struct oid_array revs = OID_ARRAY_INIT; + struct object_id oid; + + if (!argc) + return error(_("Please call `--bisect-state` with at least one argument")); + state = argv[0]; + if (check_and_set_terms(terms, state) || + !one_of(state, terms->term_good,terms->term_bad, "skip", NULL)) + return BISECT_FAILED; + argv++; + argc--; + if (!strcmp(state, terms->term_bad) && (argc > 1)) + return error(_("'git bisect %s' can take only one argument."),terms->term_bad); + if (argc == 0) { + if (bisect_head(&oid)) + return error(_("Bad bisect_head rev input")); + hex = oid_to_hex(&oid); + if (bisect_write(state, hex, terms, 0)) + return BISECT_FAILED; + check_expected_revs(&hex, 1); + return bisect_auto_next(terms, NULL); + } + + /* Here argc > 0 */ + for (; argc; argc--, argv++) { + struct object_id oid; + if (get_oid(*argv, &oid)) + return error(_("Bad rev input: %s"), *argv); + oid_array_append(&revs, &oid); + } + + for (i = 0; i < revs.nr; i++) { + hex = oid_to_hex(&revs.oid[i]); + if (bisect_write(state, hex, terms, 0)) { + oid_array_clear(&revs); + return BISECT_FAILED; + } + check_expected_revs(&hex, 1); + } + + oid_array_clear(&revs); + return bisect_auto_next(terms, NULL); +} + int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { - NEXT_ALL = 1, - WRITE_TERMS, - BISECT_CLEAN_STATE, - CHECK_EXPECTED_REVS, - BISECT_RESET, + BISECT_RESET = 1, BISECT_WRITE, CHECK_AND_SET_TERMS, BISECT_NEXT_CHECK, BISECT_TERMS, - BISECT_START + BISECT_START, + BISECT_NEXT, + BISECT_AUTO_NEXT, + BISECT_STATE } cmdmode = 0; int no_checkout = 0, res = 0, nolog = 0; struct option options[] = { - OPT_CMDMODE(0, "next-all", &cmdmode, - N_("perform 'git bisect next'"), NEXT_ALL), - OPT_CMDMODE(0, "write-terms", &cmdmode, - N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS), - OPT_CMDMODE(0, "bisect-clean-state", &cmdmode, - N_("cleanup the bisection state"), BISECT_CLEAN_STATE), - OPT_CMDMODE(0, "check-expected-revs", &cmdmode, - N_("check for expected revs"), CHECK_EXPECTED_REVS), OPT_CMDMODE(0, "bisect-reset", &cmdmode, N_("reset the bisection state"), BISECT_RESET), OPT_CMDMODE(0, "bisect-write", &cmdmode, @@ -654,6 +924,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("print out the bisect terms"), BISECT_TERMS), OPT_CMDMODE(0, "bisect-start", &cmdmode, N_("start the bisect session"), BISECT_START), + OPT_CMDMODE(0, "bisect-next", &cmdmode, + N_("find the next bisection commit"), BISECT_NEXT), + OPT_CMDMODE(0, "bisect-auto-next", &cmdmode, + N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT), + OPT_CMDMODE(0, "bisect-state", &cmdmode, + N_("mark the state of ref (or refs)"), BISECT_STATE), OPT_BOOL(0, "no-checkout", &no_checkout, N_("update BISECT_HEAD instead of checking out the current commit")), OPT_BOOL(0, "no-log", &nolog, @@ -670,20 +946,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) usage_with_options(git_bisect_helper_usage, options); switch (cmdmode) { - case NEXT_ALL: - res = bisect_next_all(the_repository, prefix, no_checkout); - break; - case WRITE_TERMS: - if (argc != 2) - return error(_("--write-terms requires two arguments")); - return write_terms(argv[0], argv[1]); - case BISECT_CLEAN_STATE: - if (argc != 0) - return error(_("--bisect-clean-state requires no arguments")); - return bisect_clean_state(); - case CHECK_EXPECTED_REVS: - check_expected_revs(argv, argc); - return 0; case BISECT_RESET: if (argc > 1) return error(_("--bisect-reset requires either no argument or a commit")); @@ -715,8 +977,25 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) set_terms(&terms, "bad", "good"); res = bisect_start(&terms, no_checkout, argv, argc); break; + case BISECT_NEXT: + if (argc) + return error(_("--bisect-next requires 0 arguments")); + get_terms(&terms); + res = bisect_next(&terms, prefix); + break; + case BISECT_AUTO_NEXT: + if (argc) + return error(_("--bisect-auto-next requires 0 arguments")); + get_terms(&terms); + res = bisect_auto_next(&terms, prefix); + break; + case BISECT_STATE: + set_terms(&terms, "bad", "good"); + get_terms(&terms); + res = bisect_state(&terms, argv, argc); + break; default: - return error("BUG: unknown subcommand '%d'", cmdmode); + BUG("unknown subcommand %d", (int)cmdmode); } free_terms(&terms); @@ -724,8 +1003,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) * Handle early success * From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all */ - if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) + if ((res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) || (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND)) res = BISECT_OK; - return abs(res); + return -res; } diff --git a/git-bisect.sh b/git-bisect.sh index 08a6ed57dd..7a8f796251 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -39,59 +39,6 @@ _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" TERM_BAD=bad TERM_GOOD=good -bisect_head() -{ - if test -f "$GIT_DIR/BISECT_HEAD" - then - echo BISECT_HEAD - else - echo HEAD - fi -} - -bisect_autostart() { - test -s "$GIT_DIR/BISECT_START" || { - gettextln "You need to start by \"git bisect start\"" >&2 - if test -t 0 - then - # TRANSLATORS: Make sure to include [Y] and [n] in your - # translation. The program will only accept English input - # at this point. - gettext "Do you want me to do it for you [Y/n]? " >&2 - read yesno - case "$yesno" in - [Nn]*) - exit ;; - esac - bisect_start - else - exit 1 - fi - } -} - -bisect_start() { - git bisect--helper --bisect-start $@ || exit - - # - # Change state. - # In case of mistaken revs or checkout error, or signals received, - # "bisect_auto_next" below may exit or misbehave. - # We have to trap this to be able to clean up using - # "bisect_clean_state". - # - trap 'git bisect--helper --bisect-clean-state' 0 - trap 'exit 255' 1 2 3 15 - - # - # Check if we can proceed to the next bisect state. - # - get_terms - bisect_auto_next - - trap '-' 0 -} - bisect_skip() { all='' for arg in "$@" @@ -104,81 +51,7 @@ bisect_skip() { esac all="$all $revs" done - eval bisect_state 'skip' $all -} - -bisect_state() { - bisect_autostart - state=$1 - git bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit - get_terms - case "$#,$state" in - 0,*) - die "Please call 'bisect_state' with at least one argument." ;; - 1,"$TERM_BAD"|1,"$TERM_GOOD"|1,skip) - bisected_head=$(bisect_head) - rev=$(git rev-parse --verify "$bisected_head") || - die "$(eval_gettext "Bad rev input: \$bisected_head")" - git bisect--helper --bisect-write "$state" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit - git bisect--helper --check-expected-revs "$rev" ;; - 2,"$TERM_BAD"|*,"$TERM_GOOD"|*,skip) - shift - hash_list='' - for rev in "$@" - do - sha=$(git rev-parse --verify "$rev^{commit}") || - die "$(eval_gettext "Bad rev input: \$rev")" - hash_list="$hash_list $sha" - done - for rev in $hash_list - do - git bisect--helper --bisect-write "$state" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit - done - git bisect--helper --check-expected-revs $hash_list ;; - *,"$TERM_BAD") - die "$(eval_gettext "'git bisect \$TERM_BAD' can take only one argument.")" ;; - *) - usage ;; - esac - bisect_auto_next -} - -bisect_auto_next() { - git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD && bisect_next || : -} - -bisect_next() { - case "$#" in 0) ;; *) usage ;; esac - bisect_autostart - git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit - - # Perform all bisection computation, display and checkout - git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout) - res=$? - - # Check if we should exit because bisection is finished - if test $res -eq 10 - then - bad_rev=$(git show-ref --hash --verify refs/bisect/$TERM_BAD) - bad_commit=$(git show-branch $bad_rev) - echo "# first $TERM_BAD commit: $bad_commit" >>"$GIT_DIR/BISECT_LOG" - exit 0 - elif test $res -eq 2 - then - echo "# only skipped commits left to test" >>"$GIT_DIR/BISECT_LOG" - good_revs=$(git for-each-ref --format="%(objectname)" "refs/bisect/$TERM_GOOD-*") - for skipped in $(git rev-list refs/bisect/$TERM_BAD --not $good_revs) - do - skipped_commit=$(git show-branch $skipped) - echo "# possible first $TERM_BAD commit: $skipped_commit" >>"$GIT_DIR/BISECT_LOG" - done - exit $res - fi - - # Check for an error in the bisection process - test $res -ne 0 && exit $res - - return 0 + eval git bisect--helper --bisect-state 'skip' $all } bisect_visualize() { @@ -223,8 +96,7 @@ bisect_replay () { get_terms case "$command" in start) - cmd="bisect_start $rev $tail" - eval "$cmd" ;; + eval "git bisect--helper --bisect-start $rev $tail" ;; "$TERM_GOOD"|"$TERM_BAD"|skip) git bisect--helper --bisect-write "$command" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit;; terms) @@ -234,7 +106,7 @@ bisect_replay () { esac done <"$file" IFS="$oIFS" - bisect_auto_next + git bisect--helper --bisect-auto-next } bisect_run () { @@ -269,8 +141,7 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2 state="$TERM_GOOD" fi - # We have to use a subshell because "bisect_state" can exit. - ( bisect_state $state >"$GIT_DIR/BISECT_RUN" ) + git bisect--helper --bisect-state $state >"$GIT_DIR/BISECT_RUN" res=$? cat "$GIT_DIR/BISECT_RUN" @@ -285,7 +156,7 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2 if [ $res -ne 0 ] then eval_gettextln "bisect run failed: -'bisect_state \$state' exited with error code \$res" >&2 +'git bisect--helper --bisect-state \$state' exited with error code \$res" >&2 exit $res fi @@ -324,14 +195,14 @@ case "$#" in help) git bisect -h ;; start) - bisect_start "$@" ;; + git bisect--helper --bisect-start "$@" ;; bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD") - bisect_state "$cmd" "$@" ;; + git bisect--helper --bisect-state "$cmd" "$@" ;; skip) bisect_skip "$@" ;; next) # Not sure we want "next" at the UI level anymore. - bisect_next "$@" ;; + git bisect--helper --bisect-next "$@" || exit ;; visualize|view) bisect_visualize "$@" ;; reset)