From 88ad372fc02c119a4e44ae71c93b6fab9d998512 Mon Sep 17 00:00:00 2001 From: Pranit Bauva Date: Thu, 15 Oct 2020 15:38:32 +0200 Subject: bisect--helper: finish porting `bisect_start()` to C Add the subcommand to `git bisect--helper` and call it from git-bisect.sh. With the conversion of `bisect_auto_next()` from shell to C in a previous commit, `bisect_start()` can now be fully ported to C. So let's complete the `--bisect-start` subcommand of `git bisect--helper` so that it fully implements `bisect_start()`, and let's use this subcommand in `git-bisect.sh` instead of `bisect_start()`. Note that the `eval` in the changed line of `git-bisect.sh` cannot be dropped: it is necessary because the `rev` and the `tail` variables may contain multiple, quoted arguments that need to be passed to `bisect--helper` (without the quotes, naturally). Mentored-by: Christian Couder Mentored-by: Johannes Schindelin Signed-off-by: Pranit Bauva Signed-off-by: Tanushree Tumane Signed-off-by: Miriam Rubio Reviewed-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/bisect--helper.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'builtin') diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 64f16d5d92..0196ee144c 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -85,6 +85,19 @@ static int one_of(const char *term, ...) return res; } +/* + * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE + * and BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND are codes + * that indicate special success. + */ + +static int is_bisect_success(enum bisect_error res) +{ + return !res || + res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND || + res == BISECT_INTERNAL_SUCCESS_MERGE_BASE; +} + static int write_in_file(const char *path, const char *mode, const char *format, va_list args) { FILE *fp = NULL; @@ -609,12 +622,13 @@ static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char return bisect_next(terms, prefix); } -static int bisect_start(struct bisect_terms *terms, const char **argv, int argc) +static enum bisect_error bisect_start(struct bisect_terms *terms, const char **argv, int argc) { int no_checkout = 0; int first_parent_only = 0; 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; @@ -754,14 +768,7 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc) * Get rid of any old bisect state. */ if (bisect_clean_state()) - return -1; - - /* - * 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". - */ + return BISECT_FAILED; /* * Write new start state @@ -778,7 +785,7 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc) } if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR)) { - res = -1; + res = BISECT_FAILED; goto finish; } } @@ -790,25 +797,31 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc) 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); + if (!is_bisect_success(res)) + bisect_clean_state(); return res; } -- cgit v1.2.3 From e4396072e7b377ed4736e3fbd2b127e6e03da58c Mon Sep 17 00:00:00 2001 From: Pranit Bauva Date: Thu, 15 Oct 2020 15:38:33 +0200 Subject: bisect--helper: retire `--bisect-clean-state` subcommand The `--bisect-clean-state` subcommand is no longer used from the git-bisect.sh shell script. Instead the function `bisect_clean_state()` is directly called from the C implementation. Mentored-by: Lars Schneider Mentored-by: Christian Couder Signed-off-by: Pranit Bauva Signed-off-by: Tanushree Tumane Signed-off-by: Miriam Rubio Reviewed-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/bisect--helper.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'builtin') diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 0196ee144c..1b9ee7d963 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -22,7 +22,6 @@ static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT") static const char * const git_bisect_helper_usage[] = { N_("git bisect--helper --next-all"), 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 "), @@ -862,7 +861,6 @@ 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_WRITE, @@ -880,8 +878,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) 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, @@ -923,10 +919,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) 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; -- cgit v1.2.3 From 04774b4e7090e6b418ab053a6d4412a665cae703 Mon Sep 17 00:00:00 2001 From: Pranit Bauva Date: Thu, 15 Oct 2020 15:38:34 +0200 Subject: bisect--helper: retire `--next-all` subcommand The `--next-all` subcommand is no longer used from the git-bisect.sh shell script. Instead the function `bisect_next_all()` is called from the C implementation of `bisect_next()`. Mentored-by: Lars Schneider Mentored-by: Christian Couder Signed-off-by: Pranit Bauva Signed-off-by: Tanushree Tumane Signed-off-by: Miriam Rubio Reviewed-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/bisect--helper.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'builtin') diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 1b9ee7d963..868bdb2c8b 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -20,7 +20,6 @@ static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT") static const char * const git_bisect_helper_usage[] = { - N_("git bisect--helper --next-all"), N_("git bisect--helper --write-terms "), N_("git bisect--helper --bisect-reset []"), N_("git bisect--helper --bisect-write [--no-log] "), @@ -859,8 +858,7 @@ static int bisect_autostart(struct bisect_terms *terms) int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { - NEXT_ALL = 1, - WRITE_TERMS, + WRITE_TERMS = 1, CHECK_EXPECTED_REVS, BISECT_RESET, BISECT_WRITE, @@ -874,8 +872,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) } cmdmode = 0; int 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, "check-expected-revs", &cmdmode, @@ -912,9 +908,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); - break; case WRITE_TERMS: if (argc != 2) return error(_("--write-terms requires two arguments")); -- cgit v1.2.3 From 27257bc4661ed7ffb715922693c7a2bee136824c Mon Sep 17 00:00:00 2001 From: Pranit Bauva Date: Thu, 15 Oct 2020 15:38:35 +0200 Subject: bisect--helper: reimplement `bisect_state` & `bisect_head` shell functions in C Reimplement the `bisect_state()` shell functions in C and also add a subcommand `--bisect-state` to `git-bisect--helper` to call them from git-bisect.sh . Using `--bisect-state` subcommand is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired and will be called by some other methods. `bisect_head()` is only called from `bisect_state()`, thus it is not required to introduce another subcommand. Note that the `eval` in the changed line of `git-bisect.sh` cannot be dropped: it is necessary because the `rev` and the `tail` variables may contain multiple, quoted arguments that need to be passed to `bisect--helper` (without the quotes, naturally). Mentored-by: Lars Schneider Mentored-by: Christian Couder Mentored-by: Johannes Schindelin Signed-off-by: Pranit Bauva Signed-off-by: Tanushree Tumane Signed-off-by: Miriam Rubio Reviewed-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/bisect--helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 868bdb2c8b..afaf8efbb7 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -31,6 +31,8 @@ static const char * const git_bisect_helper_usage[] = { N_("git bisect--helper --bisect-next"), N_("git bisect--helper --bisect-auto-next"), N_("git bisect--helper --bisect-autostart"), + N_("git bisect--helper --bisect-state (bad|new) []"), + N_("git bisect--helper --bisect-state (good|old) [...]"), NULL }; @@ -855,6 +857,80 @@ static int bisect_autostart(struct bisect_terms *terms) return res; } +static enum bisect_error bisect_state(struct bisect_terms *terms, const char **argv, + int argc) +{ + const char *state; + int i, verify_expected = 1; + struct object_id oid, expected; + struct strbuf buf = STRBUF_INIT; + struct oid_array revs = OID_ARRAY_INIT; + + if (!argc) + return error(_("Please call `--bisect-state` with at least one argument")); + + if (bisect_autostart(terms)) + return BISECT_FAILED; + + 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 (argc > 1 && !strcmp(state, terms->term_bad)) + return error(_("'git bisect %s' can take only one argument."), terms->term_bad); + + if (argc == 0) { + const char *head = "BISECT_HEAD"; + enum get_oid_result res_head = get_oid(head, &oid); + + if (res_head == MISSING_OBJECT) { + head = "HEAD"; + res_head = get_oid(head, &oid); + } + + if (res_head) + error(_("Bad rev input: %s"), head); + oid_array_append(&revs, &oid); + } + + /* + * All input revs must be checked before executing bisect_write() + * to discard junk revs. + */ + + for (; argc; argc--, argv++) { + if (get_oid(*argv, &oid)){ + error(_("Bad rev input: %s"), *argv); + oid_array_clear(&revs); + return BISECT_FAILED; + } + oid_array_append(&revs, &oid); + } + + if (strbuf_read_file(&buf, git_path_bisect_expected_rev(), 0) < the_hash_algo->hexsz || + get_oid_hex(buf.buf, &expected) < 0) + verify_expected = 0; /* Ignore invalid file contents */ + strbuf_release(&buf); + + for (i = 0; i < revs.nr; i++) { + if (bisect_write(state, oid_to_hex(&revs.oid[i]), terms, 0)) { + oid_array_clear(&revs); + return BISECT_FAILED; + } + if (verify_expected && !oideq(&revs.oid[i], &expected)) { + unlink_or_warn(git_path_bisect_ancestors_ok()); + unlink_or_warn(git_path_bisect_expected_rev()); + verify_expected = 0; + } + } + + oid_array_clear(&revs); + return bisect_auto_next(terms, NULL); +} + int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { @@ -868,7 +944,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) BISECT_START, BISECT_AUTOSTART, BISECT_NEXT, - BISECT_AUTO_NEXT + BISECT_AUTO_NEXT, + BISECT_STATE } cmdmode = 0; int res = 0, nolog = 0; struct option options[] = { @@ -894,6 +971,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT), OPT_CMDMODE(0, "bisect-autostart", &cmdmode, N_("start the bisection if it has not yet been started"), BISECT_AUTOSTART), + OPT_CMDMODE(0, "bisect-state", &cmdmode, + N_("mark the state of ref (or refs)"), BISECT_STATE), OPT_BOOL(0, "no-log", &nolog, N_("no log for BISECT_WRITE")), OPT_END() @@ -964,6 +1043,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) set_terms(&terms, "bad", "good"); res = bisect_autostart(&terms); break; + case BISECT_STATE: + set_terms(&terms, "bad", "good"); + get_terms(&terms); + res = bisect_state(&terms, argv, argc); + break; default: BUG("unknown subcommand %d", cmdmode); } -- cgit v1.2.3 From 9b437b056d9b4c8c99fb1e9dfa0ad06072e2ab0f Mon Sep 17 00:00:00 2001 From: Pranit Bauva Date: Thu, 15 Oct 2020 15:38:36 +0200 Subject: bisect--helper: retire `--check-expected-revs` subcommand The `--check-expected-revs` subcommand is no longer used from the git-bisect.sh shell script. Functions `check_expected_revs` and `is_expected_revs` are also deleted. Mentored-by: Lars Schneider Mentored-by: Christian Couder Mentored-by: Johannes Schindelin Signed-off-by: Pranit Bauva Signed-off-by: Tanushree Tumane Signed-off-by: Miriam Rubio Reviewed-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/bisect--helper.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'builtin') diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index afaf8efbb7..cae9b16366 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -187,30 +187,6 @@ static int write_terms(const char *bad, const char *good) return res; } -static int is_expected_rev(const char *expected_hex) -{ - struct strbuf actual_hex = STRBUF_INIT; - int res = 0; - if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) { - strbuf_trim(&actual_hex); - res = !strcmp(actual_hex.buf, expected_hex); - } - strbuf_release(&actual_hex); - return res; -} - -static void check_expected_revs(const char **revs, int rev_nr) -{ - int i; - - for (i = 0; i < rev_nr; i++) { - if (!is_expected_rev(revs[i])) { - unlink_or_warn(git_path_bisect_ancestors_ok()); - unlink_or_warn(git_path_bisect_expected_rev()); - } - } -} - static int bisect_reset(const char *commit) { struct strbuf branch = STRBUF_INIT; @@ -935,7 +911,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { WRITE_TERMS = 1, - CHECK_EXPECTED_REVS, BISECT_RESET, BISECT_WRITE, CHECK_AND_SET_TERMS, @@ -951,8 +926,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) struct option options[] = { OPT_CMDMODE(0, "write-terms", &cmdmode, N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS), - 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, @@ -991,9 +964,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) if (argc != 2) return error(_("--write-terms requires two arguments")); return write_terms(argv[0], argv[1]); - 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")); -- cgit v1.2.3 From 5c517fe345baa6bc7d0ecc31dd60c299dc6648ce Mon Sep 17 00:00:00 2001 From: Pranit Bauva Date: Thu, 15 Oct 2020 15:38:37 +0200 Subject: bisect--helper: retire `--write-terms` subcommand The `--write-terms` subcommand is no longer used from the git-bisect.sh shell script. Instead the function `write_terms()` is called from the C implementation of `set_terms()` and `bisect_start()`. Mentored-by: Lars Schneider Mentored-by: Christian Couder Mentored-by: Johannes Schindelin Signed-off-by: Pranit Bauva Signed-off-by: Tanushree Tumane Signed-off-by: Miriam Rubio Reviewed-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/bisect--helper.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'builtin') diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index cae9b16366..b6087a8a21 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -20,7 +20,6 @@ static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT") static const char * const git_bisect_helper_usage[] = { - N_("git bisect--helper --write-terms "), N_("git bisect--helper --bisect-reset []"), N_("git bisect--helper --bisect-write [--no-log] "), N_("git bisect--helper --bisect-check-and-set-terms "), @@ -910,8 +909,7 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, const char **a int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { - WRITE_TERMS = 1, - BISECT_RESET, + BISECT_RESET = 1, BISECT_WRITE, CHECK_AND_SET_TERMS, BISECT_NEXT_CHECK, @@ -924,8 +922,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) } cmdmode = 0; int res = 0, nolog = 0; struct option options[] = { - OPT_CMDMODE(0, "write-terms", &cmdmode, - N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS), OPT_CMDMODE(0, "bisect-reset", &cmdmode, N_("reset the bisection state"), BISECT_RESET), OPT_CMDMODE(0, "bisect-write", &cmdmode, @@ -960,10 +956,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) usage_with_options(git_bisect_helper_usage, options); switch (cmdmode) { - case WRITE_TERMS: - if (argc != 2) - return error(_("--write-terms requires two arguments")); - return write_terms(argv[0], argv[1]); case BISECT_RESET: if (argc > 1) return error(_("--bisect-reset requires either no argument or a commit")); -- cgit v1.2.3 From b0f6494f70fd72141581ae2d392d9d793be08b81 Mon Sep 17 00:00:00 2001 From: Pranit Bauva Date: Thu, 15 Oct 2020 15:38:38 +0200 Subject: bisect--helper: retire `--bisect-autostart` subcommand The `--bisect-autostart` subcommand is no longer used from the git-bisect.sh shell script. Instead the function `bisect_autostart()` is directly called from the C implementation. Mentored-by: Lars Schneider Mentored-by: Christian Couder Mentored-by: Johannes Schindelin Signed-off-by: Pranit Bauva Signed-off-by: Tanushree Tumane Signed-off-by: Miriam Rubio Reviewed-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/bisect--helper.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'builtin') diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index b6087a8a21..fc6ca257a4 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -29,7 +29,6 @@ static const char * const git_bisect_helper_usage[] = { " [--no-checkout] [--first-parent] [ [...]] [--] [...]"), N_("git bisect--helper --bisect-next"), N_("git bisect--helper --bisect-auto-next"), - N_("git bisect--helper --bisect-autostart"), N_("git bisect--helper --bisect-state (bad|new) []"), N_("git bisect--helper --bisect-state (good|old) [...]"), NULL @@ -938,8 +937,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) 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-autostart", &cmdmode, - N_("start the bisection if it has not yet been started"), BISECT_AUTOSTART), OPT_CMDMODE(0, "bisect-state", &cmdmode, N_("mark the state of ref (or refs)"), BISECT_STATE), OPT_BOOL(0, "no-log", &nolog, @@ -999,12 +996,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) get_terms(&terms); res = bisect_auto_next(&terms, prefix); break; - case BISECT_AUTOSTART: - if (argc) - return error(_("--bisect-autostart does not accept arguments")); - set_terms(&terms, "bad", "good"); - res = bisect_autostart(&terms); - break; case BISECT_STATE: set_terms(&terms, "bad", "good"); get_terms(&terms); -- cgit v1.2.3