3 #include "parse-options.h"
8 #include "run-command.h"
13 static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
14 static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
15 static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK")
16 static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
17 static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
18 static GIT_PATH_FUNC(git_path_head_name, "head-name")
19 static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
20 static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
22 static const char * const git_bisect_helper_usage[] = {
23 N_("git bisect--helper --write-terms <bad_term> <good_term>"),
24 N_("git bisect--helper --bisect-reset [<commit>]"),
25 N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"),
26 N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"),
27 N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
28 N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
29 N_("git bisect--helper --bisect-start [--term-{old,good}=<term> --term-{new,bad}=<term>]"
30 " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
31 N_("git bisect--helper --bisect-next"),
32 N_("git bisect--helper --bisect-auto-next"),
33 N_("git bisect--helper --bisect-autostart"),
34 N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
35 N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
39 struct add_bisect_ref_data {
40 struct rev_info *revs;
41 unsigned int object_flags;
49 static void free_terms(struct bisect_terms *terms)
51 FREE_AND_NULL(terms->term_good);
52 FREE_AND_NULL(terms->term_bad);
55 static void set_terms(struct bisect_terms *terms, const char *bad,
58 free((void *)terms->term_good);
59 terms->term_good = xstrdup(good);
60 free((void *)terms->term_bad);
61 terms->term_bad = xstrdup(bad);
64 static const char vocab_bad[] = "bad|new";
65 static const char vocab_good[] = "good|old";
67 static int bisect_autostart(struct bisect_terms *terms);
70 * Check whether the string `term` belongs to the set of strings
71 * included in the variable arguments.
74 static int one_of(const char *term, ...)
80 va_start(matches, term);
81 while (!res && (match = va_arg(matches, const char *)))
82 res = !strcmp(term, match);
89 * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE
90 * and BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND are codes
91 * that indicate special success.
94 static int is_bisect_success(enum bisect_error res)
97 res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ||
98 res == BISECT_INTERNAL_SUCCESS_MERGE_BASE;
101 static int write_in_file(const char *path, const char *mode, const char *format, va_list args)
106 if (strcmp(mode, "w") && strcmp(mode, "a"))
107 BUG("write-in-file does not support '%s' mode", mode);
108 fp = fopen(path, mode);
110 return error_errno(_("cannot open file '%s' in mode '%s'"), path, mode);
111 res = vfprintf(fp, format, args);
114 int saved_errno = errno;
117 return error_errno(_("could not write to file '%s'"), path);
123 static int write_to_file(const char *path, const char *format, ...)
128 va_start(args, format);
129 res = write_in_file(path, "w", format, args);
135 static int append_to_file(const char *path, const char *format, ...)
140 va_start(args, format);
141 res = write_in_file(path, "a", format, args);
147 static int check_term_format(const char *term, const char *orig_term)
150 char *new_term = xstrfmt("refs/bisect/%s", term);
152 res = check_refname_format(new_term, 0);
156 return error(_("'%s' is not a valid term"), term);
158 if (one_of(term, "help", "start", "skip", "next", "reset",
159 "visualize", "view", "replay", "log", "run", "terms", NULL))
160 return error(_("can't use the builtin command '%s' as a term"), term);
163 * In theory, nothing prevents swapping completely good and bad,
164 * but this situation could be confusing and hasn't been tested
165 * enough. Forbid it for now.
168 if ((strcmp(orig_term, "bad") && one_of(term, "bad", "new", NULL)) ||
169 (strcmp(orig_term, "good") && one_of(term, "good", "old", NULL)))
170 return error(_("can't change the meaning of the term '%s'"), term);
175 static int write_terms(const char *bad, const char *good)
179 if (!strcmp(bad, good))
180 return error(_("please use two different terms"));
182 if (check_term_format(bad, "bad") || check_term_format(good, "good"))
185 res = write_to_file(git_path_bisect_terms(), "%s\n%s\n", bad, good);
190 static int is_expected_rev(const char *expected_hex)
192 struct strbuf actual_hex = STRBUF_INIT;
194 if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {
195 strbuf_trim(&actual_hex);
196 res = !strcmp(actual_hex.buf, expected_hex);
198 strbuf_release(&actual_hex);
202 static void check_expected_revs(const char **revs, int rev_nr)
206 for (i = 0; i < rev_nr; i++) {
207 if (!is_expected_rev(revs[i])) {
208 unlink_or_warn(git_path_bisect_ancestors_ok());
209 unlink_or_warn(git_path_bisect_expected_rev());
214 static int bisect_reset(const char *commit)
216 struct strbuf branch = STRBUF_INIT;
219 if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {
220 printf(_("We are not bisecting.\n"));
223 strbuf_rtrim(&branch);
225 struct object_id oid;
227 if (get_oid_commit(commit, &oid))
228 return error(_("'%s' is not a valid commit"), commit);
229 strbuf_addstr(&branch, commit);
232 if (!ref_exists("BISECT_HEAD")) {
233 struct strvec argv = STRVEC_INIT;
235 strvec_pushl(&argv, "checkout", branch.buf, "--", NULL);
236 if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
237 error(_("could not check out original"
238 " HEAD '%s'. Try 'git bisect"
239 " reset <commit>'."), branch.buf);
240 strbuf_release(&branch);
247 strbuf_release(&branch);
248 return bisect_clean_state();
251 static void log_commit(FILE *fp, char *fmt, const char *state,
252 struct commit *commit)
254 struct pretty_print_context pp = {0};
255 struct strbuf commit_msg = STRBUF_INIT;
256 char *label = xstrfmt(fmt, state);
258 format_commit_message(commit, "%s", &commit_msg, &pp);
260 fprintf(fp, "# %s: [%s] %s\n", label, oid_to_hex(&commit->object.oid),
263 strbuf_release(&commit_msg);
267 static int bisect_write(const char *state, const char *rev,
268 const struct bisect_terms *terms, int nolog)
270 struct strbuf tag = STRBUF_INIT;
271 struct object_id oid;
272 struct commit *commit;
276 if (!strcmp(state, terms->term_bad)) {
277 strbuf_addf(&tag, "refs/bisect/%s", state);
278 } else if (one_of(state, terms->term_good, "skip", NULL)) {
279 strbuf_addf(&tag, "refs/bisect/%s-%s", state, rev);
281 res = error(_("Bad bisect_write argument: %s"), state);
285 if (get_oid(rev, &oid)) {
286 res = error(_("couldn't get the oid of the rev '%s'"), rev);
290 if (update_ref(NULL, tag.buf, &oid, NULL, 0,
291 UPDATE_REFS_MSG_ON_ERR)) {
296 fp = fopen(git_path_bisect_log(), "a");
298 res = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
302 commit = lookup_commit_reference(the_repository, &oid);
303 log_commit(fp, "%s", state, commit);
306 fprintf(fp, "git bisect %s %s\n", state, rev);
311 strbuf_release(&tag);
315 static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
317 int has_term_file = !is_empty_or_missing_file(git_path_bisect_terms());
319 if (one_of(cmd, "skip", "start", "terms", NULL))
322 if (has_term_file && strcmp(cmd, terms->term_bad) &&
323 strcmp(cmd, terms->term_good))
324 return error(_("Invalid command: you're currently in a "
325 "%s/%s bisect"), terms->term_bad,
328 if (!has_term_file) {
329 if (one_of(cmd, "bad", "good", NULL)) {
330 set_terms(terms, "bad", "good");
331 return write_terms(terms->term_bad, terms->term_good);
333 if (one_of(cmd, "new", "old", NULL)) {
334 set_terms(terms, "new", "old");
335 return write_terms(terms->term_bad, terms->term_good);
342 static int mark_good(const char *refname, const struct object_id *oid,
343 int flag, void *cb_data)
345 int *m_good = (int *)cb_data;
350 static const char need_bad_and_good_revision_warning[] =
351 N_("You need to give me at least one %s and %s revision.\n"
352 "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
354 static const char need_bisect_start_warning[] =
355 N_("You need to start by \"git bisect start\".\n"
356 "You then need to give me at least one %s and %s revision.\n"
357 "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
359 static int decide_next(const struct bisect_terms *terms,
360 const char *current_term, int missing_good,
363 if (!missing_good && !missing_bad)
368 if (missing_good && !missing_bad &&
369 !strcmp(current_term, terms->term_good)) {
372 * have bad (or new) but not good (or old). We could bisect
373 * although this is less optimum.
375 warning(_("bisecting only with a %s commit"), terms->term_bad);
379 * TRANSLATORS: Make sure to include [Y] and [n] in your
380 * translation. The program will only accept English input
383 yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO);
384 if (starts_with(yesno, "N") || starts_with(yesno, "n"))
389 if (!is_empty_or_missing_file(git_path_bisect_start()))
390 return error(_(need_bad_and_good_revision_warning),
391 vocab_bad, vocab_good, vocab_bad, vocab_good);
393 return error(_(need_bisect_start_warning),
394 vocab_good, vocab_bad, vocab_good, vocab_bad);
397 static int bisect_next_check(const struct bisect_terms *terms,
398 const char *current_term)
400 int missing_good = 1, missing_bad = 1;
401 char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
402 char *good_glob = xstrfmt("%s-*", terms->term_good);
404 if (ref_exists(bad_ref))
407 for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/",
408 (void *) &missing_good);
413 return decide_next(terms, current_term, missing_good, missing_bad);
416 static int get_terms(struct bisect_terms *terms)
418 struct strbuf str = STRBUF_INIT;
422 fp = fopen(git_path_bisect_terms(), "r");
429 strbuf_getline_lf(&str, fp);
430 terms->term_bad = strbuf_detach(&str, NULL);
431 strbuf_getline_lf(&str, fp);
432 terms->term_good = strbuf_detach(&str, NULL);
437 strbuf_release(&str);
441 static int bisect_terms(struct bisect_terms *terms, const char *option)
443 if (get_terms(terms))
444 return error(_("no terms defined"));
446 if (option == NULL) {
447 printf(_("Your current terms are %s for the old state\n"
448 "and %s for the new state.\n"),
449 terms->term_good, terms->term_bad);
452 if (one_of(option, "--term-good", "--term-old", NULL))
453 printf("%s\n", terms->term_good);
454 else if (one_of(option, "--term-bad", "--term-new", NULL))
455 printf("%s\n", terms->term_bad);
457 return error(_("invalid argument %s for 'git bisect terms'.\n"
458 "Supported options are: "
459 "--term-good|--term-old and "
460 "--term-bad|--term-new."), option);
465 static int bisect_append_log_quoted(const char **argv)
468 FILE *fp = fopen(git_path_bisect_log(), "a");
469 struct strbuf orig_args = STRBUF_INIT;
474 if (fprintf(fp, "git bisect start") < 1) {
479 sq_quote_argv(&orig_args, argv);
480 if (fprintf(fp, "%s\n", orig_args.buf) < 1)
485 strbuf_release(&orig_args);
489 static int add_bisect_ref(const char *refname, const struct object_id *oid,
492 struct add_bisect_ref_data *data = cb;
494 add_pending_oid(data->revs, refname, oid, data->object_flags);
499 static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
502 struct add_bisect_ref_data cb = { revs };
503 char *good = xstrfmt("%s-*", terms->term_good);
506 * We cannot use terms->term_bad directly in
507 * for_each_glob_ref_in() and we have to append a '*' to it,
508 * otherwise for_each_glob_ref_in() will append '/' and '*'.
510 char *bad = xstrfmt("%s*", terms->term_bad);
513 * It is important to reset the flags used by revision walks
514 * as the previous call to bisect_next_all() in turn
515 * sets up a revision walk.
517 reset_revision_walk();
518 init_revisions(revs, NULL);
519 setup_revisions(0, NULL, revs, NULL);
520 for_each_glob_ref_in(add_bisect_ref, bad, "refs/bisect/", &cb);
521 cb.object_flags = UNINTERESTING;
522 for_each_glob_ref_in(add_bisect_ref, good, "refs/bisect/", &cb);
523 if (prepare_revision_walk(revs))
524 res = error(_("revision walk setup failed\n"));
531 static int bisect_skipped_commits(struct bisect_terms *terms)
535 struct rev_info revs;
536 struct commit *commit;
537 struct pretty_print_context pp = {0};
538 struct strbuf commit_name = STRBUF_INIT;
540 res = prepare_revs(terms, &revs);
544 fp = fopen(git_path_bisect_log(), "a");
546 return error_errno(_("could not open '%s' for appending"),
547 git_path_bisect_log());
549 if (fprintf(fp, "# only skipped commits left to test\n") < 0)
550 return error_errno(_("failed to write to '%s'"), git_path_bisect_log());
552 while ((commit = get_revision(&revs)) != NULL) {
553 strbuf_reset(&commit_name);
554 format_commit_message(commit, "%s",
556 fprintf(fp, "# possible first %s commit: [%s] %s\n",
557 terms->term_bad, oid_to_hex(&commit->object.oid),
562 * Reset the flags used by revision walks in case
563 * there is another revision walk after this one.
565 reset_revision_walk();
567 strbuf_release(&commit_name);
572 static int bisect_successful(struct bisect_terms *terms)
574 struct object_id oid;
575 struct commit *commit;
576 struct pretty_print_context pp = {0};
577 struct strbuf commit_name = STRBUF_INIT;
578 char *bad_ref = xstrfmt("refs/bisect/%s",terms->term_bad);
581 read_ref(bad_ref, &oid);
582 commit = lookup_commit_reference_by_name(bad_ref);
583 format_commit_message(commit, "%s", &commit_name, &pp);
585 res = append_to_file(git_path_bisect_log(), "# first %s commit: [%s] %s\n",
586 terms->term_bad, oid_to_hex(&commit->object.oid),
589 strbuf_release(&commit_name);
594 static enum bisect_error bisect_next(struct bisect_terms *terms, const char *prefix)
596 enum bisect_error res;
598 if (bisect_autostart(terms))
599 return BISECT_FAILED;
601 if (bisect_next_check(terms, terms->term_good))
602 return BISECT_FAILED;
604 /* Perform all bisection computation */
605 res = bisect_next_all(the_repository, prefix);
607 if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
608 res = bisect_successful(terms);
609 return res ? res : BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND;
610 } else if (res == BISECT_ONLY_SKIPPED_LEFT) {
611 res = bisect_skipped_commits(terms);
612 return res ? res : BISECT_ONLY_SKIPPED_LEFT;
617 static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char *prefix)
619 if (bisect_next_check(terms, NULL))
622 return bisect_next(terms, prefix);
625 static enum bisect_error bisect_start(struct bisect_terms *terms, const char **argv, int argc)
628 int first_parent_only = 0;
629 int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
630 int flags, pathspec_pos;
631 enum bisect_error res = BISECT_OK;
632 struct string_list revs = STRING_LIST_INIT_DUP;
633 struct string_list states = STRING_LIST_INIT_DUP;
634 struct strbuf start_head = STRBUF_INIT;
635 struct strbuf bisect_names = STRBUF_INIT;
636 struct object_id head_oid;
637 struct object_id oid;
640 if (is_bare_repository())
644 * Check for one bad and then some good revisions
646 for (i = 0; i < argc; i++) {
647 if (!strcmp(argv[i], "--")) {
653 for (i = 0; i < argc; i++) {
654 const char *arg = argv[i];
655 if (!strcmp(argv[i], "--")) {
657 } else if (!strcmp(arg, "--no-checkout")) {
659 } else if (!strcmp(arg, "--first-parent")) {
660 first_parent_only = 1;
661 } else if (!strcmp(arg, "--term-good") ||
662 !strcmp(arg, "--term-old")) {
665 return error(_("'' is not a valid term"));
666 must_write_terms = 1;
667 free((void *) terms->term_good);
668 terms->term_good = xstrdup(argv[i]);
669 } else if (skip_prefix(arg, "--term-good=", &arg) ||
670 skip_prefix(arg, "--term-old=", &arg)) {
671 must_write_terms = 1;
672 free((void *) terms->term_good);
673 terms->term_good = xstrdup(arg);
674 } else if (!strcmp(arg, "--term-bad") ||
675 !strcmp(arg, "--term-new")) {
678 return error(_("'' is not a valid term"));
679 must_write_terms = 1;
680 free((void *) terms->term_bad);
681 terms->term_bad = xstrdup(argv[i]);
682 } else if (skip_prefix(arg, "--term-bad=", &arg) ||
683 skip_prefix(arg, "--term-new=", &arg)) {
684 must_write_terms = 1;
685 free((void *) terms->term_bad);
686 terms->term_bad = xstrdup(arg);
687 } else if (starts_with(arg, "--")) {
688 return error(_("unrecognized option: '%s'"), arg);
690 char *commit_id = xstrfmt("%s^{commit}", arg);
691 if (get_oid(commit_id, &oid) && has_double_dash)
692 die(_("'%s' does not appear to be a valid "
695 string_list_append(&revs, oid_to_hex(&oid));
702 * The user ran "git bisect start <sha1> <sha1>", hence did not
703 * explicitly specify the terms, but we are already starting to
704 * set references named with the default terms, and won't be able
705 * to change afterwards.
708 must_write_terms = 1;
709 for (i = 0; i < revs.nr; i++) {
711 string_list_append(&states, terms->term_good);
714 string_list_append(&states, terms->term_bad);
721 head = resolve_ref_unsafe("HEAD", 0, &head_oid, &flags);
723 if (get_oid("HEAD", &head_oid))
724 return error(_("bad HEAD - I need a HEAD"));
727 * Check if we are bisecting
729 if (!is_empty_or_missing_file(git_path_bisect_start())) {
730 /* Reset to the rev from where we started */
731 strbuf_read_file(&start_head, git_path_bisect_start(), 0);
732 strbuf_trim(&start_head);
734 struct strvec argv = STRVEC_INIT;
736 strvec_pushl(&argv, "checkout", start_head.buf,
738 if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
739 res = error(_("checking out '%s' failed."
740 " Try 'git bisect start "
747 /* Get the rev from where we start. */
748 if (!get_oid(head, &head_oid) &&
749 !starts_with(head, "refs/heads/")) {
750 strbuf_reset(&start_head);
751 strbuf_addstr(&start_head, oid_to_hex(&head_oid));
752 } else if (!get_oid(head, &head_oid) &&
753 skip_prefix(head, "refs/heads/", &head)) {
755 * This error message should only be triggered by
756 * cogito usage, and cogito users should understand
757 * it relates to cg-seek.
759 if (!is_empty_or_missing_file(git_path_head_name()))
760 return error(_("won't bisect on cg-seek'ed tree"));
761 strbuf_addstr(&start_head, head);
763 return error(_("bad HEAD - strange symbolic ref"));
768 * Get rid of any old bisect state.
770 if (bisect_clean_state())
771 return BISECT_FAILED;
774 * Write new start state
776 write_file(git_path_bisect_start(), "%s\n", start_head.buf);
778 if (first_parent_only)
779 write_file(git_path_bisect_first_parent(), "\n");
782 if (get_oid(start_head.buf, &oid) < 0) {
783 res = error(_("invalid ref: '%s'"), start_head.buf);
786 if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0,
787 UPDATE_REFS_MSG_ON_ERR)) {
793 if (pathspec_pos < argc - 1)
794 sq_quote_argv(&bisect_names, argv + pathspec_pos);
795 write_file(git_path_bisect_names(), "%s\n", bisect_names.buf);
797 for (i = 0; i < states.nr; i++)
798 if (bisect_write(states.items[i].string,
799 revs.items[i].string, terms, 1)) {
804 if (must_write_terms && write_terms(terms->term_bad,
810 res = bisect_append_log_quoted(argv);
815 string_list_clear(&revs, 0);
816 string_list_clear(&states, 0);
817 strbuf_release(&start_head);
818 strbuf_release(&bisect_names);
822 res = bisect_auto_next(terms, NULL);
823 if (!is_bisect_success(res))
824 bisect_clean_state();
828 static inline int file_is_not_empty(const char *path)
830 return !is_empty_or_missing_file(path);
833 static int bisect_autostart(struct bisect_terms *terms)
838 if (file_is_not_empty(git_path_bisect_start()))
841 fprintf_ln(stderr, _("You need to start by \"git bisect "
844 if (!isatty(STDIN_FILENO))
848 * TRANSLATORS: Make sure to include [Y] and [n] in your
849 * translation. The program will only accept English input
852 yesno = git_prompt(_("Do you want me to do it for you "
853 "[Y/n]? "), PROMPT_ECHO);
854 res = tolower(*yesno) == 'n' ?
855 -1 : bisect_start(terms, empty_strvec, 0);
860 static enum bisect_error bisect_state(struct bisect_terms *terms, const char **argv,
864 int i, verify_expected = 1;
865 struct object_id oid, expected;
866 struct strbuf buf = STRBUF_INIT;
867 struct oid_array revs = OID_ARRAY_INIT;
870 return error(_("Please call `--bisect-state` with at least one argument"));
872 if (bisect_autostart(terms))
873 return BISECT_FAILED;
876 if (check_and_set_terms(terms, state) ||
877 !one_of(state, terms->term_good, terms->term_bad, "skip", NULL))
878 return BISECT_FAILED;
882 if (argc > 1 && !strcmp(state, terms->term_bad))
883 return error(_("'git bisect %s' can take only one argument."), terms->term_bad);
886 const char *head = "BISECT_HEAD";
887 enum get_oid_result res_head = get_oid(head, &oid);
889 if (res_head == MISSING_OBJECT) {
891 res_head = get_oid(head, &oid);
895 error(_("Bad rev input: %s"), head);
896 oid_array_append(&revs, &oid);
900 * All input revs must be checked before executing bisect_write()
901 * to discard junk revs.
904 for (; argc; argc--, argv++) {
905 if (get_oid(*argv, &oid)){
906 error(_("Bad rev input: %s"), *argv);
907 oid_array_clear(&revs);
908 return BISECT_FAILED;
910 oid_array_append(&revs, &oid);
913 if (strbuf_read_file(&buf, git_path_bisect_expected_rev(), 0) < the_hash_algo->hexsz ||
914 get_oid_hex(buf.buf, &expected) < 0)
915 verify_expected = 0; /* Ignore invalid file contents */
916 strbuf_release(&buf);
918 for (i = 0; i < revs.nr; i++) {
919 if (bisect_write(state, oid_to_hex(&revs.oid[i]), terms, 0)) {
920 oid_array_clear(&revs);
921 return BISECT_FAILED;
923 if (verify_expected && !oideq(&revs.oid[i], &expected)) {
924 unlink_or_warn(git_path_bisect_ancestors_ok());
925 unlink_or_warn(git_path_bisect_expected_rev());
930 oid_array_clear(&revs);
931 return bisect_auto_next(terms, NULL);
934 int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
950 int res = 0, nolog = 0;
951 struct option options[] = {
952 OPT_CMDMODE(0, "write-terms", &cmdmode,
953 N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS),
954 OPT_CMDMODE(0, "check-expected-revs", &cmdmode,
955 N_("check for expected revs"), CHECK_EXPECTED_REVS),
956 OPT_CMDMODE(0, "bisect-reset", &cmdmode,
957 N_("reset the bisection state"), BISECT_RESET),
958 OPT_CMDMODE(0, "bisect-write", &cmdmode,
959 N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE),
960 OPT_CMDMODE(0, "check-and-set-terms", &cmdmode,
961 N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS),
962 OPT_CMDMODE(0, "bisect-next-check", &cmdmode,
963 N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK),
964 OPT_CMDMODE(0, "bisect-terms", &cmdmode,
965 N_("print out the bisect terms"), BISECT_TERMS),
966 OPT_CMDMODE(0, "bisect-start", &cmdmode,
967 N_("start the bisect session"), BISECT_START),
968 OPT_CMDMODE(0, "bisect-next", &cmdmode,
969 N_("find the next bisection commit"), BISECT_NEXT),
970 OPT_CMDMODE(0, "bisect-auto-next", &cmdmode,
971 N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT),
972 OPT_CMDMODE(0, "bisect-autostart", &cmdmode,
973 N_("start the bisection if it has not yet been started"), BISECT_AUTOSTART),
974 OPT_CMDMODE(0, "bisect-state", &cmdmode,
975 N_("mark the state of ref (or refs)"), BISECT_STATE),
976 OPT_BOOL(0, "no-log", &nolog,
977 N_("no log for BISECT_WRITE")),
980 struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };
982 argc = parse_options(argc, argv, prefix, options,
983 git_bisect_helper_usage,
984 PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN);
987 usage_with_options(git_bisect_helper_usage, options);
992 return error(_("--write-terms requires two arguments"));
993 return write_terms(argv[0], argv[1]);
994 case CHECK_EXPECTED_REVS:
995 check_expected_revs(argv, argc);
999 return error(_("--bisect-reset requires either no argument or a commit"));
1000 return !!bisect_reset(argc ? argv[0] : NULL);
1002 if (argc != 4 && argc != 5)
1003 return error(_("--bisect-write requires either 4 or 5 arguments"));
1004 set_terms(&terms, argv[3], argv[2]);
1005 res = bisect_write(argv[0], argv[1], &terms, nolog);
1007 case CHECK_AND_SET_TERMS:
1009 return error(_("--check-and-set-terms requires 3 arguments"));
1010 set_terms(&terms, argv[2], argv[1]);
1011 res = check_and_set_terms(&terms, argv[0]);
1013 case BISECT_NEXT_CHECK:
1014 if (argc != 2 && argc != 3)
1015 return error(_("--bisect-next-check requires 2 or 3 arguments"));
1016 set_terms(&terms, argv[1], argv[0]);
1017 res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);
1021 return error(_("--bisect-terms requires 0 or 1 argument"));
1022 res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);
1025 set_terms(&terms, "bad", "good");
1026 res = bisect_start(&terms, argv, argc);
1030 return error(_("--bisect-next requires 0 arguments"));
1032 res = bisect_next(&terms, prefix);
1034 case BISECT_AUTO_NEXT:
1036 return error(_("--bisect-auto-next requires 0 arguments"));
1038 res = bisect_auto_next(&terms, prefix);
1040 case BISECT_AUTOSTART:
1042 return error(_("--bisect-autostart does not accept arguments"));
1043 set_terms(&terms, "bad", "good");
1044 res = bisect_autostart(&terms);
1047 set_terms(&terms, "bad", "good");
1049 res = bisect_state(&terms, argv, argc);
1052 BUG("unknown subcommand %d", cmdmode);
1057 * Handle early success
1058 * From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all
1060 if ((res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) || (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND))