diff --git a/fetch-pack.c b/fetch-pack.c index 8b4143d7523613..503da0f4450630 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -57,6 +57,7 @@ static struct string_list uri_protocols = STRING_LIST_INIT_DUP; #define ALTERNATE (1U << 1) #define COMMON (1U << 6) #define REACH_SCRATCH (1U << 7) +#define COMPLETE_FROM_COMMIT_GRAPH (1U << 8) /* * After sending this many "have"s if we do not get any new ACK , we @@ -122,29 +123,31 @@ 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 struct commit *deref_without_lazy_fetch(const struct object_id *oid, + int mark_additional_complete_information) { - struct object_info info = { .typep = type }; + 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_additional_complete_information) + commit->object.flags |= COMPLETE_FROM_COMMIT_GRAPH; 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_additional_complete_information) tag->object.flags |= COMPLETE; oid = &tag->tagged->oid; } else { @@ -152,7 +155,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 +165,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) { @@ -820,6 +813,14 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator, save_commit_buffer = old_save_commit_buffer; } +static void warn_in_commit_graph_only(const struct object_id *oid) +{ + warning(_("You are attempting to fetch %s, which is in the commit graph file but not in the object database."), + oid_to_hex(oid)); + warning(_("This is probably due to repo corruption.")); + warning(_("If you are attempting to repair this repo corruption by refetching the missing object, use 'git fetch --refetch' with the missing object.")); +} + /* * Returns 1 if every object pointed to by the given remote refs is available * locally and reachable from a local ref, and 0 otherwise. @@ -841,6 +842,10 @@ static int everything_local(struct fetch_pack_args *args, ref->name); continue; } + if (o->flags & COMPLETE_FROM_COMMIT_GRAPH) { + if (!has_object(the_repository, remote, 0)) + warn_in_commit_graph_only(remote); + } print_verbose(args, _("already have %s (%s)"), oid_to_hex(remote), ref->name); } diff --git a/object.h b/object.h index 17f32f1103e58a..196e4892535b89 100644 --- a/object.h +++ b/object.h @@ -65,7 +65,7 @@ void object_array_init(struct object_array *array); /* * object flag allocation: * revision.h: 0---------10 15 23------27 - * fetch-pack.c: 01 67 + * fetch-pack.c: 01 6-8 * negotiator/default.c: 2--5 * walker.c: 0-2 * upload-pack.c: 4 11-----14 16-----19