1 #define USE_THE_REPOSITORY_VARIABLE
2 #define DISABLE_SIGN_COMPARE_WARNINGS
6 #include "environment.h"
9 #include "object-name.h"
10 #include "parse-options.h"
14 #include "run-command.h"
15 #include "oid-array.h"
21 static GIT_PATH_FUNC(git_path_bisect_terms
, "BISECT_TERMS")
22 static GIT_PATH_FUNC(git_path_bisect_ancestors_ok
, "BISECT_ANCESTORS_OK")
23 static GIT_PATH_FUNC(git_path_bisect_start
, "BISECT_START")
24 static GIT_PATH_FUNC(git_path_bisect_log
, "BISECT_LOG")
25 static GIT_PATH_FUNC(git_path_bisect_names
, "BISECT_NAMES")
26 static GIT_PATH_FUNC(git_path_bisect_first_parent
, "BISECT_FIRST_PARENT")
27 static GIT_PATH_FUNC(git_path_bisect_run
, "BISECT_RUN")
29 #define BUILTIN_GIT_BISECT_START_USAGE \
30 N_("git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]" \
31 " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--]" \
33 #define BUILTIN_GIT_BISECT_STATE_USAGE \
34 N_("git bisect (good|bad) [<rev>...]")
35 #define BUILTIN_GIT_BISECT_TERMS_USAGE \
36 "git bisect terms [--term-good | --term-bad]"
37 #define BUILTIN_GIT_BISECT_SKIP_USAGE \
38 N_("git bisect skip [(<rev>|<range>)...]")
39 #define BUILTIN_GIT_BISECT_NEXT_USAGE \
41 #define BUILTIN_GIT_BISECT_RESET_USAGE \
42 N_("git bisect reset [<commit>]")
43 #define BUILTIN_GIT_BISECT_VISUALIZE_USAGE \
44 "git bisect visualize"
45 #define BUILTIN_GIT_BISECT_REPLAY_USAGE \
46 N_("git bisect replay <logfile>")
47 #define BUILTIN_GIT_BISECT_LOG_USAGE \
49 #define BUILTIN_GIT_BISECT_RUN_USAGE \
50 N_("git bisect run <cmd> [<arg>...]")
52 static const char * const git_bisect_usage
[] = {
53 BUILTIN_GIT_BISECT_START_USAGE
,
54 BUILTIN_GIT_BISECT_STATE_USAGE
,
55 BUILTIN_GIT_BISECT_TERMS_USAGE
,
56 BUILTIN_GIT_BISECT_SKIP_USAGE
,
57 BUILTIN_GIT_BISECT_NEXT_USAGE
,
58 BUILTIN_GIT_BISECT_RESET_USAGE
,
59 BUILTIN_GIT_BISECT_VISUALIZE_USAGE
,
60 BUILTIN_GIT_BISECT_REPLAY_USAGE
,
61 BUILTIN_GIT_BISECT_LOG_USAGE
,
62 BUILTIN_GIT_BISECT_RUN_USAGE
,
66 struct add_bisect_ref_data
{
67 struct rev_info
*revs
;
68 unsigned int object_flags
;
76 static void free_terms(struct bisect_terms
*terms
)
78 FREE_AND_NULL(terms
->term_good
);
79 FREE_AND_NULL(terms
->term_bad
);
82 static void set_terms(struct bisect_terms
*terms
, const char *bad
,
85 free((void *)terms
->term_good
);
86 terms
->term_good
= xstrdup(good
);
87 free((void *)terms
->term_bad
);
88 terms
->term_bad
= xstrdup(bad
);
91 static const char vocab_bad
[] = "bad|new";
92 static const char vocab_good
[] = "good|old";
94 static int bisect_autostart(struct bisect_terms
*terms
);
97 * Check whether the string `term` belongs to the set of strings
98 * included in the variable arguments.
100 LAST_ARG_MUST_BE_NULL
101 static int one_of(const char *term
, ...)
107 va_start(matches
, term
);
108 while (!res
&& (match
= va_arg(matches
, const char *)))
109 res
= !strcmp(term
, match
);
116 * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE
117 * and BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND are codes
118 * that indicate special success.
121 static int is_bisect_success(enum bisect_error res
)
124 res
== BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND
||
125 res
== BISECT_INTERNAL_SUCCESS_MERGE_BASE
;
128 static int write_in_file(const char *path
, const char *mode
, const char *format
, va_list args
)
133 if (strcmp(mode
, "w") && strcmp(mode
, "a"))
134 BUG("write-in-file does not support '%s' mode", mode
);
135 fp
= fopen(path
, mode
);
137 return error_errno(_("cannot open file '%s' in mode '%s'"), path
, mode
);
138 res
= vfprintf(fp
, format
, args
);
141 int saved_errno
= errno
;
144 return error_errno(_("could not write to file '%s'"), path
);
150 __attribute__((format (printf
, 2, 3)))
151 static int write_to_file(const char *path
, const char *format
, ...)
156 va_start(args
, format
);
157 res
= write_in_file(path
, "w", format
, args
);
163 __attribute__((format (printf
, 2, 3)))
164 static int append_to_file(const char *path
, const char *format
, ...)
169 va_start(args
, format
);
170 res
= write_in_file(path
, "a", format
, args
);
176 static int print_file_to_stdout(const char *path
)
178 int fd
= open(path
, O_RDONLY
);
182 return error_errno(_("cannot open file '%s' for reading"), path
);
183 if (copy_fd(fd
, 1) < 0)
184 ret
= error_errno(_("failed to read '%s'"), path
);
189 static int check_term_format(const char *term
, const char *orig_term
)
192 char *new_term
= xstrfmt("refs/bisect/%s", term
);
194 res
= check_refname_format(new_term
, 0);
198 return error(_("'%s' is not a valid term"), term
);
200 if (one_of(term
, "help", "start", "skip", "next", "reset",
201 "visualize", "view", "replay", "log", "run", "terms", NULL
))
202 return error(_("can't use the builtin command '%s' as a term"), term
);
205 * In theory, nothing prevents swapping completely good and bad,
206 * but this situation could be confusing and hasn't been tested
207 * enough. Forbid it for now.
210 if ((strcmp(orig_term
, "bad") && one_of(term
, "bad", "new", NULL
)) ||
211 (strcmp(orig_term
, "good") && one_of(term
, "good", "old", NULL
)))
212 return error(_("can't change the meaning of the term '%s'"), term
);
217 static int write_terms(const char *bad
, const char *good
)
221 if (!strcmp(bad
, good
))
222 return error(_("please use two different terms"));
224 if (check_term_format(bad
, "bad") || check_term_format(good
, "good"))
227 res
= write_to_file(git_path_bisect_terms(), "%s\n%s\n", bad
, good
);
232 static int bisect_reset(const char *commit
)
234 struct strbuf branch
= STRBUF_INIT
;
237 if (!strbuf_read_file(&branch
, git_path_bisect_start(), 0))
238 printf(_("We are not bisecting.\n"));
240 strbuf_rtrim(&branch
);
242 struct object_id oid
;
244 if (repo_get_oid_commit(the_repository
, commit
, &oid
))
245 return error(_("'%s' is not a valid commit"), commit
);
246 strbuf_addstr(&branch
, commit
);
249 if (branch
.len
&& !refs_ref_exists(get_main_ref_store(the_repository
), "BISECT_HEAD")) {
250 struct child_process cmd
= CHILD_PROCESS_INIT
;
253 strvec_pushl(&cmd
.args
, "checkout", "--ignore-other-worktrees",
254 branch
.buf
, "--", NULL
);
255 if (run_command(&cmd
)) {
256 error(_("could not check out original"
257 " HEAD '%s'. Try 'git bisect"
258 " reset <commit>'."), branch
.buf
);
259 strbuf_release(&branch
);
264 strbuf_release(&branch
);
265 return bisect_clean_state();
268 static void log_commit(FILE *fp
,
269 const char *fmt
, const char *state
,
270 struct commit
*commit
)
272 struct pretty_print_context pp
= {0};
273 struct strbuf commit_msg
= STRBUF_INIT
;
274 char *label
= xstrfmt(fmt
, state
);
276 repo_format_commit_message(the_repository
, commit
, "%s", &commit_msg
,
279 fprintf(fp
, "# %s: [%s] %s\n", label
, oid_to_hex(&commit
->object
.oid
),
282 strbuf_release(&commit_msg
);
286 static int bisect_write(const char *state
, const char *rev
,
287 const struct bisect_terms
*terms
, int nolog
)
289 struct strbuf tag
= STRBUF_INIT
;
290 struct object_id oid
;
291 struct commit
*commit
;
295 if (!strcmp(state
, terms
->term_bad
)) {
296 strbuf_addf(&tag
, "refs/bisect/%s", state
);
297 } else if (one_of(state
, terms
->term_good
, "skip", NULL
)) {
298 strbuf_addf(&tag
, "refs/bisect/%s-%s", state
, rev
);
300 res
= error(_("Bad bisect_write argument: %s"), state
);
304 if (repo_get_oid(the_repository
, rev
, &oid
)) {
305 res
= error(_("couldn't get the oid of the rev '%s'"), rev
);
309 if (refs_update_ref(get_main_ref_store(the_repository
), NULL
, tag
.buf
, &oid
, NULL
, 0,
310 UPDATE_REFS_MSG_ON_ERR
)) {
315 fp
= fopen(git_path_bisect_log(), "a");
317 res
= error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
321 commit
= lookup_commit_reference(the_repository
, &oid
);
322 log_commit(fp
, "%s", state
, commit
);
325 fprintf(fp
, "git bisect %s %s\n", state
, rev
);
330 strbuf_release(&tag
);
334 static int check_and_set_terms(struct bisect_terms
*terms
, const char *cmd
)
336 int has_term_file
= !is_empty_or_missing_file(git_path_bisect_terms());
338 if (one_of(cmd
, "skip", "start", "terms", NULL
))
341 if (has_term_file
&& strcmp(cmd
, terms
->term_bad
) &&
342 strcmp(cmd
, terms
->term_good
))
343 return error(_("Invalid command: you're currently in a "
344 "%s/%s bisect"), terms
->term_bad
,
347 if (!has_term_file
) {
348 if (one_of(cmd
, "bad", "good", NULL
)) {
349 set_terms(terms
, "bad", "good");
350 return write_terms(terms
->term_bad
, terms
->term_good
);
352 if (one_of(cmd
, "new", "old", NULL
)) {
353 set_terms(terms
, "new", "old");
354 return write_terms(terms
->term_bad
, terms
->term_good
);
361 static int inc_nr(const char *refname UNUSED
,
362 const char *referent UNUSED
,
363 const struct object_id
*oid UNUSED
,
364 int flag UNUSED
, void *cb_data
)
366 unsigned int *nr
= (unsigned int *)cb_data
;
371 static const char need_bad_and_good_revision_warning
[] =
372 N_("You need to give me at least one %s and %s revision.\n"
373 "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
375 static const char need_bisect_start_warning
[] =
376 N_("You need to start by \"git bisect start\".\n"
377 "You then need to give me at least one %s and %s revision.\n"
378 "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
380 static int decide_next(const struct bisect_terms
*terms
,
381 const char *current_term
, int missing_good
,
384 if (!missing_good
&& !missing_bad
)
389 if (missing_good
&& !missing_bad
&&
390 !strcmp(current_term
, terms
->term_good
)) {
393 * have bad (or new) but not good (or old). We could bisect
394 * although this is less optimum.
396 warning(_("bisecting only with a %s commit"), terms
->term_bad
);
400 * TRANSLATORS: Make sure to include [Y] and [n] in your
401 * translation. The program will only accept English input
404 yesno
= git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO
);
405 if (starts_with(yesno
, "N") || starts_with(yesno
, "n"))
410 if (!is_empty_or_missing_file(git_path_bisect_start()))
411 return error(_(need_bad_and_good_revision_warning
),
412 vocab_bad
, vocab_good
, vocab_bad
, vocab_good
);
414 return error(_(need_bisect_start_warning
),
415 vocab_good
, vocab_bad
, vocab_good
, vocab_bad
);
418 static void bisect_status(struct bisect_state
*state
,
419 const struct bisect_terms
*terms
)
421 char *bad_ref
= xstrfmt("refs/bisect/%s", terms
->term_bad
);
422 char *good_glob
= xstrfmt("%s-*", terms
->term_good
);
424 if (refs_ref_exists(get_main_ref_store(the_repository
), bad_ref
))
427 refs_for_each_glob_ref_in(get_main_ref_store(the_repository
), inc_nr
,
428 good_glob
, "refs/bisect/",
429 (void *) &state
->nr_good
);
435 __attribute__((format (printf
, 1, 2)))
436 static void bisect_log_printf(const char *fmt
, ...)
438 struct strbuf buf
= STRBUF_INIT
;
442 strbuf_vaddf(&buf
, fmt
, ap
);
445 printf("%s", buf
.buf
);
446 append_to_file(git_path_bisect_log(), "# %s", buf
.buf
);
448 strbuf_release(&buf
);
451 static void bisect_print_status(const struct bisect_terms
*terms
)
453 struct bisect_state state
= { 0 };
455 bisect_status(&state
, terms
);
457 /* If we had both, we'd already be started, and shouldn't get here. */
458 if (state
.nr_good
&& state
.nr_bad
)
461 if (!state
.nr_good
&& !state
.nr_bad
)
462 bisect_log_printf(_("status: waiting for both good and bad commits\n"));
463 else if (state
.nr_good
)
464 bisect_log_printf(Q_("status: waiting for bad commit, %d good commit known\n",
465 "status: waiting for bad commit, %d good commits known\n",
466 state
.nr_good
), state
.nr_good
);
468 bisect_log_printf(_("status: waiting for good commit(s), bad commit known\n"));
471 static int bisect_next_check(const struct bisect_terms
*terms
,
472 const char *current_term
)
474 struct bisect_state state
= { 0 };
475 bisect_status(&state
, terms
);
476 return decide_next(terms
, current_term
, !state
.nr_good
, !state
.nr_bad
);
479 static int get_terms(struct bisect_terms
*terms
)
481 struct strbuf str
= STRBUF_INIT
;
485 fp
= fopen(git_path_bisect_terms(), "r");
492 strbuf_getline_lf(&str
, fp
);
493 terms
->term_bad
= strbuf_detach(&str
, NULL
);
494 strbuf_getline_lf(&str
, fp
);
495 terms
->term_good
= strbuf_detach(&str
, NULL
);
500 strbuf_release(&str
);
504 static int bisect_terms(struct bisect_terms
*terms
, const char *option
)
506 if (get_terms(terms
))
507 return error(_("no terms defined"));
510 printf(_("Your current terms are %s for the old state\n"
511 "and %s for the new state.\n"),
512 terms
->term_good
, terms
->term_bad
);
515 if (one_of(option
, "--term-good", "--term-old", NULL
))
516 printf("%s\n", terms
->term_good
);
517 else if (one_of(option
, "--term-bad", "--term-new", NULL
))
518 printf("%s\n", terms
->term_bad
);
520 return error(_("invalid argument %s for 'git bisect terms'.\n"
521 "Supported options are: "
522 "--term-good|--term-old and "
523 "--term-bad|--term-new."), option
);
528 static int bisect_append_log_quoted(const char **argv
)
531 FILE *fp
= fopen(git_path_bisect_log(), "a");
532 struct strbuf orig_args
= STRBUF_INIT
;
537 if (fprintf(fp
, "git bisect start") < 1) {
542 sq_quote_argv(&orig_args
, argv
);
543 if (fprintf(fp
, "%s\n", orig_args
.buf
) < 1)
548 strbuf_release(&orig_args
);
552 static int add_bisect_ref(const char *refname
, const char *referent UNUSED
, const struct object_id
*oid
,
553 int flags UNUSED
, void *cb
)
555 struct add_bisect_ref_data
*data
= cb
;
557 add_pending_oid(data
->revs
, refname
, oid
, data
->object_flags
);
562 static int prepare_revs(struct bisect_terms
*terms
, struct rev_info
*revs
)
565 struct add_bisect_ref_data cb
= { revs
};
566 char *good
= xstrfmt("%s-*", terms
->term_good
);
569 * We cannot use terms->term_bad directly in
570 * for_each_glob_ref_in() and we have to append a '*' to it,
571 * otherwise for_each_glob_ref_in() will append '/' and '*'.
573 char *bad
= xstrfmt("%s*", terms
->term_bad
);
576 * It is important to reset the flags used by revision walks
577 * as the previous call to bisect_next_all() in turn
578 * sets up a revision walk.
580 reset_revision_walk();
581 repo_init_revisions(the_repository
, revs
, NULL
);
582 setup_revisions(0, NULL
, revs
, NULL
);
583 refs_for_each_glob_ref_in(get_main_ref_store(the_repository
),
584 add_bisect_ref
, bad
, "refs/bisect/", &cb
);
585 cb
.object_flags
= UNINTERESTING
;
586 refs_for_each_glob_ref_in(get_main_ref_store(the_repository
),
587 add_bisect_ref
, good
, "refs/bisect/", &cb
);
588 if (prepare_revision_walk(revs
))
589 res
= error(_("revision walk setup failed"));
596 static int bisect_skipped_commits(struct bisect_terms
*terms
)
600 struct rev_info revs
;
601 struct commit
*commit
;
602 struct pretty_print_context pp
= {0};
603 struct strbuf commit_name
= STRBUF_INIT
;
605 res
= prepare_revs(terms
, &revs
);
609 fp
= fopen(git_path_bisect_log(), "a");
611 return error_errno(_("could not open '%s' for appending"),
612 git_path_bisect_log());
614 if (fprintf(fp
, "# only skipped commits left to test\n") < 0)
615 return error_errno(_("failed to write to '%s'"), git_path_bisect_log());
617 while ((commit
= get_revision(&revs
)) != NULL
) {
618 strbuf_reset(&commit_name
);
619 repo_format_commit_message(the_repository
, commit
, "%s",
621 fprintf(fp
, "# possible first %s commit: [%s] %s\n",
622 terms
->term_bad
, oid_to_hex(&commit
->object
.oid
),
627 * Reset the flags used by revision walks in case
628 * there is another revision walk after this one.
630 reset_revision_walk();
632 strbuf_release(&commit_name
);
633 release_revisions(&revs
);
638 static int bisect_successful(struct bisect_terms
*terms
)
640 struct object_id oid
;
641 struct commit
*commit
;
642 struct pretty_print_context pp
= {0};
643 struct strbuf commit_name
= STRBUF_INIT
;
644 char *bad_ref
= xstrfmt("refs/bisect/%s",terms
->term_bad
);
647 refs_read_ref(get_main_ref_store(the_repository
), bad_ref
, &oid
);
648 commit
= lookup_commit_reference_by_name(bad_ref
);
649 repo_format_commit_message(the_repository
, commit
, "%s", &commit_name
,
652 res
= append_to_file(git_path_bisect_log(), "# first %s commit: [%s] %s\n",
653 terms
->term_bad
, oid_to_hex(&commit
->object
.oid
),
656 strbuf_release(&commit_name
);
661 static enum bisect_error
bisect_next(struct bisect_terms
*terms
, const char *prefix
)
663 enum bisect_error res
;
665 if (bisect_autostart(terms
))
666 return BISECT_FAILED
;
668 if (bisect_next_check(terms
, terms
->term_good
))
669 return BISECT_FAILED
;
671 /* Perform all bisection computation */
672 res
= bisect_next_all(the_repository
, prefix
);
674 if (res
== BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND
) {
675 res
= bisect_successful(terms
);
676 return res
? res
: BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND
;
677 } else if (res
== BISECT_ONLY_SKIPPED_LEFT
) {
678 res
= bisect_skipped_commits(terms
);
679 return res
? res
: BISECT_ONLY_SKIPPED_LEFT
;
684 static enum bisect_error
bisect_auto_next(struct bisect_terms
*terms
, const char *prefix
)
686 if (bisect_next_check(terms
, NULL
)) {
687 bisect_print_status(terms
);
691 return bisect_next(terms
, prefix
);
694 static enum bisect_error
bisect_start(struct bisect_terms
*terms
, int argc
,
698 int first_parent_only
= 0;
699 int i
, has_double_dash
= 0, must_write_terms
= 0, bad_seen
= 0;
700 int flags
, pathspec_pos
;
701 enum bisect_error res
= BISECT_OK
;
702 struct string_list revs
= STRING_LIST_INIT_DUP
;
703 struct string_list states
= STRING_LIST_INIT_DUP
;
704 struct strbuf start_head
= STRBUF_INIT
;
705 struct strbuf bisect_names
= STRBUF_INIT
;
706 struct object_id head_oid
;
707 struct object_id oid
;
710 if (is_bare_repository())
714 * Check for one bad and then some good revisions
716 for (i
= 0; i
< argc
; i
++) {
717 if (!strcmp(argv
[i
], "--")) {
723 for (i
= 0; i
< argc
; i
++) {
724 const char *arg
= argv
[i
];
725 if (!strcmp(argv
[i
], "--")) {
727 } else if (!strcmp(arg
, "--no-checkout")) {
729 } else if (!strcmp(arg
, "--first-parent")) {
730 first_parent_only
= 1;
731 } else if (!strcmp(arg
, "--term-good") ||
732 !strcmp(arg
, "--term-old")) {
735 return error(_("'' is not a valid term"));
736 must_write_terms
= 1;
737 free((void *) terms
->term_good
);
738 terms
->term_good
= xstrdup(argv
[i
]);
739 } else if (skip_prefix(arg
, "--term-good=", &arg
) ||
740 skip_prefix(arg
, "--term-old=", &arg
)) {
741 must_write_terms
= 1;
742 free((void *) terms
->term_good
);
743 terms
->term_good
= xstrdup(arg
);
744 } else if (!strcmp(arg
, "--term-bad") ||
745 !strcmp(arg
, "--term-new")) {
748 return error(_("'' is not a valid term"));
749 must_write_terms
= 1;
750 free((void *) terms
->term_bad
);
751 terms
->term_bad
= xstrdup(argv
[i
]);
752 } else if (skip_prefix(arg
, "--term-bad=", &arg
) ||
753 skip_prefix(arg
, "--term-new=", &arg
)) {
754 must_write_terms
= 1;
755 free((void *) terms
->term_bad
);
756 terms
->term_bad
= xstrdup(arg
);
757 } else if (starts_with(arg
, "--")) {
758 return error(_("unrecognized option: '%s'"), arg
);
759 } else if (!get_oidf(&oid
, "%s^{commit}", arg
)) {
760 string_list_append(&revs
, oid_to_hex(&oid
));
761 } else if (has_double_dash
) {
762 die(_("'%s' does not appear to be a valid "
771 * The user ran "git bisect start <sha1> <sha1>", hence did not
772 * explicitly specify the terms, but we are already starting to
773 * set references named with the default terms, and won't be able
774 * to change afterwards.
777 must_write_terms
= 1;
778 for (i
= 0; i
< revs
.nr
; i
++) {
780 string_list_append(&states
, terms
->term_good
);
783 string_list_append(&states
, terms
->term_bad
);
790 head
= refs_resolve_ref_unsafe(get_main_ref_store(the_repository
),
791 "HEAD", 0, &head_oid
, &flags
);
793 if (repo_get_oid(the_repository
, "HEAD", &head_oid
))
794 return error(_("bad HEAD - I need a HEAD"));
797 * Check if we are bisecting
799 if (!is_empty_or_missing_file(git_path_bisect_start())) {
800 /* Reset to the rev from where we started */
801 strbuf_read_file(&start_head
, git_path_bisect_start(), 0);
802 strbuf_trim(&start_head
);
804 struct child_process cmd
= CHILD_PROCESS_INIT
;
807 strvec_pushl(&cmd
.args
, "checkout", start_head
.buf
,
809 if (run_command(&cmd
)) {
810 res
= error(_("checking out '%s' failed."
811 " Try 'git bisect start "
818 /* Get the rev from where we start. */
819 if (!repo_get_oid(the_repository
, head
, &head_oid
) &&
820 !starts_with(head
, "refs/heads/")) {
821 strbuf_reset(&start_head
);
822 strbuf_addstr(&start_head
, oid_to_hex(&head_oid
));
823 } else if (!repo_get_oid(the_repository
, head
, &head_oid
) &&
824 skip_prefix(head
, "refs/heads/", &head
)) {
825 strbuf_addstr(&start_head
, head
);
827 return error(_("bad HEAD - strange symbolic ref"));
832 * Get rid of any old bisect state.
834 if (bisect_clean_state())
835 return BISECT_FAILED
;
838 * Write new start state
840 write_file(git_path_bisect_start(), "%s\n", start_head
.buf
);
842 if (first_parent_only
)
843 write_file(git_path_bisect_first_parent(), "\n");
846 if (repo_get_oid(the_repository
, start_head
.buf
, &oid
) < 0) {
847 res
= error(_("invalid ref: '%s'"), start_head
.buf
);
850 if (refs_update_ref(get_main_ref_store(the_repository
), NULL
, "BISECT_HEAD", &oid
, NULL
, 0,
851 UPDATE_REFS_MSG_ON_ERR
)) {
857 if (pathspec_pos
< argc
- 1)
858 sq_quote_argv(&bisect_names
, argv
+ pathspec_pos
);
859 write_file(git_path_bisect_names(), "%s\n", bisect_names
.buf
);
861 for (i
= 0; i
< states
.nr
; i
++)
862 if (bisect_write(states
.items
[i
].string
,
863 revs
.items
[i
].string
, terms
, 1)) {
868 if (must_write_terms
&& write_terms(terms
->term_bad
,
874 res
= bisect_append_log_quoted(argv
);
879 string_list_clear(&revs
, 0);
880 string_list_clear(&states
, 0);
881 strbuf_release(&start_head
);
882 strbuf_release(&bisect_names
);
886 res
= bisect_auto_next(terms
, NULL
);
887 if (!is_bisect_success(res
))
888 bisect_clean_state();
892 static inline int file_is_not_empty(const char *path
)
894 return !is_empty_or_missing_file(path
);
897 static int bisect_autostart(struct bisect_terms
*terms
)
902 if (file_is_not_empty(git_path_bisect_start()))
905 fprintf_ln(stderr
, _("You need to start by \"git bisect "
908 if (!isatty(STDIN_FILENO
))
912 * TRANSLATORS: Make sure to include [Y] and [n] in your
913 * translation. The program will only accept English input
916 yesno
= git_prompt(_("Do you want me to do it for you "
917 "[Y/n]? "), PROMPT_ECHO
);
918 res
= tolower(*yesno
) == 'n' ?
919 -1 : bisect_start(terms
, 0, empty_strvec
);
924 static enum bisect_error
bisect_state(struct bisect_terms
*terms
, int argc
,
928 int i
, verify_expected
= 1;
929 struct object_id oid
, expected
;
930 struct oid_array revs
= OID_ARRAY_INIT
;
933 return error(_("Please call `--bisect-state` with at least one argument"));
935 if (bisect_autostart(terms
))
936 return BISECT_FAILED
;
939 if (check_and_set_terms(terms
, state
) ||
940 !one_of(state
, terms
->term_good
, terms
->term_bad
, "skip", NULL
))
941 return BISECT_FAILED
;
945 if (argc
> 1 && !strcmp(state
, terms
->term_bad
))
946 return error(_("'git bisect %s' can take only one argument."), terms
->term_bad
);
949 const char *head
= "BISECT_HEAD";
950 enum get_oid_result res_head
= repo_get_oid(the_repository
,
953 if (res_head
== MISSING_OBJECT
) {
955 res_head
= repo_get_oid(the_repository
, head
, &oid
);
959 error(_("Bad rev input: %s"), head
);
960 oid_array_append(&revs
, &oid
);
964 * All input revs must be checked before executing bisect_write()
965 * to discard junk revs.
968 for (; argc
; argc
--, argv
++) {
969 struct commit
*commit
;
971 if (repo_get_oid(the_repository
, *argv
, &oid
)){
972 error(_("Bad rev input: %s"), *argv
);
973 oid_array_clear(&revs
);
974 return BISECT_FAILED
;
977 commit
= lookup_commit_reference(the_repository
, &oid
);
979 die(_("Bad rev input (not a commit): %s"), *argv
);
981 oid_array_append(&revs
, &commit
->object
.oid
);
984 if (refs_read_ref(get_main_ref_store(the_repository
), "BISECT_EXPECTED_REV", &expected
))
985 verify_expected
= 0; /* Ignore invalid file contents */
987 for (i
= 0; i
< revs
.nr
; i
++) {
988 if (bisect_write(state
, oid_to_hex(&revs
.oid
[i
]), terms
, 0)) {
989 oid_array_clear(&revs
);
990 return BISECT_FAILED
;
992 if (verify_expected
&& !oideq(&revs
.oid
[i
], &expected
)) {
993 unlink_or_warn(git_path_bisect_ancestors_ok());
994 refs_delete_ref(get_main_ref_store(the_repository
),
995 NULL
, "BISECT_EXPECTED_REV", NULL
,
1001 oid_array_clear(&revs
);
1002 return bisect_auto_next(terms
, NULL
);
1005 static enum bisect_error
bisect_log(void)
1008 const char* filename
= git_path_bisect_log();
1010 if (is_empty_or_missing_file(filename
))
1011 return error(_("We are not bisecting."));
1013 fd
= open(filename
, O_RDONLY
);
1015 return BISECT_FAILED
;
1017 status
= copy_fd(fd
, STDOUT_FILENO
);
1019 return status
? BISECT_FAILED
: BISECT_OK
;
1022 static int process_replay_line(struct bisect_terms
*terms
, struct strbuf
*line
)
1024 const char *p
= line
->buf
+ strspn(line
->buf
, " \t");
1025 char *word_end
, *rev
;
1027 if ((!skip_prefix(p
, "git bisect", &p
) &&
1028 !skip_prefix(p
, "git-bisect", &p
)) || !isspace(*p
))
1030 p
+= strspn(p
, " \t");
1032 word_end
= (char *)p
+ strcspn(p
, " \t");
1033 rev
= word_end
+ strspn(word_end
, " \t");
1034 *word_end
= '\0'; /* NUL-terminate the word */
1037 if (check_and_set_terms(terms
, p
))
1040 if (!strcmp(p
, "start")) {
1041 struct strvec argv
= STRVEC_INIT
;
1043 sq_dequote_to_strvec(rev
, &argv
);
1044 res
= bisect_start(terms
, argv
.nr
, argv
.v
);
1045 strvec_clear(&argv
);
1049 if (one_of(p
, terms
->term_good
,
1050 terms
->term_bad
, "skip", NULL
))
1051 return bisect_write(p
, rev
, terms
, 0);
1053 if (!strcmp(p
, "terms")) {
1054 struct strvec argv
= STRVEC_INIT
;
1056 sq_dequote_to_strvec(rev
, &argv
);
1057 res
= bisect_terms(terms
, argv
.nr
== 1 ? argv
.v
[0] : NULL
);
1058 strvec_clear(&argv
);
1061 error(_("'%s'?? what are you talking about?"), p
);
1066 static enum bisect_error
bisect_replay(struct bisect_terms
*terms
, const char *filename
)
1069 enum bisect_error res
= BISECT_OK
;
1070 struct strbuf line
= STRBUF_INIT
;
1072 if (is_empty_or_missing_file(filename
))
1073 return error(_("cannot read file '%s' for replaying"), filename
);
1075 if (bisect_reset(NULL
))
1076 return BISECT_FAILED
;
1078 fp
= fopen(filename
, "r");
1080 return BISECT_FAILED
;
1082 while ((strbuf_getline(&line
, fp
) != EOF
) && !res
)
1083 res
= process_replay_line(terms
, &line
);
1085 strbuf_release(&line
);
1089 return BISECT_FAILED
;
1091 return bisect_auto_next(terms
, NULL
);
1094 static enum bisect_error
bisect_skip(struct bisect_terms
*terms
, int argc
,
1098 enum bisect_error res
;
1099 struct strvec argv_state
= STRVEC_INIT
;
1101 strvec_push(&argv_state
, "skip");
1103 for (i
= 0; i
< argc
; i
++) {
1104 const char *dotdot
= strstr(argv
[i
], "..");
1107 struct rev_info revs
;
1108 struct commit
*commit
;
1110 repo_init_revisions(the_repository
, &revs
, NULL
);
1111 setup_revisions(2, argv
+ i
- 1, &revs
, NULL
);
1113 if (prepare_revision_walk(&revs
))
1114 die(_("revision walk setup failed"));
1115 while ((commit
= get_revision(&revs
)) != NULL
)
1116 strvec_push(&argv_state
,
1117 oid_to_hex(&commit
->object
.oid
));
1119 reset_revision_walk();
1120 release_revisions(&revs
);
1122 strvec_push(&argv_state
, argv
[i
]);
1125 res
= bisect_state(terms
, argv_state
.nr
, argv_state
.v
);
1127 strvec_clear(&argv_state
);
1131 static int bisect_visualize(struct bisect_terms
*terms
, int argc
,
1134 struct child_process cmd
= CHILD_PROCESS_INIT
;
1135 struct strbuf sb
= STRBUF_INIT
;
1137 if (bisect_next_check(terms
, NULL
) != 0)
1138 return BISECT_FAILED
;
1142 if ((getenv("DISPLAY") || getenv("SESSIONNAME") || getenv("MSYSTEM") ||
1143 getenv("SECURITYSESSIONID")) && exists_in_PATH("gitk")) {
1144 strvec_push(&cmd
.args
, "gitk");
1146 strvec_push(&cmd
.args
, "log");
1150 if (argv
[0][0] == '-') {
1151 strvec_push(&cmd
.args
, "log");
1153 } else if (strcmp(argv
[0], "tig") && !starts_with(argv
[0], "git"))
1156 strvec_pushv(&cmd
.args
, argv
);
1159 strvec_pushl(&cmd
.args
, "--bisect", "--", NULL
);
1161 strbuf_read_file(&sb
, git_path_bisect_names(), 0);
1162 sq_dequote_to_strvec(sb
.buf
, &cmd
.args
);
1163 strbuf_release(&sb
);
1165 return run_command(&cmd
);
1168 static int get_first_good(const char *refname UNUSED
,
1169 const char *referent UNUSED
,
1170 const struct object_id
*oid
,
1171 int flag UNUSED
, void *cb_data
)
1173 oidcpy(cb_data
, oid
);
1177 static int do_bisect_run(const char *command
)
1179 struct child_process cmd
= CHILD_PROCESS_INIT
;
1181 printf(_("running %s\n"), command
);
1183 strvec_push(&cmd
.args
, command
);
1184 return run_command(&cmd
);
1187 static int verify_good(const struct bisect_terms
*terms
, const char *command
)
1190 enum bisect_error res
;
1191 struct object_id good_rev
;
1192 struct object_id current_rev
;
1193 char *good_glob
= xstrfmt("%s-*", terms
->term_good
);
1194 int no_checkout
= refs_ref_exists(get_main_ref_store(the_repository
),
1197 refs_for_each_glob_ref_in(get_main_ref_store(the_repository
),
1198 get_first_good
, good_glob
, "refs/bisect/",
1202 if (refs_read_ref(get_main_ref_store(the_repository
), no_checkout
? "BISECT_HEAD" : "HEAD", ¤t_rev
))
1205 res
= bisect_checkout(&good_rev
, no_checkout
);
1206 if (res
!= BISECT_OK
)
1209 rc
= do_bisect_run(command
);
1211 res
= bisect_checkout(¤t_rev
, no_checkout
);
1212 if (res
!= BISECT_OK
)
1218 static int bisect_run(struct bisect_terms
*terms
, int argc
, const char **argv
)
1220 int res
= BISECT_OK
;
1221 struct strbuf command
= STRBUF_INIT
;
1222 const char *new_state
;
1223 int temporary_stdout_fd
, saved_stdout
;
1224 int is_first_run
= 1;
1226 if (bisect_next_check(terms
, NULL
))
1227 return BISECT_FAILED
;
1230 error(_("bisect run failed: no command provided."));
1231 return BISECT_FAILED
;
1234 sq_quote_argv(&command
, argv
);
1235 strbuf_ltrim(&command
);
1237 res
= do_bisect_run(command
.buf
);
1240 * Exit code 126 and 127 can either come from the shell
1241 * if it was unable to execute or even find the script,
1242 * or from the script itself. Check with a known-good
1243 * revision to avoid trashing the bisect run due to a
1244 * missing or non-executable script.
1246 if (is_first_run
&& (res
== 126 || res
== 127)) {
1247 int rc
= verify_good(terms
, command
.buf
);
1249 if (rc
< 0 || 128 <= rc
) {
1250 error(_("unable to verify %s on good"
1251 " revision"), command
.buf
);
1252 res
= BISECT_FAILED
;
1256 error(_("bogus exit code %d for good revision"),
1258 res
= BISECT_FAILED
;
1263 if (res
< 0 || 128 <= res
) {
1264 error(_("bisect run failed: exit code %d from"
1265 " %s is < 0 or >= 128"), res
, command
.buf
);
1272 new_state
= terms
->term_good
;
1274 new_state
= terms
->term_bad
;
1276 temporary_stdout_fd
= open(git_path_bisect_run(), O_CREAT
| O_WRONLY
| O_TRUNC
, 0666);
1278 if (temporary_stdout_fd
< 0) {
1279 res
= error_errno(_("cannot open file '%s' for writing"), git_path_bisect_run());
1284 saved_stdout
= dup(1);
1285 dup2(temporary_stdout_fd
, 1);
1287 res
= bisect_state(terms
, 1, &new_state
);
1290 dup2(saved_stdout
, 1);
1291 close(saved_stdout
);
1292 close(temporary_stdout_fd
);
1294 print_file_to_stdout(git_path_bisect_run());
1296 if (res
== BISECT_ONLY_SKIPPED_LEFT
)
1297 error(_("bisect run cannot continue any more"));
1298 else if (res
== BISECT_INTERNAL_SUCCESS_MERGE_BASE
) {
1299 puts(_("bisect run success"));
1301 } else if (res
== BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND
) {
1302 puts(_("bisect found first bad commit"));
1305 error(_("bisect run failed: 'git bisect %s'"
1306 " exited with error code %d"), new_state
, res
);
1313 strbuf_release(&command
);
1317 static int cmd_bisect__reset(int argc
, const char **argv
, const char *prefix UNUSED
,
1318 struct repository
*repo UNUSED
)
1321 return error(_("'%s' requires either no argument or a commit"),
1322 "git bisect reset");
1323 return bisect_reset(argc
? argv
[0] : NULL
);
1326 static int cmd_bisect__terms(int argc
, const char **argv
, const char *prefix UNUSED
,
1327 struct repository
*repo UNUSED
)
1330 struct bisect_terms terms
= { 0 };
1333 return error(_("'%s' requires 0 or 1 argument"),
1334 "git bisect terms");
1335 res
= bisect_terms(&terms
, argc
== 1 ? argv
[0] : NULL
);
1340 static int cmd_bisect__start(int argc
, const char **argv
, const char *prefix UNUSED
,
1341 struct repository
*repo UNUSED
)
1344 struct bisect_terms terms
= { 0 };
1346 set_terms(&terms
, "bad", "good");
1347 res
= bisect_start(&terms
, argc
, argv
);
1352 static int cmd_bisect__next(int argc
, const char **argv UNUSED
, const char *prefix
,
1353 struct repository
*repo UNUSED
)
1356 struct bisect_terms terms
= { 0 };
1359 return error(_("'%s' requires 0 arguments"),
1362 res
= bisect_next(&terms
, prefix
);
1367 static int cmd_bisect__log(int argc UNUSED
, const char **argv UNUSED
,
1368 const char *prefix UNUSED
,
1369 struct repository
*repo UNUSED
)
1371 return bisect_log();
1374 static int cmd_bisect__replay(int argc
, const char **argv
, const char *prefix UNUSED
,
1375 struct repository
*repo UNUSED
)
1378 struct bisect_terms terms
= { 0 };
1381 return error(_("no logfile given"));
1382 set_terms(&terms
, "bad", "good");
1383 res
= bisect_replay(&terms
, argv
[0]);
1388 static int cmd_bisect__skip(int argc
, const char **argv
, const char *prefix UNUSED
,
1389 struct repository
*repo UNUSED
)
1392 struct bisect_terms terms
= { 0 };
1394 set_terms(&terms
, "bad", "good");
1396 res
= bisect_skip(&terms
, argc
, argv
);
1401 static int cmd_bisect__visualize(int argc
, const char **argv
, const char *prefix UNUSED
,
1402 struct repository
*repo UNUSED
)
1405 struct bisect_terms terms
= { 0 };
1408 res
= bisect_visualize(&terms
, argc
, argv
);
1413 static int cmd_bisect__run(int argc
, const char **argv
, const char *prefix UNUSED
,
1414 struct repository
*repo UNUSED
)
1417 struct bisect_terms terms
= { 0 };
1420 return error(_("'%s' failed: no command provided."), "git bisect run");
1422 res
= bisect_run(&terms
, argc
, argv
);
1427 int cmd_bisect(int argc
,
1430 struct repository
*repo
)
1433 parse_opt_subcommand_fn
*fn
= NULL
;
1434 struct option options
[] = {
1435 OPT_SUBCOMMAND("reset", &fn
, cmd_bisect__reset
),
1436 OPT_SUBCOMMAND("terms", &fn
, cmd_bisect__terms
),
1437 OPT_SUBCOMMAND("start", &fn
, cmd_bisect__start
),
1438 OPT_SUBCOMMAND("next", &fn
, cmd_bisect__next
),
1439 OPT_SUBCOMMAND("log", &fn
, cmd_bisect__log
),
1440 OPT_SUBCOMMAND("replay", &fn
, cmd_bisect__replay
),
1441 OPT_SUBCOMMAND("skip", &fn
, cmd_bisect__skip
),
1442 OPT_SUBCOMMAND("visualize", &fn
, cmd_bisect__visualize
),
1443 OPT_SUBCOMMAND("view", &fn
, cmd_bisect__visualize
),
1444 OPT_SUBCOMMAND("run", &fn
, cmd_bisect__run
),
1447 argc
= parse_options(argc
, argv
, prefix
, options
, git_bisect_usage
,
1448 PARSE_OPT_SUBCOMMAND_OPTIONAL
);
1451 struct bisect_terms terms
= { 0 };
1454 usage_msg_opt(_("need a command"), git_bisect_usage
, options
);
1456 set_terms(&terms
, "bad", "good");
1458 if (check_and_set_terms(&terms
, argv
[0]))
1459 usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage
,
1461 res
= bisect_state(&terms
, argc
, argv
);
1466 res
= fn(argc
, argv
, prefix
, repo
);
1469 return is_bisect_success(res
) ? 0 : -res
;