/* * "check_merge_bases" checks that merge bases are not "bad" (or "new"). * * - If one is "bad" (or "new"), it means the user assumed something wrong * and we must exit with a non 0 error code. * - If one is "good" (or "old"), that's good, we have nothing to do. * - 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) { 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); for (; result; result = result->next) { const unsigned char *mb = result->item->object.sha1; if (!hashcmp(mb, current_bad_oid->hash)) { handle_bad_merge_base(); } else if (0 <= sha1_array_lookup(&good_revs, mb)) { continue; } else if (0 <= sha1_array_lookup(&skipped_revs, mb)) { handle_skipped_merge_base(mb); } else { printf("Bisecting: a merge base must be tested\n"); exit(bisect_checkout(mb, no_checkout)); } } free(rev); free_commit_list(result); }
int main(int argc, char **argv) { struct sha1_array array = SHA1_ARRAY_INIT; struct strbuf line = STRBUF_INIT; while (strbuf_getline_lf(&line, stdin) != EOF) { const char *arg; unsigned char sha1[20]; if (skip_prefix(line.buf, "append ", &arg)) { if (get_sha1_hex(arg, sha1)) die("not a hexadecimal SHA1: %s", arg); sha1_array_append(&array, sha1); } else if (skip_prefix(line.buf, "lookup ", &arg)) { if (get_sha1_hex(arg, sha1)) die("not a hexadecimal SHA1: %s", arg); printf("%d\n", sha1_array_lookup(&array, sha1)); } else if (!strcmp(line.buf, "clear")) sha1_array_clear(&array); else if (!strcmp(line.buf, "for_each_unique")) sha1_array_for_each_unique(&array, print_sha1, NULL); else die("unknown command: %s", line.buf); } return 0; }
static int report(struct fsck_options *options, struct object *object, enum fsck_msg_id id, const char *fmt, ...) { va_list ap; struct strbuf sb = STRBUF_INIT; int msg_type = fsck_msg_type(id, options), result; if (msg_type == FSCK_IGNORE) return 0; if (options->skiplist && object && sha1_array_lookup(options->skiplist, object->oid.hash) >= 0) return 0; if (msg_type == FSCK_FATAL) msg_type = FSCK_ERROR; else if (msg_type == FSCK_INFO) msg_type = FSCK_WARN; append_msg_id(&sb, msg_id_info[id].id_string); va_start(ap, fmt); strbuf_vaddf(&sb, fmt, ap); result = options->error_func(object, msg_type, sb.buf); strbuf_release(&sb); va_end(ap); return result; }
/* * In this function, passing a not NULL skipped_first is very special. * It means that we want to know if the first commit in the list is * skipped because we will want to test a commit away from it if it is * indeed skipped. * So if the first commit is skipped, we cannot take the shortcut to * just "return list" when we find the first non skipped commit, we * have to return a fully filtered list. * * We use (*skipped_first == -1) to mean "it has been found that the * first commit is not skipped". In this case *skipped_first is set back * to 0 just before the function returns. */ struct commit_list *filter_skipped(struct commit_list *list, struct commit_list **tried, int show_all, int *count, int *skipped_first) { struct commit_list *filtered = NULL, **f = &filtered; *tried = NULL; if (skipped_first) *skipped_first = 0; if (count) *count = 0; if (!skipped_revs.nr) return list; while (list) { struct commit_list *next = list->next; list->next = NULL; if (0 <= sha1_array_lookup(&skipped_revs, list->item->object.sha1)) { if (skipped_first && !*skipped_first) *skipped_first = 1; /* Move current to tried list */ *tried = list; tried = &list->next; } else { if (!show_all) { if (!skipped_first || !*skipped_first) return list; } else if (skipped_first && !*skipped_first) { /* This means we know it's not skipped */ *skipped_first = -1; } /* Move current to filtered list */ *f = list; f = &list->next; if (count) (*count)++; } list = next; } if (skipped_first && *skipped_first == -1) *skipped_first = 0; return filtered; }