diff options
Diffstat (limited to 'bisect.c')
-rw-r--r-- | bisect.c | 82 |
1 files changed, 49 insertions, 33 deletions
@@ -12,6 +12,9 @@ #include "bisect.h" #include "sha1-array.h" #include "argv-array.h" +#include "commit-slab.h" +#include "commit-reach.h" +#include "object-store.h" static struct oid_array good_revs; static struct oid_array skipped_revs; @@ -70,16 +73,19 @@ static void clear_distance(struct commit_list *list) } } +define_commit_slab(commit_weight, int *); +static struct commit_weight commit_weight; + #define DEBUG_BISECT 0 static inline int weight(struct commit_list *elem) { - return *((int*)(elem->item->util)); + return **commit_weight_at(&commit_weight, elem->item); } static inline void weight_set(struct commit_list *elem, int weight) { - *((int*)(elem->item->util)) = weight; + **commit_weight_at(&commit_weight, elem->item) = weight; } static int count_interesting_parents(struct commit *commit) @@ -116,14 +122,14 @@ static inline int halfway(struct commit_list *p, int nr) } } -#if !DEBUG_BISECT -#define show_list(a,b,c,d) do { ; } while (0) -#else static void show_list(const char *debug, int counted, int nr, struct commit_list *list) { struct commit_list *p; + if (!DEBUG_BISECT) + return; + fprintf(stderr, "%s (%d/%d)\n", debug, counted, nr); for (p = list; p; p = p->next) { @@ -141,7 +147,7 @@ static void show_list(const char *debug, int counted, int nr, (flags & TREESAME) ? ' ' : 'T', (flags & UNINTERESTING) ? 'U' : ' ', (flags & COUNTED) ? 'C' : ' '); - if (commit->util) + if (*commit_weight_at(&commit_weight, p->item)) fprintf(stderr, "%3d", weight(p)); else fprintf(stderr, "---"); @@ -156,7 +162,6 @@ static void show_list(const char *debug, int counted, int nr, fprintf(stderr, "\n"); } } -#endif /* DEBUG_BISECT */ static struct commit_list *best_bisection(struct commit_list *list, int nr) { @@ -265,7 +270,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list, struct commit *commit = p->item; unsigned flags = commit->object.flags; - p->item->util = &weights[n++]; + *commit_weight_at(&commit_weight, p->item) = &weights[n++]; switch (count_interesting_parents(commit)) { case 0: if (!(flags & TREESAME)) { @@ -372,6 +377,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches, int *weights; show_list("bisection 2 entry", 0, 0, *commit_list); + init_commit_weight(&commit_weight); /* * Count the number of total and tree-changing items on the @@ -412,6 +418,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches, } free(weights); *commit_list = best; + clear_commit_weight(&commit_weight); } static int register_ref(const char *refname, const struct object_id *oid, @@ -551,7 +558,8 @@ struct commit_list *filter_skipped(struct commit_list *list, * is increased by one between each call, but that should not matter * for this application. */ -static unsigned get_prn(unsigned count) { +static unsigned get_prn(unsigned count) +{ count = count * 1103515245 + 12345; return (count/65536) % PRN_MODULO; } @@ -589,7 +597,7 @@ static struct commit_list *skip_away(struct commit_list *list, int count) for (i = 0; cur; cur = cur->next, i++) { if (i == index) { - if (oidcmp(&cur->item->object.oid, current_bad_oid)) + if (!oideq(&cur->item->object.oid, current_bad_oid)) return cur; if (previous) return previous; @@ -619,14 +627,15 @@ static struct commit_list *managed_skipped(struct commit_list *list, return skip_away(list, count); } -static void bisect_rev_setup(struct rev_info *revs, const char *prefix, +static void bisect_rev_setup(struct repository *r, struct rev_info *revs, + const char *prefix, const char *bad_format, const char *good_format, int read_paths) { struct argv_array rev_argv = ARGV_ARRAY_INIT; int i; - init_revisions(revs, prefix); + repo_init_revisions(r, revs, prefix); revs->abbrev = 0; revs->commit_format = CMIT_FMT_UNSPECIFIED; @@ -649,7 +658,7 @@ static void bisect_common(struct rev_info *revs) if (prepare_revision_walk(revs)) die("revision walk setup failed"); if (revs->tree_objects) - mark_edges_uninteresting(revs, NULL); + mark_edges_uninteresting(revs, NULL, 0); } static void exit_if_skipped_commits(struct commit_list *tried, @@ -716,23 +725,25 @@ static int bisect_checkout(const struct object_id *bisect_rev, int no_checkout) return run_command_v_opt(argv_show_branch, RUN_GIT_CMD); } -static struct commit *get_commit_reference(const struct object_id *oid) +static struct commit *get_commit_reference(struct repository *r, + const struct object_id *oid) { - struct commit *r = lookup_commit_reference(oid); - if (!r) + struct commit *c = lookup_commit_reference(r, oid); + if (!c) die(_("Not a valid commit name %s"), oid_to_hex(oid)); - return r; + return c; } -static struct commit **get_bad_and_good_commits(int *rev_nr) +static struct commit **get_bad_and_good_commits(struct repository *r, + int *rev_nr) { struct commit **rev; int i, n = 0; ALLOC_ARRAY(rev, 1 + good_revs.nr); - rev[n++] = get_commit_reference(current_bad_oid); + rev[n++] = get_commit_reference(r, current_bad_oid); for (i = 0; i < good_revs.nr; i++) - rev[n++] = get_commit_reference(good_revs.oid + i); + rev[n++] = get_commit_reference(r, good_revs.oid + i); *rev_nr = n; return rev; @@ -801,7 +812,7 @@ static void check_merge_bases(int rev_nr, struct commit **rev, int no_checkout) for (; result; result = result->next) { const struct object_id *mb = &result->item->object.oid; - if (!oidcmp(mb, current_bad_oid)) { + if (oideq(mb, current_bad_oid)) { handle_bad_merge_base(); } else if (0 <= oid_array_lookup(&good_revs, mb)) { continue; @@ -816,12 +827,13 @@ static void check_merge_bases(int rev_nr, struct commit **rev, int no_checkout) free_commit_list(result); } -static int check_ancestors(int rev_nr, struct commit **rev, const char *prefix) +static int check_ancestors(struct repository *r, int rev_nr, + struct commit **rev, const char *prefix) { struct rev_info revs; int res; - bisect_rev_setup(&revs, prefix, "^%s", "%s", 0); + bisect_rev_setup(r, &revs, prefix, "^%s", "%s", 0); bisect_common(&revs); res = (revs.commits != NULL); @@ -840,7 +852,9 @@ static int check_ancestors(int rev_nr, struct commit **rev, const char *prefix) * If a merge base must be tested by the user, its source code will be * checked out to be tested by the user and we will exit. */ -static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) +static void check_good_are_ancestors_of_bad(struct repository *r, + const char *prefix, + int no_checkout) { char *filename = git_pathdup("BISECT_ANCESTORS_OK"); struct stat st; @@ -859,8 +873,8 @@ 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. */ - rev = get_bad_and_good_commits(&rev_nr); - if (check_ancestors(rev_nr, rev, prefix)) + rev = get_bad_and_good_commits(r, &rev_nr); + if (check_ancestors(r, rev_nr, rev, prefix)) check_merge_bases(rev_nr, rev, no_checkout); free(rev); @@ -878,12 +892,14 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) /* * This does "git diff-tree --pretty COMMIT" without one fork+exec. */ -static void show_diff_tree(const char *prefix, struct commit *commit) +static void show_diff_tree(struct repository *r, + const char *prefix, + struct commit *commit) { struct rev_info opt; /* diff-tree init */ - init_revisions(&opt, prefix); + repo_init_revisions(r, &opt, prefix); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ opt.abbrev = 0; opt.diff = 1; @@ -938,7 +954,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good) * If no_checkout is non-zero, the bisection process does not * checkout the trial commit but instead simply updates BISECT_HEAD. */ -int bisect_next_all(const char *prefix, int no_checkout) +int bisect_next_all(struct repository *r, const char *prefix, int no_checkout) { struct rev_info revs; struct commit_list *tried; @@ -950,9 +966,9 @@ int bisect_next_all(const char *prefix, int no_checkout) if (read_bisect_refs()) die(_("reading bisect refs failed")); - check_good_are_ancestors_of_bad(prefix, no_checkout); + check_good_are_ancestors_of_bad(r, prefix, no_checkout); - bisect_rev_setup(&revs, prefix, "%s", "^%s", 1); + bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1); revs.limited = 1; bisect_common(&revs); @@ -982,11 +998,11 @@ int bisect_next_all(const char *prefix, int no_checkout) bisect_rev = &revs.commits->item->object.oid; - if (!oidcmp(bisect_rev, current_bad_oid)) { + if (oideq(bisect_rev, current_bad_oid)) { exit_if_skipped_commits(tried, current_bad_oid); printf("%s is the first %s commit\n", oid_to_hex(bisect_rev), term_bad); - show_diff_tree(prefix, revs.commits->item); + show_diff_tree(r, prefix, revs.commits->item); /* This means the bisection process succeeded. */ exit(10); } |