completion: use __gitcomp_builtin in _git_fsck
[gitweb.git] / bisect.c
index 87e4dee16d712bdb85a7133d00f87cd421945d08..f6d05bd66f42bd9874a08f5585ae99337d22dad5 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -132,7 +132,7 @@ static void show_list(const char *debug, int counted, int nr,
                unsigned flags = commit->object.flags;
                enum object_type type;
                unsigned long size;
-               char *buf = read_sha1_file(commit->object.sha1, &type, &size);
+               char *buf = read_sha1_file(commit->object.oid.hash, &type, &size);
                const char *subject_start;
                int subject_len;
 
@@ -144,10 +144,10 @@ static void show_list(const char *debug, int counted, int nr,
                        fprintf(stderr, "%3d", weight(p));
                else
                        fprintf(stderr, "---");
-               fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
+               fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.oid.hash));
                for (pp = commit->parents; pp; pp = pp->next)
                        fprintf(stderr, " %.*s", 8,
-                               sha1_to_hex(pp->item->object.sha1));
+                               sha1_to_hex(pp->item->object.oid.hash));
 
                subject_len = find_commit_subject(buf, &subject_start);
                if (subject_len)
@@ -441,7 +441,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_head_name, "head-name")
 
 static void read_bisect_paths(struct argv_array *array)
 {
@@ -693,11 +698,12 @@ static int bisect_checkout(const struct object_id *bisect_rev, int no_checkout)
        char bisect_rev_hex[GIT_MAX_HEXSZ + 1];
 
        memcpy(bisect_rev_hex, oid_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);
-       update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev->hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+       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->hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+               update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0,
+                          UPDATE_REFS_DIE_ON_ERR);
        } else {
                int res;
                res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
@@ -786,11 +792,9 @@ static void handle_skipped_merge_base(const struct object_id *mb)
  * - If one is "skipped", we can't know but we should warn.
  * - If we don't know, we should check it out and ask the user to test.
  */
-static void check_merge_bases(int no_checkout)
+static void check_merge_bases(int rev_nr, struct commit **rev, int no_checkout)
 {
        struct commit_list *result;
-       int rev_nr;
-       struct commit **rev = get_bad_and_good_commits(&rev_nr);
 
        result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1);
 
@@ -808,34 +812,21 @@ static void check_merge_bases(int no_checkout)
                }
        }
 
-       free(rev);
        free_commit_list(result);
 }
 
-static int check_ancestors(const char *prefix)
+static int check_ancestors(int rev_nr, struct commit **rev, const char *prefix)
 {
        struct rev_info revs;
-       struct object_array pending_copy;
        int res;
 
        bisect_rev_setup(&revs, prefix, "^%s", "%s", 0);
 
-       /* Save pending objects, so they can be cleaned up later. */
-       pending_copy = revs.pending;
-       revs.leak_pending = 1;
-
-       /*
-        * bisect_common calls prepare_revision_walk right away, which
-        * (together with .leak_pending = 1) makes us the sole owner of
-        * the list of pending objects.
-        */
        bisect_common(&revs);
        res = (revs.commits != NULL);
 
        /* Clean up objects used, as they will be reused. */
-       clear_commit_marks_for_object_array(&pending_copy, ALL_REV_FLAGS);
-
-       object_array_clear(&pending_copy);
+       clear_commit_marks_many(rev_nr, rev, ALL_REV_FLAGS);
 
        return res;
 }
@@ -852,7 +843,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
 {
        char *filename = git_pathdup("BISECT_ANCESTORS_OK");
        struct stat st;
-       int fd;
+       int fd, rev_nr;
+       struct commit **rev;
 
        if (!current_bad_oid)
                die(_("a %s revision is needed"), term_bad);
@@ -866,8 +858,10 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
                goto done;
 
        /* Check if all good revs are ancestor of the bad rev. */
-       if (check_ancestors(prefix))
-               check_merge_bases(no_checkout);
+       rev = get_bad_and_good_commits(&rev_nr);
+       if (check_ancestors(rev_nr, rev, prefix))
+               check_merge_bases(rev_nr, rev, no_checkout);
+       free(rev);
 
        /* Create file BISECT_ANCESTORS_OK. */
        fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
@@ -1051,3 +1045,40 @@ 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)
+{
+       struct string_list *refs = cb_data;
+       char *ref = xstrfmt("refs/bisect%s", refname);
+       string_list_append(refs, ref);
+       return 0;
+}
+
+int bisect_clean_state(void)
+{
+       int result = 0;
+
+       /* There may be some refs packed during bisection */
+       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"));
+       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());
+       /* 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.
+        */
+       unlink_or_warn(git_path_bisect_start());
+
+       return result;
+}