]> git.ipfire.org Git - thirdparty/git.git/commitdiff
packfile: refactor kept-pack cache to work with packfile stores
authorPatrick Steinhardt <ps@pks.im>
Thu, 18 Dec 2025 06:55:22 +0000 (07:55 +0100)
committerJunio C Hamano <gitster@pobox.com>
Wed, 7 Jan 2026 00:37:43 +0000 (09:37 +0900)
The kept pack cache is a cache of packfiles that are marked as kept
either via an accompanying ".kept" file or via an in-memory flag. The
cache can be retrieved via `kept_pack_cache()`, where one needs to pass
in a repository.

Ultimately though the kept-pack cache is a property of the packfile
store, and this causes problems in a subsequent commit where we want to
move down the packfile store to be a per-object-source entity.

Prepare for this and refactor the kept-pack cache to work on top of a
packfile store instead. While at it, rename both the function and flags
specific to the kept-pack cache so that they can be properly attributed
to the respective subsystems.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/pack-objects.c
packfile.c
packfile.h
reachable.c
revision.c

index 1ce8d6ee21532655366547bf87373a30be91f38a..e86b8f387a8c64074512012d64a3550a3dc11f5a 100644 (file)
@@ -1529,9 +1529,9 @@ static int want_cruft_object_mtime(struct repository *r,
                                   const struct object_id *oid,
                                   unsigned flags, uint32_t mtime)
 {
-       struct packed_git **cache;
+       struct packed_git **cache = packfile_store_get_kept_pack_cache(r->objects->packfiles, flags);
 
-       for (cache = kept_pack_cache(r, flags); *cache; cache++) {
+       for (; *cache; cache++) {
                struct packed_git *p = *cache;
                off_t ofs;
                uint32_t candidate_mtime;
@@ -1624,9 +1624,9 @@ static int want_found_object(const struct object_id *oid, int exclude,
                 */
                unsigned flags = 0;
                if (ignore_packed_keep_on_disk)
-                       flags |= ON_DISK_KEEP_PACKS;
+                       flags |= KEPT_PACK_ON_DISK;
                if (ignore_packed_keep_in_core)
-                       flags |= IN_CORE_KEEP_PACKS;
+                       flags |= KEPT_PACK_IN_CORE;
 
                /*
                 * If the object is in a pack that we want to ignore, *and* we
@@ -3931,7 +3931,7 @@ static void read_stdin_packs(enum stdin_packs_mode mode, int rev_list_unpacked)
         * an optimization during delta selection.
         */
        revs.no_kept_objects = 1;
-       revs.keep_pack_cache_flags |= IN_CORE_KEEP_PACKS;
+       revs.keep_pack_cache_flags |= KEPT_PACK_IN_CORE;
        revs.blob_objects = 1;
        revs.tree_objects = 1;
        revs.tag_objects = 1;
@@ -4030,7 +4030,7 @@ static void show_cruft_commit(struct commit *commit, void *data)
 
 static int cruft_include_check_obj(struct object *obj, void *data UNUSED)
 {
-       return !has_object_kept_pack(to_pack.repo, &obj->oid, IN_CORE_KEEP_PACKS);
+       return !has_object_kept_pack(to_pack.repo, &obj->oid, KEPT_PACK_IN_CORE);
 }
 
 static int cruft_include_check(struct commit *commit, void *data)
index ab86afa01d7a992186ed09bcf1b30ce2e1fb0676..191344eb1cf3463c8f1d81a8e859e0322de56a62 100644 (file)
@@ -2164,25 +2164,26 @@ int packfile_store_read_object_info(struct packfile_store *store,
        return 0;
 }
 
-static void maybe_invalidate_kept_pack_cache(struct repository *r,
+static void maybe_invalidate_kept_pack_cache(struct packfile_store *store,
                                             unsigned flags)
 {
-       if (!r->objects->packfiles->kept_cache.packs)
+       if (!store->kept_cache.packs)
                return;
-       if (r->objects->packfiles->kept_cache.flags == flags)
+       if (store->kept_cache.flags == flags)
                return;
-       FREE_AND_NULL(r->objects->packfiles->kept_cache.packs);
-       r->objects->packfiles->kept_cache.flags = 0;
+       FREE_AND_NULL(store->kept_cache.packs);
+       store->kept_cache.flags = 0;
 }
 
-struct packed_git **kept_pack_cache(struct repository *r, unsigned flags)
+struct packed_git **packfile_store_get_kept_pack_cache(struct packfile_store *store,
+                                                      unsigned flags)
 {
-       maybe_invalidate_kept_pack_cache(r, flags);
+       maybe_invalidate_kept_pack_cache(store, flags);
 
-       if (!r->objects->packfiles->kept_cache.packs) {
+       if (!store->kept_cache.packs) {
                struct packed_git **packs = NULL;
+               struct packfile_list_entry *e;
                size_t nr = 0, alloc = 0;
-               struct packed_git *p;
 
                /*
                 * We want "all" packs here, because we need to cover ones that
@@ -2192,9 +2193,11 @@ struct packed_git **kept_pack_cache(struct repository *r, unsigned flags)
                 * covers, one kept and one not kept, but the midx returns only
                 * the non-kept version.
                 */
-               repo_for_each_pack(r, p) {
-                       if ((p->pack_keep && (flags & ON_DISK_KEEP_PACKS)) ||
-                           (p->pack_keep_in_core && (flags & IN_CORE_KEEP_PACKS))) {
+               for (e = packfile_store_get_packs(store); e; e = e->next) {
+                       struct packed_git *p = e->pack;
+
+                       if ((p->pack_keep && (flags & KEPT_PACK_ON_DISK)) ||
+                           (p->pack_keep_in_core && (flags & KEPT_PACK_IN_CORE))) {
                                ALLOC_GROW(packs, nr + 1, alloc);
                                packs[nr++] = p;
                        }
@@ -2202,11 +2205,11 @@ struct packed_git **kept_pack_cache(struct repository *r, unsigned flags)
                ALLOC_GROW(packs, nr + 1, alloc);
                packs[nr] = NULL;
 
-               r->objects->packfiles->kept_cache.packs = packs;
-               r->objects->packfiles->kept_cache.flags = flags;
+               store->kept_cache.packs = packs;
+               store->kept_cache.flags = flags;
        }
 
-       return r->objects->packfiles->kept_cache.packs;
+       return store->kept_cache.packs;
 }
 
 int find_kept_pack_entry(struct repository *r,
@@ -2214,9 +2217,9 @@ int find_kept_pack_entry(struct repository *r,
                         unsigned flags,
                         struct pack_entry *e)
 {
-       struct packed_git **cache;
+       struct packed_git **cache = packfile_store_get_kept_pack_cache(r->objects->packfiles, flags);
 
-       for (cache = kept_pack_cache(r, flags); *cache; cache++) {
+       for (; *cache; cache++) {
                struct packed_git *p = *cache;
                if (fill_pack_entry(oid, e, p))
                        return 1;
index 33cc1c1654f081894ed8d1abccc1e6aff7bc920d..410f85f03d7710736748a722903b518962e7d320 100644 (file)
@@ -90,9 +90,10 @@ struct packfile_store {
         * is an on-disk ".keep" file or because they are marked as "kept" in
         * memory.
         *
-        * Should not be accessed directly, but via `kept_pack_cache()`. The
-        * list of packs gets invalidated when the stored flags and the flags
-        * passed to `kept_pack_cache()` mismatch.
+        * Should not be accessed directly, but via
+        * `packfile_store_get_kept_pack_cache()`. The list of packs gets
+        * invalidated when the stored flags and the flags passed to
+        * `packfile_store_get_kept_pack_cache()` mismatch.
         */
        struct {
                struct packed_git **packs;
@@ -210,6 +211,19 @@ struct packed_git *packfile_store_load_pack(struct packfile_store *store,
 int packfile_store_freshen_object(struct packfile_store *store,
                                  const struct object_id *oid);
 
+enum kept_pack_type {
+       KEPT_PACK_ON_DISK = (1 << 0),
+       KEPT_PACK_IN_CORE = (1 << 1),
+};
+
+/*
+ * Retrieve the cache of kept packs from the given packfile store. Accepts a
+ * combination of `kept_pack_type` flags. The cache is computed on demand and
+ * will be recomputed whenever the flags change.
+ */
+struct packed_git **packfile_store_get_kept_pack_cache(struct packfile_store *store,
+                                                      unsigned flags);
+
 struct pack_window {
        struct pack_window *next;
        unsigned char *base;
@@ -385,9 +399,6 @@ int packed_object_info(struct repository *r,
 void mark_bad_packed_object(struct packed_git *, const struct object_id *);
 const struct packed_git *has_packed_and_bad(struct repository *, const struct object_id *);
 
-#define ON_DISK_KEEP_PACKS 1
-#define IN_CORE_KEEP_PACKS 2
-
 /*
  * Iff a pack file in the given repository contains the object named by sha1,
  * return true and store its location to e.
@@ -398,8 +409,6 @@ int has_object_pack(struct repository *r, const struct object_id *oid);
 int has_object_kept_pack(struct repository *r, const struct object_id *oid,
                         unsigned flags);
 
-struct packed_git **kept_pack_cache(struct repository *r, unsigned flags);
-
 /*
  * Return 1 if an object in a promisor packfile is or refers to the given
  * object, 0 otherwise.
index b753c395530b6d3212006742bbd4f1671a2e22a6..4b532039d5f84fbfeafbe9184a17c0e022f13e8b 100644 (file)
@@ -242,7 +242,7 @@ static int want_recent_object(struct recent_data *data,
                              const struct object_id *oid)
 {
        if (data->ignore_in_core_kept_packs &&
-           has_object_kept_pack(data->revs->repo, oid, IN_CORE_KEEP_PACKS))
+           has_object_kept_pack(data->revs->repo, oid, KEPT_PACK_IN_CORE))
                return 0;
        return 1;
 }
index 5f0850ae5c9c1aec7838b0a9e05e2951a6f50fdd..64d223a7c683f0f97994ad17c8f4e5c16b762c74 100644 (file)
@@ -2541,14 +2541,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                die(_("--unpacked=<packfile> no longer supported"));
        } else if (!strcmp(arg, "--no-kept-objects")) {
                revs->no_kept_objects = 1;
-               revs->keep_pack_cache_flags |= IN_CORE_KEEP_PACKS;
-               revs->keep_pack_cache_flags |= ON_DISK_KEEP_PACKS;
+               revs->keep_pack_cache_flags |= KEPT_PACK_IN_CORE;
+               revs->keep_pack_cache_flags |= KEPT_PACK_ON_DISK;
        } else if (skip_prefix(arg, "--no-kept-objects=", &optarg)) {
                revs->no_kept_objects = 1;
                if (!strcmp(optarg, "in-core"))
-                       revs->keep_pack_cache_flags |= IN_CORE_KEEP_PACKS;
+                       revs->keep_pack_cache_flags |= KEPT_PACK_IN_CORE;
                if (!strcmp(optarg, "on-disk"))
-                       revs->keep_pack_cache_flags |= ON_DISK_KEEP_PACKS;
+                       revs->keep_pack_cache_flags |= KEPT_PACK_ON_DISK;
        } else if (!strcmp(arg, "-r")) {
                revs->diff = 1;
                revs->diffopt.flags.recursive = 1;