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 --next-all"),
24 N_("git bisect--helper --write-terms <bad_term> <good_term>"),
25 N_("git bisect--helper --bisect-reset [<commit>]"),
26 N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"),
27 N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"),
28 N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
29 N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
30 N_("git bisect--helper --bisect-start [--term-{old,good}=<term> --term-{new,bad}=<term>]"
31 " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
32 N_("git bisect--helper --bisect-next"),
33 N_("git bisect--helper --bisect-auto-next"),
34 N_("git bisect--helper --bisect-autostart"),
38 struct add_bisect_ref_data {
39 struct rev_info *revs;
40 unsigned int object_flags;
48 static void free_terms(struct bisect_terms *terms)
50 FREE_AND_NULL(terms->term_good);
51 FREE_AND_NULL(terms->term_bad);
54 static void set_terms(struct bisect_terms *terms, const char *bad,
57 free((void *)terms->term_good);
58 terms->term_good = xstrdup(good);
59 free((void *)terms->term_bad);
60 terms->term_bad = xstrdup(bad);
63 static const char vocab_bad[] = "bad|new";
64 static const char vocab_good[] = "good|old";
66 static int bisect_autostart(struct bisect_terms *terms);
69 * Check whether the string `term` belongs to the set of strings
70 * included in the variable arguments.
73 static int one_of(const char *term, ...)
79 va_start(matches, term);
80 while (!res && (match = va_arg(matches, const char *)))
81 res = !strcmp(term, match);
88 * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE
89 * and BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND are codes
90 * that indicate special success.
93 static int is_bisect_success(enum bisect_error res)
96 res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ||
97 res == BISECT_INTERNAL_SUCCESS_MERGE_BASE;
100 static int write_in_file(const char *path, const char *mode, const char *format, va_list args)
105 if (strcmp(mode, "w") && strcmp(mode, "a"))
106 BUG("write-in-file does not support '%s' mode", mode);
107 fp = fopen(path, mode);
109 return error_errno(_("cannot open file '%s' in mode '%s'"), path, mode);
110 res = vfprintf(fp, format, args);
113 int saved_errno = errno;
116 return error_errno(_("could not write to file '%s'"), path);
122 static int write_to_file(const char *path, const char *format, ...)
127 va_start(args, format);
128 res = write_in_file(path, "w", format, args);
134 static int append_to_file(const char *path, const char *format, ...)
139 va_start(args, format);
140 res = write_in_file(path, "a", format, args);
146 static int check_term_format(const char *term, const char *orig_term)
149 char *new_term = xstrfmt("refs/bisect/%s", term);
151 res = check_refname_format(new_term, 0);
155 return error(_("'%s' is not a valid term"), term);
157 if (one_of(term, "help", "start", "skip", "next", "reset",
158 "visualize", "view", "replay", "log", "run", "terms", NULL))
159 return error(_("can't use the builtin command '%s' as a term"), term);
162 * In theory, nothing prevents swapping completely good and bad,
163 * but this situation could be confusing and hasn't been tested
164 * enough. Forbid it for now.
167 if ((strcmp(orig_term, "bad") && one_of(term, "bad", "new", NULL)) ||
168 (strcmp(orig_term, "good") && one_of(term, "good", "old", NULL)))
169 return error(_("can't change the meaning of the term '%s'"), term);
174 static int write_terms(const char *bad, const char *good)
178 if (!strcmp(bad, good))
179 return error(_("please use two different terms"));
181 if (check_term_format(bad, "bad") || check_term_format(good, "good"))
184 res = write_to_file(git_path_bisect_terms(), "%s\n%s\n", bad, good);
189 static int is_expected_rev(const char *expected_hex)
191 struct strbuf actual_hex = STRBUF_INIT;
193 if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {
194 strbuf_trim(&actual_hex);
195 res = !strcmp(actual_hex.buf, expected_hex);
197 strbuf_release(&actual_hex);
201 static void check_expected_revs(const char **revs, int rev_nr)
205 for (i = 0; i < rev_nr; i++) {
206 if (!is_expected_rev(revs[i])) {
207 unlink_or_warn(git_path_bisect_ancestors_ok());
208 unlink_or_warn(git_path_bisect_expected_rev());
213 static int bisect_reset(const char *commit)
215 struct strbuf branch = STRBUF_INIT;
218 if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {
219 printf(_("We are not bisecting.\n"));
222 strbuf_rtrim(&branch);
224 struct object_id oid;
226 if (get_oid_commit(commit, &oid))
227 return error(_("'%s' is not a valid commit"), commit);
228 strbuf_addstr(&branch, commit);
231 if (!ref_exists("BISECT_HEAD")) {
232 struct strvec argv = STRVEC_INIT;
234 strvec_pushl(&argv, "checkout", branch.buf, "--", NULL);
235 if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
236 error(_("could not check out original"
237 " HEAD '%s'. Try 'git bisect"
238 " reset <commit>'."), branch.buf);
239 strbuf_release(&branch);
246 strbuf_release(&branch);
247 return bisect_clean_state();
250 static void log_commit(FILE *fp, char *fmt, const char *state,
251 struct commit *commit)
253 struct pretty_print_context pp = {0};
254 struct strbuf commit_msg = STRBUF_INIT;
255 char *label = xstrfmt(fmt, state);
257 format_commit_message(commit, "%s", &commit_msg, &pp);
259 fprintf(fp, "# %s: [%s] %s\n", label, oid_to_hex(&commit->object.oid),
262 strbuf_release(&commit_msg);
266 static int bisect_write(const char *state, const char *rev,
267 const struct bisect_terms *terms, int nolog)
269 struct strbuf tag = STRBUF_INIT;
270 struct object_id oid;
271 struct commit *commit;
275 if (!strcmp(state, terms->term_bad)) {
276 strbuf_addf(&tag, "refs/bisect/%s", state);
277 } else if (one_of(state, terms->term_good, "skip", NULL)) {
278 strbuf_addf(&tag, "refs/bisect/%s-%s", state, rev);
280 res = error(_("Bad bisect_write argument: %s"), state);
284 if (get_oid(rev, &oid)) {
285 res = error(_("couldn't get the oid of the rev '%s'"), rev);
289 if (update_ref(NULL, tag.buf, &oid, NULL, 0,
290 UPDATE_REFS_MSG_ON_ERR)) {
295 fp = fopen(git_path_bisect_log(), "a");
297 res = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
301 commit = lookup_commit_reference(the_repository, &oid);
302 log_commit(fp, "%s", state, commit);
305 fprintf(fp, "git bisect %s %s\n", state, rev);
310 strbuf_release(&tag);
314 static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
316 int has_term_file = !is_empty_or_missing_file(git_path_bisect_terms());
318 if (one_of(cmd, "skip", "start", "terms", NULL))
321 if (has_term_file && strcmp(cmd, terms->term_bad) &&
322 strcmp(cmd, terms->term_good))
323 return error(_("Invalid command: you're currently in a "
324 "%s/%s bisect"), terms->term_bad,
327 if (!has_term_file) {
328 if (one_of(cmd, "bad", "good", NULL)) {
329 set_terms(terms, "bad", "good");
330 return write_terms(terms->term_bad, terms->term_good);
332 if (one_of(cmd, "new", "old", NULL)) {
333 set_terms(terms, "new", "old");
334 return write_terms(terms->term_bad, terms->term_good);
341 static int mark_good(const char *refname, const struct object_id *oid,
342 int flag, void *cb_data)
344 int *m_good = (int *)cb_data;
349 static const char need_bad_and_good_revision_warning[] =
350 N_("You need to give me at least one %s and %s revision.\n"
351 "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
353 static const char need_bisect_start_warning[] =
354 N_("You need to start by \"git bisect start\".\n"
355 "You then need to give me at least one %s and %s revision.\n"
356 "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
358 static int decide_next(const struct bisect_terms *terms,
359 const char *current_term, int missing_good,
362 if (!missing_good && !missing_bad)
367 if (missing_good && !missing_bad &&
368 !strcmp(current_term, terms->term_good)) {
371 * have bad (or new) but not good (or old). We could bisect
372 * although this is less optimum.
374 warning(_("bisecting only with a %s commit"), terms->term_bad);
378 * TRANSLATORS: Make sure to include [Y] and [n] in your
379 * translation. The program will only accept English input
382 yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO);
383 if (starts_with(yesno, "N") || starts_with(yesno, "n"))
388 if (!is_empty_or_missing_file(git_path_bisect_start()))
389 return error(_(need_bad_and_good_revision_warning),
390 vocab_bad, vocab_good, vocab_bad, vocab_good);
392 return error(_(need_bisect_start_warning),
393 vocab_good, vocab_bad, vocab_good, vocab_bad);
396 static int bisect_next_check(const struct bisect_terms *terms,
397 const char *current_term)
399 int missing_good = 1, missing_bad = 1;
400 char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
401 char *good_glob = xstrfmt("%s-*", terms->term_good);
403 if (ref_exists(bad_ref))
406 for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/",
407 (void *) &missing_good);
412 return decide_next(terms, current_term, missing_good, missing_bad);
415 static int get_terms(struct bisect_terms *terms)
417 struct strbuf str = STRBUF_INIT;
421 fp = fopen(git_path_bisect_terms(), "r");
428 strbuf_getline_lf(&str, fp);
429 terms->term_bad = strbuf_detach(&str, NULL);
430 strbuf_getline_lf(&str, fp);
431 terms->term_good = strbuf_detach(&str, NULL);
436 strbuf_release(&str);
440 static int bisect_terms(struct bisect_terms *terms, const char *option)
442 if (get_terms(terms))
443 return error(_("no terms defined"));
445 if (option == NULL) {
446 printf(_("Your current terms are %s for the old state\n"
447 "and %s for the new state.\n"),
448 terms->term_good, terms->term_bad);
451 if (one_of(option, "--term-good", "--term-old", NULL))
452 printf("%s\n", terms->term_good);
453 else if (one_of(option, "--term-bad", "--term-new", NULL))
454 printf("%s\n", terms->term_bad);
456 return error(_("invalid argument %s for 'git bisect terms'.\n"
457 "Supported options are: "
458 "--term-good|--term-old and "
459 "--term-bad|--term-new."), option);
464 static int bisect_append_log_quoted(const char **argv)
467 FILE *fp = fopen(git_path_bisect_log(), "a");
468 struct strbuf orig_args = STRBUF_INIT;
473 if (fprintf(fp, "git bisect start") < 1) {
478 sq_quote_argv(&orig_args, argv);
479 if (fprintf(fp, "%s\n", orig_args.buf) < 1)
484 strbuf_release(&orig_args);
488 static int add_bisect_ref(const char *refname, const struct object_id *oid,
491 struct add_bisect_ref_data *data = cb;
493 add_pending_oid(data->revs, refname, oid, data->object_flags);
498 static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
501 struct add_bisect_ref_data cb = { revs };
502 char *good = xstrfmt("%s-*", terms->term_good);
505 * We cannot use terms->term_bad directly in
506 * for_each_glob_ref_in() and we have to append a '*' to it,
507 * otherwise for_each_glob_ref_in() will append '/' and '*'.
509 char *bad = xstrfmt("%s*", terms->term_bad);
512 * It is important to reset the flags used by revision walks
513 * as the previous call to bisect_next_all() in turn
514 * sets up a revision walk.
516 reset_revision_walk();
517 init_revisions(revs, NULL);
518 setup_revisions(0, NULL, revs, NULL);
519 for_each_glob_ref_in(add_bisect_ref, bad, "refs/bisect/", &cb);
520 cb.object_flags = UNINTERESTING;
521 for_each_glob_ref_in(add_bisect_ref, good, "refs/bisect/", &cb);
522 if (prepare_revision_walk(revs))
523 res = error(_("revision walk setup failed\n"));
530 static int bisect_skipped_commits(struct bisect_terms *terms)
534 struct rev_info revs;
535 struct commit *commit;
536 struct pretty_print_context pp = {0};
537 struct strbuf commit_name = STRBUF_INIT;
539 res = prepare_revs(terms, &revs);
543 fp = fopen(git_path_bisect_log(), "a");
545 return error_errno(_("could not open '%s' for appending"),
546 git_path_bisect_log());
548 if (fprintf(fp, "# only skipped commits left to test\n") < 0)
549 return error_errno(_("failed to write to '%s'"), git_path_bisect_log());
551 while ((commit = get_revision(&revs)) != NULL) {
552 strbuf_reset(&commit_name);
553 format_commit_message(commit, "%s",
555 fprintf(fp, "# possible first %s commit: [%s] %s\n",
556 terms->term_bad, oid_to_hex(&commit->object.oid),
561 * Reset the flags used by revision walks in case
562 * there is another revision walk after this one.
564 reset_revision_walk();
566 strbuf_release(&commit_name);
571 static int bisect_successful(struct bisect_terms *terms)
573 struct object_id oid;
574 struct commit *commit;
575 struct pretty_print_context pp = {0};
576 struct strbuf commit_name = STRBUF_INIT;
577 char *bad_ref = xstrfmt("refs/bisect/%s",terms->term_bad);
580 read_ref(bad_ref, &oid);
581 commit = lookup_commit_reference_by_name(bad_ref);
582 format_commit_message(commit, "%s", &commit_name, &pp);
584 res = append_to_file(git_path_bisect_log(), "# first %s commit: [%s] %s\n",
585 terms->term_bad, oid_to_hex(&commit->object.oid),
588 strbuf_release(&commit_name);
593 static enum bisect_error bisect_next(struct bisect_terms *terms, const char *prefix)
595 enum bisect_error res;
597 if (bisect_autostart(terms))
598 return BISECT_FAILED;
600 if (bisect_next_check(terms, terms->term_good))
601 return BISECT_FAILED;
603 /* Perform all bisection computation */
604 res = bisect_next_all(the_repository, prefix);
606 if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
607 res = bisect_successful(terms);
608 return res ? res : BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND;
609 } else if (res == BISECT_ONLY_SKIPPED_LEFT) {
610 res = bisect_skipped_commits(terms);
611 return res ? res : BISECT_ONLY_SKIPPED_LEFT;
616 static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char *prefix)
618 if (bisect_next_check(terms, NULL))
621 return bisect_next(terms, prefix);
624 static enum bisect_error bisect_start(struct bisect_terms *terms, const char **argv, int argc)
627 int first_parent_only = 0;
628 int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
629 int flags, pathspec_pos;
630 enum bisect_error res = BISECT_OK;
631 struct string_list revs = STRING_LIST_INIT_DUP;
632 struct string_list states = STRING_LIST_INIT_DUP;
633 struct strbuf start_head = STRBUF_INIT;
634 struct strbuf bisect_names = STRBUF_INIT;
635 struct object_id head_oid;
636 struct object_id oid;
639 if (is_bare_repository())
643 * Check for one bad and then some good revisions
645 for (i = 0; i < argc; i++) {
646 if (!strcmp(argv[i], "--")) {
652 for (i = 0; i < argc; i++) {
653 const char *arg = argv[i];
654 if (!strcmp(argv[i], "--")) {
656 } else if (!strcmp(arg, "--no-checkout")) {
658 } else if (!strcmp(arg, "--first-parent")) {
659 first_parent_only = 1;
660 } else if (!strcmp(arg, "--term-good") ||
661 !strcmp(arg, "--term-old")) {
664 return error(_("'' is not a valid term"));
665 must_write_terms = 1;
666 free((void *) terms->term_good);
667 terms->term_good = xstrdup(argv[i]);
668 } else if (skip_prefix(arg, "--term-good=", &arg) ||
669 skip_prefix(arg, "--term-old=", &arg)) {
670 must_write_terms = 1;
671 free((void *) terms->term_good);
672 terms->term_good = xstrdup(arg);
673 } else if (!strcmp(arg, "--term-bad") ||
674 !strcmp(arg, "--term-new")) {
677 return error(_("'' is not a valid term"));
678 must_write_terms = 1;
679 free((void *) terms->term_bad);
680 terms->term_bad = xstrdup(argv[i]);
681 } else if (skip_prefix(arg, "--term-bad=", &arg) ||
682 skip_prefix(arg, "--term-new=", &arg)) {
683 must_write_terms = 1;
684 free((void *) terms->term_bad);
685 terms->term_bad = xstrdup(arg);
686 } else if (starts_with(arg, "--")) {
687 return error(_("unrecognized option: '%s'"), arg);
689 char *commit_id = xstrfmt("%s^{commit}", arg);
690 if (get_oid(commit_id, &oid) && has_double_dash)
691 die(_("'%s' does not appear to be a valid "
694 string_list_append(&revs, oid_to_hex(&oid));
701 * The user ran "git bisect start <sha1> <sha1>", hence did not
702 * explicitly specify the terms, but we are already starting to
703 * set references named with the default terms, and won't be able
704 * to change afterwards.
707 must_write_terms = 1;
708 for (i = 0; i < revs.nr; i++) {
710 string_list_append(&states, terms->term_good);
713 string_list_append(&states, terms->term_bad);
720 head = resolve_ref_unsafe("HEAD", 0, &head_oid, &flags);
722 if (get_oid("HEAD", &head_oid))
723 return error(_("bad HEAD - I need a HEAD"));
726 * Check if we are bisecting
728 if (!is_empty_or_missing_file(git_path_bisect_start())) {
729 /* Reset to the rev from where we started */
730 strbuf_read_file(&start_head, git_path_bisect_start(), 0);
731 strbuf_trim(&start_head);
733 struct strvec argv = STRVEC_INIT;
735 strvec_pushl(&argv, "checkout", start_head.buf,
737 if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
738 res = error(_("checking out '%s' failed."
739 " Try 'git bisect start "
746 /* Get the rev from where we start. */
747 if (!get_oid(head, &head_oid) &&
748 !starts_with(head, "refs/heads/")) {
749 strbuf_reset(&start_head);
750 strbuf_addstr(&start_head, oid_to_hex(&head_oid));
751 } else if (!get_oid(head, &head_oid) &&
752 skip_prefix(head, "refs/heads/", &head)) {
754 * This error message should only be triggered by
755 * cogito usage, and cogito users should understand
756 * it relates to cg-seek.
758 if (!is_empty_or_missing_file(git_path_head_name()))
759 return error(_("won't bisect on cg-seek'ed tree"));
760 strbuf_addstr(&start_head, head);
762 return error(_("bad HEAD - strange symbolic ref"));
767 * Get rid of any old bisect state.
769 if (bisect_clean_state())
770 return BISECT_FAILED;
773 * Write new start state
775 write_file(git_path_bisect_start(), "%s\n", start_head.buf);
777 if (first_parent_only)
778 write_file(git_path_bisect_first_parent(), "\n");
781 if (get_oid(start_head.buf, &oid) < 0) {
782 res = error(_("invalid ref: '%s'"), start_head.buf);
785 if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0,
786 UPDATE_REFS_MSG_ON_ERR)) {
792 if (pathspec_pos < argc - 1)
793 sq_quote_argv(&bisect_names, argv + pathspec_pos);
794 write_file(git_path_bisect_names(), "%s\n", bisect_names.buf);
796 for (i = 0; i < states.nr; i++)
797 if (bisect_write(states.items[i].string,
798 revs.items[i].string, terms, 1)) {
803 if (must_write_terms && write_terms(terms->term_bad,
809 res = bisect_append_log_quoted(argv);
814 string_list_clear(&revs, 0);
815 string_list_clear(&states, 0);
816 strbuf_release(&start_head);
817 strbuf_release(&bisect_names);
821 res = bisect_auto_next(terms, NULL);
822 if (!is_bisect_success(res))
823 bisect_clean_state();
827 static inline int file_is_not_empty(const char *path)
829 return !is_empty_or_missing_file(path);
832 static int bisect_autostart(struct bisect_terms *terms)
837 if (file_is_not_empty(git_path_bisect_start()))
840 fprintf_ln(stderr, _("You need to start by \"git bisect "
843 if (!isatty(STDIN_FILENO))
847 * TRANSLATORS: Make sure to include [Y] and [n] in your
848 * translation. The program will only accept English input
851 yesno = git_prompt(_("Do you want me to do it for you "
852 "[Y/n]? "), PROMPT_ECHO);
853 res = tolower(*yesno) == 'n' ?
854 -1 : bisect_start(terms, empty_strvec, 0);
859 int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
875 int res = 0, nolog = 0;
876 struct option options[] = {
877 OPT_CMDMODE(0, "next-all", &cmdmode,
878 N_("perform 'git bisect next'"), NEXT_ALL),
879 OPT_CMDMODE(0, "write-terms", &cmdmode,
880 N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS),
881 OPT_CMDMODE(0, "check-expected-revs", &cmdmode,
882 N_("check for expected revs"), CHECK_EXPECTED_REVS),
883 OPT_CMDMODE(0, "bisect-reset", &cmdmode,
884 N_("reset the bisection state"), BISECT_RESET),
885 OPT_CMDMODE(0, "bisect-write", &cmdmode,
886 N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE),
887 OPT_CMDMODE(0, "check-and-set-terms", &cmdmode,
888 N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS),
889 OPT_CMDMODE(0, "bisect-next-check", &cmdmode,
890 N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK),
891 OPT_CMDMODE(0, "bisect-terms", &cmdmode,
892 N_("print out the bisect terms"), BISECT_TERMS),
893 OPT_CMDMODE(0, "bisect-start", &cmdmode,
894 N_("start the bisect session"), BISECT_START),
895 OPT_CMDMODE(0, "bisect-next", &cmdmode,
896 N_("find the next bisection commit"), BISECT_NEXT),
897 OPT_CMDMODE(0, "bisect-auto-next", &cmdmode,
898 N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT),
899 OPT_CMDMODE(0, "bisect-autostart", &cmdmode,
900 N_("start the bisection if it has not yet been started"), BISECT_AUTOSTART),
901 OPT_BOOL(0, "no-log", &nolog,
902 N_("no log for BISECT_WRITE")),
905 struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };
907 argc = parse_options(argc, argv, prefix, options,
908 git_bisect_helper_usage,
909 PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN);
912 usage_with_options(git_bisect_helper_usage, options);
916 res = bisect_next_all(the_repository, prefix);
920 return error(_("--write-terms requires two arguments"));
921 return write_terms(argv[0], argv[1]);
922 case CHECK_EXPECTED_REVS:
923 check_expected_revs(argv, argc);
927 return error(_("--bisect-reset requires either no argument or a commit"));
928 return !!bisect_reset(argc ? argv[0] : NULL);
930 if (argc != 4 && argc != 5)
931 return error(_("--bisect-write requires either 4 or 5 arguments"));
932 set_terms(&terms, argv[3], argv[2]);
933 res = bisect_write(argv[0], argv[1], &terms, nolog);
935 case CHECK_AND_SET_TERMS:
937 return error(_("--check-and-set-terms requires 3 arguments"));
938 set_terms(&terms, argv[2], argv[1]);
939 res = check_and_set_terms(&terms, argv[0]);
941 case BISECT_NEXT_CHECK:
942 if (argc != 2 && argc != 3)
943 return error(_("--bisect-next-check requires 2 or 3 arguments"));
944 set_terms(&terms, argv[1], argv[0]);
945 res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);
949 return error(_("--bisect-terms requires 0 or 1 argument"));
950 res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);
953 set_terms(&terms, "bad", "good");
954 res = bisect_start(&terms, argv, argc);
958 return error(_("--bisect-next requires 0 arguments"));
960 res = bisect_next(&terms, prefix);
962 case BISECT_AUTO_NEXT:
964 return error(_("--bisect-auto-next requires 0 arguments"));
966 res = bisect_auto_next(&terms, prefix);
968 case BISECT_AUTOSTART:
970 return error(_("--bisect-autostart does not accept arguments"));
971 set_terms(&terms, "bad", "good");
972 res = bisect_autostart(&terms);
975 BUG("unknown subcommand %d", cmdmode);
980 * Handle early success
981 * From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all
983 if ((res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) || (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND))