packfile: introduce function to read object info from a store

Extract the logic to read object info for a packed object from `do_oid_object_into_extended()` into a standalone function that operates on the packfile store. This function will be used in a subsequent commit. Note that this change allows us to make `find_pack_entry()` an internal implementation detail. As a consequence though we have to move around `packfile_store_freshen_object()` so that it is defined after that function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 23, 2025 at 19:59 UTC 385e18810f10ec0ce0a266d25da4e1878c8ce15a
3 files changed +69 -43
odb.c
+4 -25
@@ -666,8 +666,6 @@ static int do_oid_object_info_extended(struct object_database *odb,
666 {
667 static struct object_info blank_oi = OBJECT_INFO_INIT;
668 const struct cached_object *co;
669 - struct pack_entry e;
670 - int rtype;
669 const struct object_id *real = oid;
670 int already_retried = 0;
671
@@ -702,8 +700,8 @@ static int do_oid_object_info_extended(struct object_database *odb,
700 while (1) {
701 struct odb_source *source;
702
705 - if (find_pack_entry(odb->repo, real, &e))
706 - break;
703 + if (!packfile_store_read_object_info(odb->packfiles, real, oi, flags))
704 + return 0;
705
706 /* Most likely it's a loose object. */
707 for (source = odb->sources; source; source = source->next)
@@ -713,8 +711,8 @@ static int do_oid_object_info_extended(struct object_database *odb,
711 /* Not a loose object; someone else may have just packed it. */
712 if (!(flags & OBJECT_INFO_QUICK)) {
713 odb_reprepare(odb->repo->objects);
716 - if (find_pack_entry(odb->repo, real, &e))
717 - break;
714 + if (!packfile_store_read_object_info(odb->packfiles, real, oi, flags))
715 + return 0;
716 }
717
718 /*
@@ -747,25 +745,6 @@ static int do_oid_object_info_extended(struct object_database *odb,
745 }
746 return -1;
747 }
750 -
751 - if (oi == &blank_oi)
752 - /*
753 - * We know that the caller doesn't actually need the
754 - * information below, so return early.
755 - */
756 - return 0;
757 - rtype = packed_object_info(odb->repo, e.p, e.offset, oi);
758 - if (rtype < 0) {
759 - mark_bad_packed_object(e.p, real);
760 - return do_oid_object_info_extended(odb, real, oi, 0);
761 - } else if (oi->whence == OI_PACKED) {
762 - oi->u.packed.offset = e.offset;
763 - oi->u.packed.pack = e.p;
764 - oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
765 - rtype == OBJ_OFS_DELTA);
766 - }
767 -
768 - return 0;
748 }
749
750 static int oid_object_info_convert(struct repository *r,
packfile.c
+54 -17
@@ -819,22 +819,6 @@ struct packed_git *packfile_store_load_pack(struct packfile_store *store,
819 return p;
820 }
821
822 -int packfile_store_freshen_object(struct packfile_store *store,
823 - const struct object_id *oid)
824 -{
825 - struct pack_entry e;
826 - if (!find_pack_entry(store->odb->repo, oid, &e))
827 - return 0;
828 - if (e.p->is_cruft)
829 - return 0;
830 - if (e.p->freshened)
831 - return 1;
832 - if (utime(e.p->pack_name, NULL))
833 - return 0;
834 - e.p->freshened = 1;
835 - return 1;
836 -}
837 -
822 void (*report_garbage)(unsigned seen_bits, const char *path);
823
824 static void report_helper(const struct string_list *list,
@@ -2064,7 +2048,9 @@ static int fill_pack_entry(const struct object_id *oid,
2048 return 1;
2049 }
2050
2067 -int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e)
2051 +static int find_pack_entry(struct repository *r,
2052 + const struct object_id *oid,
2053 + struct pack_entry *e)
2054 {
2055 struct list_head *pos;
2056
@@ -2087,6 +2073,57 @@ int find_pack_entry(struct repository *r, const struct object_id *oid, struct pa
2073 return 0;
2074 }
2075
2076 +int packfile_store_freshen_object(struct packfile_store *store,
2077 + const struct object_id *oid)
2078 +{
2079 + struct pack_entry e;
2080 + if (!find_pack_entry(store->odb->repo, oid, &e))
2081 + return 0;
2082 + if (e.p->is_cruft)
2083 + return 0;
2084 + if (e.p->freshened)
2085 + return 1;
2086 + if (utime(e.p->pack_name, NULL))
2087 + return 0;
2088 + e.p->freshened = 1;
2089 + return 1;
2090 +}
2091 +
2092 +int packfile_store_read_object_info(struct packfile_store *store,
2093 + const struct object_id *oid,
2094 + struct object_info *oi,
2095 + unsigned flags UNUSED)
2096 +{
2097 + static struct object_info blank_oi = OBJECT_INFO_INIT;
2098 + struct pack_entry e;
2099 + int rtype;
2100 +
2101 + if (!find_pack_entry(store->odb->repo, oid, &e))
2102 + return 1;
2103 +
2104 + /*
2105 + * We know that the caller doesn't actually need the
2106 + * information below, so return early.
2107 + */
2108 + if (oi == &blank_oi)
2109 + return 0;
2110 +
2111 + rtype = packed_object_info(store->odb->repo, e.p, e.offset, oi);
2112 + if (rtype < 0) {
2113 + mark_bad_packed_object(e.p, oid);
2114 + return -1;
2115 + }
2116 +
2117 + if (oi->whence == OI_PACKED) {
2118 + oi->u.packed.offset = e.offset;
2119 + oi->u.packed.pack = e.p;
2120 + oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
2121 + rtype == OBJ_OFS_DELTA);
2122 + }
2123 +
2124 + return 0;
2125 +}
2126 +
2127 static void maybe_invalidate_kept_pack_cache(struct repository *r,
2128 unsigned flags)
2129 {
packfile.h
+11 -1
@@ -144,6 +144,17 @@ void packfile_store_add_pack(struct packfile_store *store,
144 #define repo_for_each_pack(repo, p) \
145 for (p = packfile_store_get_packs(repo->objects->packfiles); p; p = p->next)
146
147 +/*
148 + * Try to read the object identified by its ID from the object store and
149 + * populate the object info with its data. Returns 1 in case the object was
150 + * not found, 0 if it was and read successfully, and a negative error code in
151 + * case the object was corrupted.
152 + */
153 +int packfile_store_read_object_info(struct packfile_store *store,
154 + const struct object_id *oid,
155 + struct object_info *oi,
156 + unsigned flags);
157 +
158 /*
159 * Get all packs managed by the given store, including packfiles that are
160 * referenced by multi-pack indices.
@@ -357,7 +368,6 @@ const struct packed_git *has_packed_and_bad(struct repository *, const struct ob
368 * Iff a pack file in the given repository contains the object named by sha1,
369 * return true and store its location to e.
370 */
360 -int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e);
371 int find_kept_pack_entry(struct repository *r, const struct object_id *oid, unsigned flags, struct pack_entry *e);
372
373 int has_object_pack(struct repository *r, const struct object_id *oid);