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