summaryrefslogtreecommitdiff
path: root/builtin/repack.c
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2023-04-14 06:01:36 (GMT)
committerJunio C Hamano <gitster@pobox.com>2023-04-14 17:27:51 (GMT)
commit3d74a2337c679839265efa16b2bca2a9b7795a00 (patch)
tree8dd6c351133f15213cdad19fa4ab1a098d4f45b0 /builtin/repack.c
parentceb96a160b05c3ec45c416851bac00b711418839 (diff)
downloadgit-3d74a2337c679839265efa16b2bca2a9b7795a00.zip
git-3d74a2337c679839265efa16b2bca2a9b7795a00.tar.gz
git-3d74a2337c679839265efa16b2bca2a9b7795a00.tar.bz2
repack: fix trying to use preferred pack in alternates
When doing a geometric repack with multi-pack-indices, then we ask git-multi-pack-index(1) to use the largest packfile as the preferred pack. It can happen though that the largest packfile is not part of the main object database, but instead part of an alternate object database. The result is that git-multi-pack-index(1) will not be able to find the preferred pack and print a warning. It then falls back to use the first packfile that the multi-pack-index shall reference. Fix this bug by only considering packfiles as preferred pack that are local. This is the right thing to do given that a multi-pack-index should never reference packfiles borrowed from an alternate. While at it, rename the function `get_largest_active_packfile()` to `get_preferred_pack()` to better document its intent. Helped-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/repack.c')
-rw-r--r--builtin/repack.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/builtin/repack.c b/builtin/repack.c
index f649379..63585ad 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -444,8 +444,10 @@ static void split_pack_geometry(struct pack_geometry *geometry, int factor)
geometry->split = split;
}
-static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry)
+static struct packed_git *get_preferred_pack(struct pack_geometry *geometry)
{
+ uint32_t i;
+
if (!geometry) {
/*
* No geometry means either an all-into-one repack (in which
@@ -460,7 +462,21 @@ static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry
}
if (geometry->split == geometry->pack_nr)
return NULL;
- return geometry->pack[geometry->pack_nr - 1];
+
+ /*
+ * The preferred pack is the largest pack above the split line. In
+ * other words, it is the largest pack that does not get rolled up in
+ * the geometric repack.
+ */
+ for (i = geometry->pack_nr; i > geometry->split; i--)
+ /*
+ * A pack that is not local would never be included in a
+ * multi-pack index. We thus skip over any non-local packs.
+ */
+ if (geometry->pack[i - 1]->pack_local)
+ return geometry->pack[i - 1];
+
+ return NULL;
}
static void clear_pack_geometry(struct pack_geometry *geometry)
@@ -587,7 +603,7 @@ static int write_midx_included_packs(struct string_list *include,
{
struct child_process cmd = CHILD_PROCESS_INIT;
struct string_list_item *item;
- struct packed_git *largest = get_largest_active_pack(geometry);
+ struct packed_git *preferred = get_preferred_pack(geometry);
FILE *in;
int ret;
@@ -608,9 +624,9 @@ static int write_midx_included_packs(struct string_list *include,
if (write_bitmaps)
strvec_push(&cmd.args, "--bitmap");
- if (largest)
+ if (preferred)
strvec_pushf(&cmd.args, "--preferred-pack=%s",
- pack_basename(largest));
+ pack_basename(preferred));
if (refs_snapshot)
strvec_pushf(&cmd.args, "--refs-snapshot=%s", refs_snapshot);