Merge branch 'jt/commit-graph-missing'
A regression where commit objects missing from a commit-graph can cause an infinite loop when doing a fetch in a partial clone has been fixed. * jt/commit-graph-missing: fetch-pack: die if in commit graph but not obj db Revert "fetch-pack: add a deref_without_lazy_fetch_extended()"maint
commit
486c9d3995
42
fetch-pack.c
42
fetch-pack.c
|
|
@ -122,29 +122,41 @@ static void for_each_cached_alternate(struct fetch_negotiator *negotiator,
|
|||
cb(negotiator, cache.items[i]);
|
||||
}
|
||||
|
||||
static struct commit *deref_without_lazy_fetch_extended(const struct object_id *oid,
|
||||
int mark_tags_complete,
|
||||
enum object_type *type,
|
||||
unsigned int oi_flags)
|
||||
static void die_in_commit_graph_only(const struct object_id *oid)
|
||||
{
|
||||
struct object_info info = { .typep = type };
|
||||
die(_("You are attempting to fetch %s, which is in the commit graph file but not in the object database.\n"
|
||||
"This is probably due to repo corruption.\n"
|
||||
"If you are attempting to repair this repo corruption by refetching the missing object, use 'git fetch --refetch' with the missing object."),
|
||||
oid_to_hex(oid));
|
||||
}
|
||||
|
||||
static struct commit *deref_without_lazy_fetch(const struct object_id *oid,
|
||||
int mark_tags_complete_and_check_obj_db)
|
||||
{
|
||||
enum object_type type;
|
||||
struct object_info info = { .typep = &type };
|
||||
struct commit *commit;
|
||||
|
||||
commit = lookup_commit_in_graph(the_repository, oid);
|
||||
if (commit)
|
||||
if (commit) {
|
||||
if (mark_tags_complete_and_check_obj_db) {
|
||||
if (!has_object(the_repository, oid, 0))
|
||||
die_in_commit_graph_only(oid);
|
||||
}
|
||||
return commit;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (oid_object_info_extended(the_repository, oid, &info,
|
||||
oi_flags))
|
||||
OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK))
|
||||
return NULL;
|
||||
if (*type == OBJ_TAG) {
|
||||
if (type == OBJ_TAG) {
|
||||
struct tag *tag = (struct tag *)
|
||||
parse_object(the_repository, oid);
|
||||
|
||||
if (!tag->tagged)
|
||||
return NULL;
|
||||
if (mark_tags_complete)
|
||||
if (mark_tags_complete_and_check_obj_db)
|
||||
tag->object.flags |= COMPLETE;
|
||||
oid = &tag->tagged->oid;
|
||||
} else {
|
||||
|
|
@ -152,7 +164,7 @@ static struct commit *deref_without_lazy_fetch_extended(const struct object_id *
|
|||
}
|
||||
}
|
||||
|
||||
if (*type == OBJ_COMMIT) {
|
||||
if (type == OBJ_COMMIT) {
|
||||
struct commit *commit = lookup_commit(the_repository, oid);
|
||||
if (!commit || repo_parse_commit(the_repository, commit))
|
||||
return NULL;
|
||||
|
|
@ -162,16 +174,6 @@ static struct commit *deref_without_lazy_fetch_extended(const struct object_id *
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static struct commit *deref_without_lazy_fetch(const struct object_id *oid,
|
||||
int mark_tags_complete)
|
||||
{
|
||||
enum object_type type;
|
||||
unsigned flags = OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK;
|
||||
return deref_without_lazy_fetch_extended(oid, mark_tags_complete,
|
||||
&type, flags);
|
||||
}
|
||||
|
||||
static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
|
||||
const struct object_id *oid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ test_expect_success 'fetch any commit from promisor with the usage of the commit
|
|||
git -C with-commit-graph config remote.origin.partialclonefilter blob:none &&
|
||||
test_commit -C with-commit any-commit &&
|
||||
anycommit=$(git -C with-commit rev-parse HEAD) &&
|
||||
GIT_TRACE="$(pwd)/trace.txt" \
|
||||
test_must_fail env GIT_TRACE="$(pwd)/trace.txt" \
|
||||
git -C with-commit-graph fetch origin $anycommit 2>err &&
|
||||
! grep "fatal: promisor-remote: unable to fork off fetch subprocess" err &&
|
||||
test_grep ! "fatal: promisor-remote: unable to fork off fetch subprocess" err &&
|
||||
grep "git fetch origin" trace.txt >actual &&
|
||||
test_line_count = 1 actual
|
||||
'
|
||||
|
|
|
|||
Loading…
Reference in New Issue