summaryrefslogtreecommitdiff
path: root/builtin/repack.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2023-04-25 20:56:20 (GMT)
committerJunio C Hamano <gitster@pobox.com>2023-04-25 20:56:20 (GMT)
commit36628c56ed54b5a86aa9a17ed589fc0ee7f5bea5 (patch)
tree3fadafc81f95d070092fb0a000b10dc02f5b1669 /builtin/repack.c
parentc4c9d5586fed1b994ef579a0862b86ff36afcbe8 (diff)
parentd85cd1877777aa92c73868b9e86516d4be04b4a0 (diff)
downloadgit-36628c56ed54b5a86aa9a17ed589fc0ee7f5bea5.zip
git-36628c56ed54b5a86aa9a17ed589fc0ee7f5bea5.tar.gz
git-36628c56ed54b5a86aa9a17ed589fc0ee7f5bea5.tar.bz2
Merge branch 'ps/fix-geom-repack-with-alternates'
Geometric repacking ("git repack --geometric=<n>") in a repository that borrows from an alternate object database had various corner case bugs, which have been corrected. * ps/fix-geom-repack-with-alternates: repack: disable writing bitmaps when doing a local repack repack: honor `-l` when calculating pack geometry t/helper: allow chmtime to print verbosely without modifying mtime pack-objects: extend test coverage of `--stdin-packs` with alternates pack-objects: fix error when same packfile is included and excluded pack-objects: fix error when packing same pack twice pack-objects: split out `--stdin-packs` tests into separate file repack: fix generating multi-pack-index with only non-local packs repack: fix trying to use preferred pack in alternates midx: fix segfault with no packs and invalid preferred pack
Diffstat (limited to 'builtin/repack.c')
-rw-r--r--builtin/repack.c62
1 files changed, 55 insertions, 7 deletions
diff --git a/builtin/repack.c b/builtin/repack.c
index df4d8e0..a690227 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -325,7 +325,8 @@ static int geometry_cmp(const void *va, const void *vb)
}
static void init_pack_geometry(struct pack_geometry **geometry_p,
- struct string_list *existing_kept_packs)
+ struct string_list *existing_kept_packs,
+ const struct pack_objects_args *args)
{
struct packed_git *p;
struct pack_geometry *geometry;
@@ -335,6 +336,14 @@ static void init_pack_geometry(struct pack_geometry **geometry_p,
geometry = *geometry_p;
for (p = get_all_packs(the_repository); p; p = p->next) {
+ if (args->local && !p->pack_local)
+ /*
+ * When asked to only repack local packfiles we skip
+ * over any packfiles that are borrowed from alternate
+ * object directories.
+ */
+ continue;
+
if (!pack_kept_objects) {
/*
* Any pack that has its pack_keep bit set will appear
@@ -448,8 +457,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
@@ -464,7 +475,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)
@@ -558,6 +583,17 @@ static void midx_included_packs(struct string_list *include,
for (i = geometry->split; i < geometry->pack_nr; i++) {
struct packed_git *p = geometry->pack[i];
+ /*
+ * The multi-pack index never refers to packfiles part
+ * of an alternate object database, so we skip these.
+ * While git-multi-pack-index(1) would silently ignore
+ * them anyway, this allows us to skip executing the
+ * command completely when we have only non-local
+ * packfiles.
+ */
+ if (!p->pack_local)
+ continue;
+
strbuf_addstr(&buf, pack_basename(p));
strbuf_strip_suffix(&buf, ".pack");
strbuf_addstr(&buf, ".idx");
@@ -591,7 +627,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;
@@ -612,9 +648,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);
@@ -853,6 +889,18 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx)
die(_(incremental_bitmap_conflict_error));
+ if (write_bitmaps && po_args.local && has_alt_odb(the_repository)) {
+ /*
+ * When asked to do a local repack, but we have
+ * packfiles that are inherited from an alternate, then
+ * we cannot guarantee that the multi-pack-index would
+ * have full coverage of all objects. We thus disable
+ * writing bitmaps in that case.
+ */
+ warning(_("disabling bitmap writing, as some objects are not being packed"));
+ write_bitmaps = 0;
+ }
+
if (write_midx && write_bitmaps) {
struct strbuf path = STRBUF_INIT;
@@ -875,7 +923,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
if (geometric_factor) {
if (pack_everything)
die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
- init_pack_geometry(&geometry, &existing_kept_packs);
+ init_pack_geometry(&geometry, &existing_kept_packs, &po_args);
split_pack_geometry(geometry, geometric_factor);
}