commit-reach(repo_get_merge_bases): pass on "missing commits" errors

The `merge_bases_many()` function was just taught to indicate parsing errors, and now the `repo_get_merge_bases()` function (which is also surfaced via the `repo_get_merge_bases()` macro) is aware of that, too. Naturally, there are a lot of callers that need to be adjusted now, too. Next step: adjust the callers of `get_octopus_merge_bases()`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Feb 28, 2024 at 09:44 UTC 76e2a0999907644966dfe48b573d6e57e2f1e275
17 files changed +96 -51
builtin/log.c
+5 -5
@@ -1704,11 +1704,11 @@ static struct commit *get_base_commit(const char *base_commit,
1704 */
1705 while (rev_nr > 1) {
1706 for (i = 0; i < rev_nr / 2; i++) {
1707 - struct commit_list *merge_base;
1708 - merge_base = repo_get_merge_bases(the_repository,
1709 - rev[2 * i],
1710 - rev[2 * i + 1]);
1711 - if (!merge_base || merge_base->next) {
1707 + struct commit_list *merge_base = NULL;
1708 + if (repo_get_merge_bases(the_repository,
1709 + rev[2 * i],
1710 + rev[2 * i + 1], &merge_base) < 0 ||
1711 + !merge_base || merge_base->next) {
1712 if (die_on_failure) {
1713 die(_("failed to find exact merge base"));
1714 } else {
builtin/merge-tree.c
+3 -2
@@ -462,8 +462,9 @@ static int real_merge(struct merge_tree_options *o,
462 * Get the merge bases, in reverse order; see comment above
463 * merge_incore_recursive in merge-ort.h
464 */
465 - merge_bases = repo_get_merge_bases(the_repository, parent1,
466 - parent2);
465 + if (repo_get_merge_bases(the_repository, parent1,
466 + parent2, &merge_bases) < 0)
467 + exit(128);
468 if (!merge_bases && !o->allow_unrelated_histories)
469 die(_("refusing to merge unrelated histories"));
470 merge_bases = reverse_commit_list(merge_bases);
builtin/merge.c
+12 -8
@@ -1514,10 +1514,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1514
1515 if (!remoteheads)
1516 ; /* already up-to-date */
1517 - else if (!remoteheads->next)
1518 - common = repo_get_merge_bases(the_repository, head_commit,
1519 - remoteheads->item);
1520 - else {
1517 + else if (!remoteheads->next) {
1518 + if (repo_get_merge_bases(the_repository, head_commit,
1519 + remoteheads->item, &common) < 0) {
1520 + ret = 2;
1521 + goto done;
1522 + }
1523 + } else {
1524 struct commit_list *list = remoteheads;
1525 commit_list_insert(head_commit, &list);
1526 common = get_octopus_merge_bases(list);
@@ -1627,7 +1630,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1630 struct commit_list *j;
1631
1632 for (j = remoteheads; j; j = j->next) {
1630 - struct commit_list *common_one;
1633 + struct commit_list *common_one = NULL;
1634 struct commit *common_item;
1635
1636 /*
@@ -1635,9 +1638,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1638 * merge_bases again, otherwise "git merge HEAD^
1639 * HEAD^^" would be missed.
1640 */
1638 - common_one = repo_get_merge_bases(the_repository,
1639 - head_commit,
1640 - j->item);
1641 + if (repo_get_merge_bases(the_repository, head_commit,
1642 + j->item, &common_one) < 0)
1643 + exit(128);
1644 +
1645 common_item = common_one->item;
1646 free_commit_list(common_one);
1647 if (!oideq(&common_item->object.oid, &j->item->object.oid)) {
builtin/rebase.c
+5 -3
@@ -867,7 +867,8 @@ static int can_fast_forward(struct commit *onto, struct commit *upstream,
867 if (!upstream)
868 goto done;
869
870 - merge_bases = repo_get_merge_bases(the_repository, upstream, head);
870 + if (repo_get_merge_bases(the_repository, upstream, head, &merge_bases) < 0)
871 + exit(128);
872 if (!merge_bases || merge_bases->next)
873 goto done;
874
@@ -886,8 +887,9 @@ static void fill_branch_base(struct rebase_options *options,
887 {
888 struct commit_list *merge_bases = NULL;
889
889 - merge_bases = repo_get_merge_bases(the_repository, options->onto,
890 - options->orig_head);
890 + if (repo_get_merge_bases(the_repository, options->onto,
891 + options->orig_head, &merge_bases) < 0)
892 + exit(128);
893 if (!merge_bases || merge_bases->next)
894 oidcpy(branch_base, null_oid());
895 else
builtin/rev-parse.c
+3 -2
@@ -297,7 +297,7 @@ static int try_difference(const char *arg)
297 show_rev(NORMAL, &end_oid, end);
298 show_rev(symmetric ? NORMAL : REVERSED, &start_oid, start);
299 if (symmetric) {
300 - struct commit_list *exclude;
300 + struct commit_list *exclude = NULL;
301 struct commit *a, *b;
302 a = lookup_commit_reference(the_repository, &start_oid);
303 b = lookup_commit_reference(the_repository, &end_oid);
@@ -305,7 +305,8 @@ static int try_difference(const char *arg)
305 *dotdot = '.';
306 return 0;
307 }
308 - exclude = repo_get_merge_bases(the_repository, a, b);
308 + if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0)
309 + exit(128);
310 while (exclude) {
311 struct commit *commit = pop_commit(&exclude);
312 show_rev(REVERSED, &commit->object.oid, NULL);
commit-reach.c
+11 -12
@@ -188,9 +188,12 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in)
188 struct commit_list *new_commits = NULL, *end = NULL;
189
190 for (j = ret; j; j = j->next) {
191 - struct commit_list *bases;
192 - bases = repo_get_merge_bases(the_repository, i->item,
193 - j->item);
191 + struct commit_list *bases = NULL;
192 + if (repo_get_merge_bases(the_repository, i->item,
193 + j->item, &bases) < 0) {
194 + free_commit_list(bases);
195 + return NULL;
196 + }
197 if (!new_commits)
198 new_commits = bases;
199 else
@@ -482,16 +485,12 @@ struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
485 return result;
486 }
487
485 -struct commit_list *repo_get_merge_bases(struct repository *r,
486 - struct commit *one,
487 - struct commit *two)
488 +int repo_get_merge_bases(struct repository *r,
489 + struct commit *one,
490 + struct commit *two,
491 + struct commit_list **result)
492 {
489 - struct commit_list *result = NULL;
490 - if (get_merge_bases_many_0(r, one, 1, &two, 1, &result) < 0) {
491 - free_commit_list(result);
492 - return NULL;
493 - }
494 - return result;
493 + return get_merge_bases_many_0(r, one, 1, &two, 1, result);
494 }
495
496 /*
commit-reach.h
+4 -3
@@ -9,9 +9,10 @@ struct ref_filter;
9 struct object_id;
10 struct object_array;
11
12 -struct commit_list *repo_get_merge_bases(struct repository *r,
13 - struct commit *rev1,
14 - struct commit *rev2);
12 +int repo_get_merge_bases(struct repository *r,
13 + struct commit *rev1,
14 + struct commit *rev2,
15 + struct commit_list **result);
16 struct commit_list *repo_get_merge_bases_many(struct repository *r,
17 struct commit *one, int n,
18 struct commit **twos);
diff-lib.c
+3 -2
@@ -570,7 +570,7 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
570 {
571 int i;
572 struct commit *mb_child[2] = {0};
573 - struct commit_list *merge_bases;
573 + struct commit_list *merge_bases = NULL;
574
575 for (i = 0; i < revs->pending.nr; i++) {
576 struct object *obj = revs->pending.objects[i].item;
@@ -597,7 +597,8 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
597 mb_child[1] = lookup_commit_reference(the_repository, &oid);
598 }
599
600 - merge_bases = repo_get_merge_bases(the_repository, mb_child[0], mb_child[1]);
600 + if (repo_get_merge_bases(the_repository, mb_child[0], mb_child[1], &merge_bases) < 0)
601 + exit(128);
602 if (!merge_bases)
603 die(_("no merge base found"));
604 if (merge_bases->next)
log-tree.c
+3 -2
@@ -1011,7 +1011,7 @@ static int do_remerge_diff(struct rev_info *opt,
1011 struct object_id *oid)
1012 {
1013 struct merge_options o;
1014 - struct commit_list *bases;
1014 + struct commit_list *bases = NULL;
1015 struct merge_result res = {0};
1016 struct pretty_print_context ctx = {0};
1017 struct commit *parent1 = parents->item;
@@ -1036,7 +1036,8 @@ static int do_remerge_diff(struct rev_info *opt,
1036 /* Parse the relevant commits and get the merge bases */
1037 parse_commit_or_die(parent1);
1038 parse_commit_or_die(parent2);
1039 - bases = repo_get_merge_bases(the_repository, parent1, parent2);
1039 + if (repo_get_merge_bases(the_repository, parent1, parent2, &bases) < 0)
1040 + exit(128);
1041
1042 /* Re-merge the parents */
1043 merge_incore_recursive(&o, bases, parent1, parent2, &res);
merge-ort.c
+5 -1
@@ -5068,7 +5068,11 @@ static void merge_ort_internal(struct merge_options *opt,
5068 struct strbuf merge_base_abbrev = STRBUF_INIT;
5069
5070 if (!merge_bases) {
5071 - merge_bases = repo_get_merge_bases(the_repository, h1, h2);
5071 + if (repo_get_merge_bases(the_repository, h1, h2,
5072 + &merge_bases) < 0) {
5073 + result->clean = -1;
5074 + return;
5075 + }
5076 /* See merge-ort.h:merge_incore_recursive() declaration NOTE */
5077 merge_bases = reverse_commit_list(merge_bases);
5078 }
merge-recursive.c
+3 -1
@@ -3633,7 +3633,9 @@ static int merge_recursive_internal(struct merge_options *opt,
3633 }
3634
3635 if (!merge_bases) {
3636 - merge_bases = repo_get_merge_bases(the_repository, h1, h2);
3636 + if (repo_get_merge_bases(the_repository, h1, h2,
3637 + &merge_bases) < 0)
3638 + return -1;
3639 merge_bases = reverse_commit_list(merge_bases);
3640 }
3641
notes-merge.c
+2 -1
@@ -607,7 +607,8 @@ int notes_merge(struct notes_merge_options *o,
607 assert(local && remote);
608
609 /* Find merge bases */
610 - bases = repo_get_merge_bases(the_repository, local, remote);
610 + if (repo_get_merge_bases(the_repository, local, remote, &bases) < 0)
611 + exit(128);
612 if (!bases) {
613 base_oid = null_oid();
614 base_tree_oid = the_hash_algo->empty_tree;
object-name.c
+5 -2
@@ -1479,7 +1479,7 @@ int repo_get_oid_mb(struct repository *r,
1479 struct object_id *oid)
1480 {
1481 struct commit *one, *two;
1482 - struct commit_list *mbs;
1482 + struct commit_list *mbs = NULL;
1483 struct object_id oid_tmp;
1484 const char *dots;
1485 int st;
@@ -1507,7 +1507,10 @@ int repo_get_oid_mb(struct repository *r,
1507 two = lookup_commit_reference_gently(r, &oid_tmp, 0);
1508 if (!two)
1509 return -1;
1510 - mbs = repo_get_merge_bases(r, one, two);
1510 + if (repo_get_merge_bases(r, one, two, &mbs) < 0) {
1511 + free_commit_list(mbs);
1512 + return -1;
1513 + }
1514 if (!mbs || mbs->next)
1515 st = -1;
1516 else {
revision.c
+8 -4
@@ -1963,7 +1963,7 @@ static void add_pending_commit_list(struct rev_info *revs,
1963
1964 static void prepare_show_merge(struct rev_info *revs)
1965 {
1966 - struct commit_list *bases;
1966 + struct commit_list *bases = NULL;
1967 struct commit *head, *other;
1968 struct object_id oid;
1969 const char **prune = NULL;
@@ -1978,7 +1978,8 @@ static void prepare_show_merge(struct rev_info *revs)
1978 other = lookup_commit_or_die(&oid, "MERGE_HEAD");
1979 add_pending_object(revs, &head->object, "HEAD");
1980 add_pending_object(revs, &other->object, "MERGE_HEAD");
1981 - bases = repo_get_merge_bases(the_repository, head, other);
1981 + if (repo_get_merge_bases(the_repository, head, other, &bases) < 0)
1982 + exit(128);
1983 add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
1984 add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
1985 free_commit_list(bases);
@@ -2066,14 +2067,17 @@ static int handle_dotdot_1(const char *arg, char *dotdot,
2067 } else {
2068 /* A...B -- find merge bases between the two */
2069 struct commit *a, *b;
2069 - struct commit_list *exclude;
2070 + struct commit_list *exclude = NULL;
2071
2072 a = lookup_commit_reference(revs->repo, &a_obj->oid);
2073 b = lookup_commit_reference(revs->repo, &b_obj->oid);
2074 if (!a || !b)
2075 return dotdot_missing(arg, dotdot, revs, symmetric);
2076
2076 - exclude = repo_get_merge_bases(the_repository, a, b);
2077 + if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0) {
2078 + free_commit_list(exclude);
2079 + return -1;
2080 + }
2081 add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE,
2082 flags_exclude);
2083 add_pending_commit_list(revs, exclude, flags_exclude);
sequencer.c
+6 -2
@@ -3908,7 +3908,7 @@ static int do_merge(struct repository *r,
3908 int run_commit_flags = 0;
3909 struct strbuf ref_name = STRBUF_INIT;
3910 struct commit *head_commit, *merge_commit, *i;
3911 - struct commit_list *bases, *j;
3911 + struct commit_list *bases = NULL, *j;
3912 struct commit_list *to_merge = NULL, **tail = &to_merge;
3913 const char *strategy = !opts->xopts.nr &&
3914 (!opts->strategy ||
@@ -4134,7 +4134,11 @@ static int do_merge(struct repository *r,
4134 }
4135
4136 merge_commit = to_merge->item;
4137 - bases = repo_get_merge_bases(r, head_commit, merge_commit);
4137 + if (repo_get_merge_bases(r, head_commit, merge_commit, &bases) < 0) {
4138 + ret = -1;
4139 + goto leave_merge;
4140 + }
4141 +
4142 if (bases && oideq(&merge_commit->object.oid,
4143 &bases->item->object.oid)) {
4144 ret = 0;
submodule.c
+6 -1
@@ -592,7 +592,12 @@ static void show_submodule_header(struct diff_options *o,
592 (!is_null_oid(two) && !*right))
593 message = "(commits not present)";
594
595 - *merge_bases = repo_get_merge_bases(sub, *left, *right);
595 + *merge_bases = NULL;
596 + if (repo_get_merge_bases(sub, *left, *right, merge_bases) < 0) {
597 + message = "(corrupt repository)";
598 + goto output_header;
599 + }
600 +
601 if (*merge_bases) {
602 if ((*merge_bases)->item == *left)
603 fast_forward = 1;
t/t4301-merge-tree-write-tree.sh
+12
@@ -945,4 +945,16 @@ test_expect_success 'check the input format when --stdin is passed' '
945 test_cmp expect actual
946 '
947
948 +test_expect_success 'error out on missing commits as well' '
949 + git init --bare missing-commit.git &&
950 + git rev-list --objects side1 side3 >list-including-initial &&
951 + grep -v ^$(git rev-parse side1^) <list-including-initial >list &&
952 + git pack-objects missing-commit.git/objects/pack/missing-initial <list &&
953 + side1=$(git rev-parse side1) &&
954 + side3=$(git rev-parse side3) &&
955 + test_must_fail git --git-dir=missing-commit.git \
956 + merge-tree --allow-unrelated-histories $side1 $side3 >actual &&
957 + test_must_be_empty actual
958 +'
959 +
960 test_done