Skip to content

Commit

Permalink
commit-reach(repo_in_merge_bases_many): optionally expect missing com…
Browse files Browse the repository at this point in the history
…mits

Currently this function treats unrelated commit histories the same way
as commit histories with missing commit objects.

Typically, missing commit objects constitute a corrupt repository,
though, and should be reported as such. The next commits will make it
so, but there is one exception: In `git fetch --update-shallow` we
_expect_ commit objects to be missing, and we do want to treat the
now-incomplete commit histories as unrelated.

To allow for that, let's introduce an additional parameter that is
passed to `repo_in_merge_bases_many()` to trigger this behavior, and use
it in the two callers in `shallow.c`.

This commit changes behavior slightly: unless called from the
`shallow.c` functions that set the `ignore_missing_commits` bit, any
non-existing tip commit that is passed to `repo_in_merge_bases_many()`
will now result in an error.

Note: When encountering missing commits while traversing the commit
history in search for merge bases, with this commit there won't be a
change in behavior just yet, their children will still be interpreted as
root commits. This bug will get fixed by follow-up commits.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
dscho authored and gitster committed Feb 28, 2024
1 parent e67431d commit 207c40e
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 9 deletions.
9 changes: 5 additions & 4 deletions commit-reach.c
Expand Up @@ -466,7 +466,7 @@ int repo_is_descendant_of(struct repository *r,

other = with_commit->item;
with_commit = with_commit->next;
if (repo_in_merge_bases_many(r, other, 1, &commit))
if (repo_in_merge_bases_many(r, other, 1, &commit, 0))
return 1;
}
return 0;
Expand All @@ -477,17 +477,18 @@ int repo_is_descendant_of(struct repository *r,
* Is "commit" an ancestor of one of the "references"?
*/
int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
int nr_reference, struct commit **reference)
int nr_reference, struct commit **reference,
int ignore_missing_commits)
{
struct commit_list *bases;
int ret = 0, i;
timestamp_t generation, max_generation = GENERATION_NUMBER_ZERO;

if (repo_parse_commit(r, commit))
return ret;
return ignore_missing_commits ? 0 : -1;
for (i = 0; i < nr_reference; i++) {
if (repo_parse_commit(r, reference[i]))
return ret;
return ignore_missing_commits ? 0 : -1;

generation = commit_graph_generation(reference[i]);
if (generation > max_generation)
Expand Down
3 changes: 2 additions & 1 deletion commit-reach.h
Expand Up @@ -30,7 +30,8 @@ int repo_in_merge_bases(struct repository *r,
struct commit *reference);
int repo_in_merge_bases_many(struct repository *r,
struct commit *commit,
int nr_reference, struct commit **reference);
int nr_reference, struct commit **reference,
int ignore_missing_commits);

/*
* Takes a list of commits and returns a new list where those
Expand Down
2 changes: 1 addition & 1 deletion remote.c
Expand Up @@ -2680,7 +2680,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)
if (MERGE_BASES_BATCH_SIZE < size)
size = MERGE_BASES_BATCH_SIZE;

if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk)))
if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk, 0)))
break;
}

Expand Down
5 changes: 3 additions & 2 deletions shallow.c
Expand Up @@ -796,7 +796,7 @@ static void post_assign_shallow(struct shallow_info *info,
for (j = 0; j < bitmap_nr; j++)
if (bitmap[0][j] &&
/* Step 7, reachability test at commit level */
!repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits)) {
!repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1)) {
update_refstatus(ref_status, info->ref->nr, *bitmap);
dst++;
break;
Expand Down Expand Up @@ -827,7 +827,8 @@ int delayed_reachability_test(struct shallow_info *si, int c)
si->reachable[c] = repo_in_merge_bases_many(the_repository,
commit,
si->nr_commits,
si->commits);
si->commits,
1);
si->need_reachability_test[c] = 0;
}
return si->reachable[c];
Expand Down
2 changes: 1 addition & 1 deletion t/helper/test-reach.c
Expand Up @@ -111,7 +111,7 @@ int cmd__reach(int ac, const char **av)
repo_in_merge_bases(the_repository, A, B));
else if (!strcmp(av[1], "in_merge_bases_many"))
printf("%s(A,X):%d\n", av[1],
repo_in_merge_bases_many(the_repository, A, X_nr, X_array));
repo_in_merge_bases_many(the_repository, A, X_nr, X_array, 0));
else if (!strcmp(av[1], "is_descendant_of"))
printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X));
else if (!strcmp(av[1], "get_merge_bases_many")) {
Expand Down

0 comments on commit 207c40e

Please sign in to comment.