]> git.ipfire.org Git - thirdparty/git.git/commitdiff
packfile: introduce function to load and add packfiles
authorPatrick Steinhardt <ps@pks.im>
Tue, 23 Sep 2025 10:17:10 +0000 (12:17 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 Sep 2025 18:53:50 +0000 (11:53 -0700)
We have a recurring pattern where we essentially perform an upsert of a
packfile in case it isn't yet known by the packfile store. The logic to
do so is non-trivial as we have to reconstruct the packfile's key, check
the map of packfiles, then create the new packfile and finally add it to
the store.

Introduce a new function that does this dance for us. Refactor callsites
to use it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fast-import.c
builtin/index-pack.c
midx.c
packfile.c
packfile.h

index e9d82b31c390bf05e5229d9d9af037ae4e056ce6..a26e79689d55b86709abbe4636cd54008be43a29 100644 (file)
@@ -897,11 +897,11 @@ static void end_packfile(void)
                idx_name = keep_pack(create_index());
 
                /* Register the packfile with core git's machinery. */
-               new_p = add_packed_git(pack_data->repo, idx_name, strlen(idx_name), 1);
+               new_p = packfile_store_load_pack(pack_data->repo->objects->packfiles,
+                                                idx_name, 1);
                if (!new_p)
                        die("core git rejected index %s", idx_name);
                all_packs[pack_id] = new_p;
-               packfile_store_add_pack(the_repository->objects->packfiles, new_p);
                free(idx_name);
 
                /* Print the boundary */
index ed490dfad47859a8eafa5e57e6cd6317fb3e06dc..2b78ba7fe4d14a8bcb12165395ff02deeb8c047f 100644 (file)
@@ -1640,13 +1640,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
        rename_tmp_packfile(&final_index_name, curr_index_name, &index_name,
                            hash, "idx", 1);
 
-       if (do_fsck_object) {
-               struct packed_git *p;
-               p = add_packed_git(the_repository, final_index_name,
-                                  strlen(final_index_name), 0);
-               if (p)
-                       packfile_store_add_pack(the_repository->objects->packfiles, p);
-       }
+       if (do_fsck_object)
+               packfile_store_load_pack(the_repository->objects->packfiles,
+                                        final_index_name, 0);
 
        if (!from_stdin) {
                printf("%s\n", hash_to_hex(hash));
diff --git a/midx.c b/midx.c
index 69c44be71c5dc7e59e165260a6eb98fc50bbcb93..3faeaf2f8faed15caec2d5fd8215c82a1009472d 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -443,7 +443,6 @@ int prepare_midx_pack(struct multi_pack_index *m,
 {
        struct repository *r = m->source->odb->repo;
        struct strbuf pack_name = STRBUF_INIT;
-       struct strbuf key = STRBUF_INIT;
        struct packed_git *p;
 
        pack_int_id = midx_for_pack(&m, pack_int_id);
@@ -455,25 +454,11 @@ int prepare_midx_pack(struct multi_pack_index *m,
 
        strbuf_addf(&pack_name, "%s/pack/%s", m->source->path,
                    m->pack_names[pack_int_id]);
-
-       /* pack_map holds the ".pack" name, but we have the .idx */
-       strbuf_addbuf(&key, &pack_name);
-       strbuf_strip_suffix(&key, ".idx");
-       strbuf_addstr(&key, ".pack");
-       p = hashmap_get_entry_from_hash(&r->objects->packfiles->map,
-                                       strhash(key.buf), key.buf,
-                                       struct packed_git, packmap_ent);
-       if (!p) {
-               p = add_packed_git(r, pack_name.buf, pack_name.len,
-                                  m->source->local);
-               if (p) {
-                       packfile_store_add_pack(r->objects->packfiles, p);
-                       list_add_tail(&p->mru, &r->objects->packfiles->mru);
-               }
-       }
-
+       p = packfile_store_load_pack(r->objects->packfiles,
+                                    pack_name.buf, m->source->local);
+       if (p)
+               list_add_tail(&p->mru, &r->objects->packfiles->mru);
        strbuf_release(&pack_name);
-       strbuf_release(&key);
 
        if (!p) {
                m->packs[pack_int_id] = MIDX_PACK_ERROR;
index af806aba093518b9e4c74e57f77ede7546bdad75..9224ca424c187ce6eefea5fcda93d31aa47ce041 100644 (file)
@@ -792,6 +792,33 @@ void packfile_store_add_pack(struct packfile_store *store,
        hashmap_add(&store->map, &pack->packmap_ent);
 }
 
+struct packed_git *packfile_store_load_pack(struct packfile_store *store,
+                                           const char *idx_path, int local)
+{
+       struct strbuf key = STRBUF_INIT;
+       struct packed_git *p;
+
+       /*
+        * We're being called with the path to the index file, but `pack_map`
+        * holds the path to the packfile itself.
+        */
+       strbuf_addstr(&key, idx_path);
+       strbuf_strip_suffix(&key, ".idx");
+       strbuf_addstr(&key, ".pack");
+
+       p = hashmap_get_entry_from_hash(&store->map, strhash(key.buf), key.buf,
+                                       struct packed_git, packmap_ent);
+       if (!p) {
+               p = add_packed_git(store->odb->repo, idx_path,
+                                  strlen(idx_path), local);
+               if (p)
+                       packfile_store_add_pack(store, p);
+       }
+
+       strbuf_release(&key);
+       return p;
+}
+
 void (*report_garbage)(unsigned seen_bits, const char *path);
 
 static void report_helper(const struct string_list *list,
@@ -891,23 +918,14 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
                         const char *file_name, void *_data)
 {
        struct prepare_pack_data *data = (struct prepare_pack_data *)_data;
-       struct packed_git *p;
        size_t base_len = full_name_len;
 
        if (strip_suffix_mem(full_name, &base_len, ".idx") &&
            !(data->m && midx_contains_pack(data->m, file_name))) {
-               struct hashmap_entry hent;
-               char *pack_name = xstrfmt("%.*s.pack", (int)base_len, full_name);
-               unsigned int hash = strhash(pack_name);
-               hashmap_entry_init(&hent, hash);
-
-               /* Don't reopen a pack we already have. */
-               if (!hashmap_get(&data->r->objects->packfiles->map, &hent, pack_name)) {
-                       p = add_packed_git(data->r, full_name, full_name_len, data->local);
-                       if (p)
-                               packfile_store_add_pack(data->r->objects->packfiles, p);
-               }
-               free(pack_name);
+               char *trimmed_path = xstrndup(full_name, full_name_len);
+               packfile_store_load_pack(data->r->objects->packfiles,
+                                        trimmed_path, data->local);
+               free(trimmed_path);
        }
 
        if (!report_garbage)
index ba4b0cef9cb0e7b51e4a36dd226f8c4cb796df86..fcefcbbef65f0bad818820f5323aac88b9664d83 100644 (file)
@@ -127,6 +127,14 @@ void packfile_store_reprepare(struct packfile_store *store);
 void packfile_store_add_pack(struct packfile_store *store,
                             struct packed_git *pack);
 
+/*
+ * Open the packfile and add it to the store if it isn't yet known. Returns
+ * either the newly opened packfile or the preexisting packfile. Returns a
+ * `NULL` pointer in case the packfile could not be opened.
+ */
+struct packed_git *packfile_store_load_pack(struct packfile_store *store,
+                                           const char *idx_path, int local);
+
 struct pack_window {
        struct pack_window *next;
        unsigned char *base;