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

The `paint_down_to_common()` function was just taught to indicate parsing errors, and now the `merge_bases_many()` function is aware of that, too. One tricky aspect is that `merge_bases_many()` parses commits of its own, but wants to gracefully handle the scenario where NULL is passed as a merge head, returning the empty list of merge bases. The way this was handled involved calling `repo_parse_commit(NULL)` and relying on it to return an error. This has to be done differently now so that we can handle missing commits correctly by producing a fatal error. Next step: adjust the caller of `merge_bases_many()`: `get_merge_bases_many_0()`. 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 fb02c523a317937a4080315c2d8f8151730b87be
1 file changed +22 -13
commit-reach.c
+22 -13
@@ -130,41 +130,49 @@ static int paint_down_to_common(struct repository *r,
130 return 0;
131 }
132
133 -static struct commit_list *merge_bases_many(struct repository *r,
134 - struct commit *one, int n,
135 - struct commit **twos)
133 +static int merge_bases_many(struct repository *r,
134 + struct commit *one, int n,
135 + struct commit **twos,
136 + struct commit_list **result)
137 {
138 struct commit_list *list = NULL;
138 - struct commit_list *result = NULL;
139 int i;
140
141 for (i = 0; i < n; i++) {
142 - if (one == twos[i])
142 + if (one == twos[i]) {
143 /*
144 * We do not mark this even with RESULT so we do not
145 * have to clean it up.
146 */
147 - return commit_list_insert(one, &result);
147 + *result = commit_list_insert(one, result);
148 + return 0;
149 + }
150 }
151
152 + if (!one)
153 + return 0;
154 if (repo_parse_commit(r, one))
151 - return NULL;
155 + return error(_("could not parse commit %s"),
156 + oid_to_hex(&one->object.oid));
157 for (i = 0; i < n; i++) {
158 + if (!twos[i])
159 + return 0;
160 if (repo_parse_commit(r, twos[i]))
154 - return NULL;
161 + return error(_("could not parse commit %s"),
162 + oid_to_hex(&twos[i]->object.oid));
163 }
164
165 if (paint_down_to_common(r, one, n, twos, 0, 0, &list)) {
166 free_commit_list(list);
159 - return NULL;
167 + return -1;
168 }
169
170 while (list) {
171 struct commit *commit = pop_commit(&list);
172 if (!(commit->object.flags & STALE))
165 - commit_list_insert_by_date(commit, &result);
173 + commit_list_insert_by_date(commit, result);
174 }
167 - return result;
175 + return 0;
176 }
177
178 struct commit_list *get_octopus_merge_bases(struct commit_list *in)
@@ -409,10 +417,11 @@ static struct commit_list *get_merge_bases_many_0(struct repository *r,
417 {
418 struct commit_list *list;
419 struct commit **rslt;
412 - struct commit_list *result;
420 + struct commit_list *result = NULL;
421 int cnt, i;
422
415 - result = merge_bases_many(r, one, n, twos);
423 + if (merge_bases_many(r, one, n, twos, &result) < 0)
424 + return NULL;
425 for (i = 0; i < n; i++) {
426 if (one == twos[i])
427 return result;