diff options
Diffstat (limited to 'bisect.c')
-rw-r--r-- | bisect.c | 102 |
1 files changed, 50 insertions, 52 deletions
@@ -1,12 +1,14 @@ -#include "cache.h" +#include "git-compat-util.h" #include "config.h" #include "commit.h" #include "diff.h" +#include "environment.h" +#include "gettext.h" +#include "hex.h" #include "revision.h" #include "refs.h" #include "list-objects.h" #include "quote.h" -#include "hash-lookup.h" #include "run-command.h" #include "log-tree.h" #include "bisect.h" @@ -14,7 +16,9 @@ #include "strvec.h" #include "commit-slab.h" #include "commit-reach.h" -#include "object-store.h" +#include "object-name.h" +#include "object-store-ll.h" +#include "path.h" #include "dir.h" static struct oid_array good_revs; @@ -22,8 +26,6 @@ static struct oid_array skipped_revs; static struct object_id *current_bad_oid; -static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL}; - static const char *term_bad; static const char *term_good; @@ -150,11 +152,15 @@ static void show_list(const char *debug, int counted, int nr, unsigned commit_flags = commit->object.flags; enum object_type type; unsigned long size; - char *buf = read_object_file(&commit->object.oid, &type, - &size); + char *buf = repo_read_object_file(the_repository, + &commit->object.oid, &type, + &size); const char *subject_start; int subject_len; + if (!buf) + die(_("unable to read %s"), oid_to_hex(&commit->object.oid)); + fprintf(stderr, "%c%c%c ", (commit_flags & TREESAME) ? ' ' : 'T', (commit_flags & UNINTERESTING) ? 'U' : ' ', @@ -441,7 +447,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches, } static int register_ref(const char *refname, const struct object_id *oid, - int flags, void *cb_data) + int flags UNUSED, void *cb_data UNUSED) { struct strbuf good_prefix = STRBUF_INIT; strbuf_addstr(&good_prefix, term_good); @@ -467,14 +473,12 @@ static int read_bisect_refs(void) } static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") -static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV") static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK") static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN") static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START") static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG") static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS") static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT") -static GIT_PATH_FUNC(git_path_head_name, "head-name") static void read_bisect_paths(struct strvec *array) { @@ -648,11 +652,14 @@ static struct commit_list *managed_skipped(struct commit_list *list, } static void bisect_rev_setup(struct repository *r, struct rev_info *revs, + struct strvec *rev_argv, const char *prefix, const char *bad_format, const char *good_format, int read_paths) { - struct strvec rev_argv = STRVEC_INIT; + struct setup_revision_opt opt = { + .free_removed_argv_elements = 1, + }; int i; repo_init_revisions(r, revs, prefix); @@ -660,17 +667,16 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs, revs->commit_format = CMIT_FMT_UNSPECIFIED; /* rev_argv.argv[0] will be ignored by setup_revisions */ - strvec_push(&rev_argv, "bisect_rev_setup"); - strvec_pushf(&rev_argv, bad_format, oid_to_hex(current_bad_oid)); + strvec_push(rev_argv, "bisect_rev_setup"); + strvec_pushf(rev_argv, bad_format, oid_to_hex(current_bad_oid)); for (i = 0; i < good_revs.nr; i++) - strvec_pushf(&rev_argv, good_format, + strvec_pushf(rev_argv, good_format, oid_to_hex(good_revs.oid + i)); - strvec_push(&rev_argv, "--"); + strvec_push(rev_argv, "--"); if (read_paths) - read_bisect_paths(&rev_argv); + read_bisect_paths(rev_argv); - setup_revisions(rev_argv.nr, rev_argv.v, revs, NULL); - /* XXX leak rev_argv, as "revs" may still be pointing to it */ + setup_revisions(rev_argv->nr, rev_argv->v, revs, &opt); } static void bisect_common(struct rev_info *revs) @@ -702,45 +708,31 @@ static enum bisect_error error_if_skipped_commits(struct commit_list *tried, static int is_expected_rev(const struct object_id *oid) { - const char *filename = git_path_bisect_expected_rev(); - struct stat st; - struct strbuf str = STRBUF_INIT; - FILE *fp; - int res = 0; - - if (stat(filename, &st) || !S_ISREG(st.st_mode)) + struct object_id expected_oid; + if (read_ref("BISECT_EXPECTED_REV", &expected_oid)) return 0; - - fp = fopen_or_warn(filename, "r"); - if (!fp) - return 0; - - if (strbuf_getline_lf(&str, fp) != EOF) - res = !strcmp(str.buf, oid_to_hex(oid)); - - strbuf_release(&str); - fclose(fp); - - return res; + return oideq(oid, &expected_oid); } enum bisect_error bisect_checkout(const struct object_id *bisect_rev, int no_checkout) { - char bisect_rev_hex[GIT_MAX_HEXSZ + 1]; struct commit *commit; struct pretty_print_context pp = {0}; struct strbuf commit_msg = STRBUF_INIT; - oid_to_hex_r(bisect_rev_hex, bisect_rev); update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR); - argv_checkout[2] = bisect_rev_hex; if (no_checkout) { update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR); } else { - if (run_command_v_opt(argv_checkout, RUN_GIT_CMD)) + struct child_process cmd = CHILD_PROCESS_INIT; + + cmd.git_cmd = 1; + strvec_pushl(&cmd.args, "checkout", "-q", + oid_to_hex(bisect_rev), "--", NULL); + if (run_command(&cmd)) /* * Errors in `run_command()` itself, signaled by res < 0, * and errors in the child process, signaled by res > 0 @@ -750,7 +742,8 @@ enum bisect_error bisect_checkout(const struct object_id *bisect_rev, } commit = lookup_commit_reference(the_repository, bisect_rev); - format_commit_message(commit, "[%H] %s%n", &commit_msg, &pp); + repo_format_commit_message(the_repository, commit, "[%H] %s%n", + &commit_msg, &pp); fputs(commit_msg.buf, stdout); strbuf_release(&commit_msg); @@ -843,9 +836,11 @@ static void handle_skipped_merge_base(const struct object_id *mb) static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int no_checkout) { enum bisect_error res = BISECT_OK; - struct commit_list *result; + struct commit_list *result = NULL; - result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1); + if (repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1, + rev + 1, &result) < 0) + exit(128); for (; result; result = result->next) { const struct object_id *mb = &result->item->object.oid; @@ -873,10 +868,11 @@ static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int static int check_ancestors(struct repository *r, int rev_nr, struct commit **rev, const char *prefix) { + struct strvec rev_argv = STRVEC_INIT; struct rev_info revs; int res; - bisect_rev_setup(r, &revs, prefix, "^%s", "%s", 0); + bisect_rev_setup(r, &revs, &rev_argv, prefix, "^%s", "%s", 0); bisect_common(&revs); res = (revs.commits != NULL); @@ -885,6 +881,7 @@ static int check_ancestors(struct repository *r, int rev_nr, clear_commit_marks_many(rev_nr, rev, ALL_REV_FLAGS); release_revisions(&revs); + strvec_clear(&rev_argv); return res; } @@ -1010,6 +1007,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good) */ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) { + struct strvec rev_argv = STRVEC_INIT; struct rev_info revs = REV_INFO_INIT; struct commit_list *tried; int reaches = 0, all = 0, nr, steps; @@ -1037,7 +1035,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) if (res) goto cleanup; - bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1); + bisect_rev_setup(r, &revs, &rev_argv, prefix, "%s", "^%s", 1); revs.first_parent_only = !!(bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY); revs.limited = 1; @@ -1054,7 +1052,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) */ res = error_if_skipped_commits(tried, NULL); if (res < 0) - return res; + goto cleanup; printf(_("%s was both %s and %s\n"), oid_to_hex(current_bad_oid), term_good, @@ -1112,6 +1110,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) res = bisect_checkout(bisect_rev, no_checkout); cleanup: release_revisions(&revs); + strvec_clear(&rev_argv); return res; } @@ -1154,8 +1153,9 @@ int estimate_bisect_steps(int all) return (e < 3 * x) ? n : n - 1; } -static int mark_for_removal(const char *refname, const struct object_id *oid, - int flag, void *cb_data) +static int mark_for_removal(const char *refname, + const struct object_id *oid UNUSED, + int flag UNUSED, void *cb_data) { struct string_list *refs = cb_data; char *ref = xstrfmt("refs/bisect%s", refname); @@ -1171,18 +1171,16 @@ int bisect_clean_state(void) struct string_list refs_for_removal = STRING_LIST_INIT_NODUP; for_each_ref_in("refs/bisect", mark_for_removal, (void *) &refs_for_removal); string_list_append(&refs_for_removal, xstrdup("BISECT_HEAD")); + string_list_append(&refs_for_removal, xstrdup("BISECT_EXPECTED_REV")); result = delete_refs("bisect: remove", &refs_for_removal, REF_NO_DEREF); refs_for_removal.strdup_strings = 1; string_list_clear(&refs_for_removal, 0); - unlink_or_warn(git_path_bisect_expected_rev()); unlink_or_warn(git_path_bisect_ancestors_ok()); unlink_or_warn(git_path_bisect_log()); unlink_or_warn(git_path_bisect_names()); unlink_or_warn(git_path_bisect_run()); unlink_or_warn(git_path_bisect_terms()); unlink_or_warn(git_path_bisect_first_parent()); - /* Cleanup head-name if it got left by an old version of git-bisect */ - unlink_or_warn(git_path_head_name()); /* * Cleanup BISECT_START last to support the --no-checkout option * introduced in the commit 4796e823a. |