]> git.ipfire.org Git - thirdparty/git.git/commitdiff
repack: teach MIDX retention about geometric rollups
authorTaylor Blau <me@ttaylorr.com>
Fri, 26 Jun 2026 19:02:23 +0000 (15:02 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 26 Jun 2026 21:54:54 +0000 (14:54 -0700)
When writing an incremental MIDX, existing_packs_retain_midx_packs()
marks packs in the existing MIDX chain as retained. This keeps them from
being deleted by the later existing_packs deletion pass, since retained
MIDX layers may still refer to those packs.

Geometric repacks need a narrower rule. Packs below the split are rolled
up into the newly-written pack, and should remain eligible for deletion
even if the old MIDX chain mentions them. Packs above the split were
marked as retained by the previous commit.

Teach existing_packs_retain_midx_packs() to skip packs which are part of
the geometric rollup. This does not change the current caller's behavior,
since geometric repacks do not yet use the existing_packs deletion path.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/repack.c
repack.c
repack.h

index ce979d86d964c35ebd707488d80731ee4b198a28..66b46b86896d7e91f807779a9e178f0a7d35abf0 100644 (file)
@@ -576,7 +576,7 @@ int cmd_repack(int argc,
 
        if (delete_redundant && pack_everything & ALL_INTO_ONE) {
                if (write_midx == REPACK_WRITE_MIDX_INCREMENTAL)
-                       existing_packs_retain_midx_packs(&existing);
+                       existing_packs_retain_midx_packs(&existing, &geometry);
                existing_packs_mark_for_deletion(&existing, &names);
        }
 
index 9b3cb4254310a91ccdaef3a3477deaf1d5641a9c..c7b79a3c1137a2159475e520821df00ed23903ae 100644 (file)
--- a/repack.c
+++ b/repack.c
@@ -292,6 +292,39 @@ void existing_packs_mark_for_deletion(struct existing_packs *existing,
                                           &existing->cruft_packs);
 }
 
+static int pack_geometry_contains_pack(struct packed_git **packs,
+                                      uint32_t packs_nr,
+                                      const char *base)
+{
+       struct strbuf buf = STRBUF_INIT;
+       uint32_t i;
+
+       for (i = 0; i < packs_nr; i++) {
+               strbuf_reset(&buf);
+               strbuf_addstr(&buf, pack_basename(packs[i]));
+               strbuf_strip_suffix(&buf, ".pack");
+
+               if (!strcmp(buf.buf, base)) {
+                       strbuf_release(&buf);
+                       return 1;
+               }
+       }
+
+       strbuf_release(&buf);
+       return 0;
+}
+
+static int pack_geometry_contains_rollup(const struct pack_geometry *geometry,
+                                        const char *base)
+{
+       if (!geometry || !geometry->split_factor)
+               return 0;
+
+       return pack_geometry_contains_pack(geometry->pack, geometry->split, base) ||
+              pack_geometry_contains_pack(geometry->promisor_pack,
+                                          geometry->promisor_split, base);
+}
+
 /*
  * Mark every pack that is referenced by the existing MIDX chain as
  * retained, so that a subsequent call to
@@ -300,9 +333,12 @@ void existing_packs_mark_for_deletion(struct existing_packs *existing,
  * This is used when writing an incremental MIDX layer on top of an
  * existing chain: retained layers continue to reference the same
  * packs on disk, so those packs must not be unlinked even if the
- * freshly-written pack supersedes them.
+ * freshly-written pack supersedes them. When doing a geometric repack,
+ * packs below the split are rewritten into the new MIDX tip and should
+ * remain eligible for deletion.
  */
-void existing_packs_retain_midx_packs(struct existing_packs *existing)
+void existing_packs_retain_midx_packs(struct existing_packs *existing,
+                                     const struct pack_geometry *geometry)
 {
        struct string_list_item *item;
        struct strbuf buf = STRBUF_INIT;
@@ -315,6 +351,9 @@ void existing_packs_retain_midx_packs(struct existing_packs *existing)
                strbuf_strip_suffix(&buf, ".pack");
                strbuf_strip_suffix(&buf, ".idx");
 
+               if (pack_geometry_contains_rollup(geometry, buf.buf))
+                       continue;
+
                found = string_list_lookup(&existing->non_kept_packs, buf.buf);
                if (found)
                        existing_packs_mark_retained(found);
index bb4c944d0cbd9070e7843c668ac44e11f695808f..f0d082df9e8accfce8905116d26690cd470cfd7f 100644 (file)
--- a/repack.h
+++ b/repack.h
@@ -87,7 +87,8 @@ void existing_packs_retain_from_geometry(struct existing_packs *existing,
                                         const struct pack_geometry *geometry);
 void existing_packs_mark_for_deletion(struct existing_packs *existing,
                                      struct string_list *names);
-void existing_packs_retain_midx_packs(struct existing_packs *existing);
+void existing_packs_retain_midx_packs(struct existing_packs *existing,
+                                     const struct pack_geometry *geometry);
 void existing_packs_remove_redundant(struct existing_packs *existing,
                                     const char *packdir,
                                     bool wrote_incremental_midx);