!(pack_everything & PACK_CRUFT))
strvec_push(&cmd.args, "--pack-loose-unreachable");
} else if (geometry.split_factor) {
+ pack_geometry_repack_promisors(repo, &po_args, &geometry,
+ &names, packtmp);
+
if (midx_must_contain_cruft)
strvec_push(&cmd.args, "--stdin-packs");
else
if (p->is_cruft)
continue;
- ALLOC_GROW(geometry->pack,
- geometry->pack_nr + 1,
- geometry->pack_alloc);
-
- geometry->pack[geometry->pack_nr] = p;
- geometry->pack_nr++;
+ if (p->pack_promisor) {
+ ALLOC_GROW(geometry->promisor_pack,
+ geometry->promisor_pack_nr + 1,
+ geometry->promisor_pack_alloc);
+
+ geometry->promisor_pack[geometry->promisor_pack_nr] = p;
+ geometry->promisor_pack_nr++;
+ } else {
+ ALLOC_GROW(geometry->pack,
+ geometry->pack_nr + 1,
+ geometry->pack_alloc);
+
+ geometry->pack[geometry->pack_nr] = p;
+ geometry->pack_nr++;
+ }
}
QSORT(geometry->pack, geometry->pack_nr, pack_geometry_cmp);
+ QSORT(geometry->promisor_pack, geometry->promisor_pack_nr, pack_geometry_cmp);
strbuf_release(&buf);
}
{
geometry->split = compute_pack_geometry_split(geometry->pack, geometry->pack_nr,
geometry->split_factor);
+ geometry->promisor_split = compute_pack_geometry_split(geometry->promisor_pack,
+ geometry->promisor_pack_nr,
+ geometry->split_factor);
}
struct packed_git *pack_geometry_preferred_pack(struct pack_geometry *geometry)
{
remove_redundant_packs(geometry->pack, geometry->split,
names, existing, packdir);
+ remove_redundant_packs(geometry->promisor_pack, geometry->promisor_split,
+ names, existing, packdir);
}
void pack_geometry_release(struct pack_geometry *geometry)
return;
free(geometry->pack);
+ free(geometry->promisor_pack);
}
finish_repacking_promisor_objects(repo, &cmd, names, packtmp);
}
+
+void pack_geometry_repack_promisors(struct repository *repo,
+ const struct pack_objects_args *args,
+ const struct pack_geometry *geometry,
+ struct string_list *names,
+ const char *packtmp)
+{
+ struct child_process cmd = CHILD_PROCESS_INIT;
+ FILE *in;
+
+ if (!geometry->promisor_split)
+ return;
+
+ prepare_pack_objects(&cmd, args, packtmp);
+ strvec_push(&cmd.args, "--stdin-packs");
+ cmd.in = -1;
+ if (start_command(&cmd))
+ die(_("could not start pack-objects to repack promisor packs"));
+
+ in = xfdopen(cmd.in, "w");
+ for (size_t i = 0; i < geometry->promisor_split; i++)
+ fprintf(in, "%s\n", pack_basename(geometry->promisor_pack[i]));
+ for (size_t i = geometry->promisor_split; i < geometry->promisor_pack_nr; i++)
+ fprintf(in, "^%s\n", pack_basename(geometry->promisor_pack[i]));
+ fclose(in);
+
+ finish_repacking_promisor_objects(repo, &cmd, names, packtmp);
+}
uint32_t pack_nr, pack_alloc;
uint32_t split;
+ struct packed_git **promisor_pack;
+ uint32_t promisor_pack_nr, promisor_pack_alloc;
+ uint32_t promisor_split;
+
int split_factor;
};
+void pack_geometry_repack_promisors(struct repository *repo,
+ const struct pack_objects_args *args,
+ const struct pack_geometry *geometry,
+ struct string_list *names,
+ const char *packtmp);
+
void pack_geometry_init(struct pack_geometry *geometry,
struct existing_packs *existing,
const struct pack_objects_args *args);
test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap
'
+write_packfile () {
+ NR="$1"
+ PREFIX="$2"
+
+ printf "blob\ndata <<EOB\n$PREFIX %s\nEOB\n" $(test_seq $NR) |
+ git fast-import &&
+ git pack-objects --pack-loose-unreachable .git/objects/pack/pack &&
+ git prune-packed
+}
+
+write_promisor_packfile () {
+ PACKFILE=$(write_packfile "$@") &&
+ touch .git/objects/pack/pack-$PACKFILE.promisor &&
+ echo "$PACKFILE"
+}
+
+test_expect_success 'geometric repack works with promisor packs' '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set maintenance.auto false &&
+ git remote add promisor garbage &&
+ git config set remote.promisor.promisor true &&
+
+ # Packs A and B need to be merged.
+ NORMAL_A=$(write_packfile 2 normal-a) &&
+ NORMAL_B=$(write_packfile 2 normal-b) &&
+ NORMAL_C=$(write_packfile 14 normal-c) &&
+
+ # Packs A, B and C need to be merged.
+ PROMISOR_A=$(write_promisor_packfile 1 promisor-a) &&
+ PROMISOR_B=$(write_promisor_packfile 3 promisor-b) &&
+ PROMISOR_C=$(write_promisor_packfile 3 promisor-c) &&
+ PROMISOR_D=$(write_promisor_packfile 20 promisor-d) &&
+ PROMISOR_E=$(write_promisor_packfile 40 promisor-e) &&
+
+ git cat-file --batch-all-objects --batch-check="%(objectname)" >objects-expect &&
+
+ ls .git/objects/pack/*.pack >packs-before &&
+ test_line_count = 8 packs-before &&
+ git repack --geometric=2 -d &&
+ ls .git/objects/pack/*.pack >packs-after &&
+ test_line_count = 5 packs-after &&
+ test_grep ! "$NORMAL_A" packs-after &&
+ test_grep ! "$NORMAL_B" packs-after &&
+ test_grep "$NORMAL_C" packs-after &&
+ test_grep ! "$PROMISOR_A" packs-after &&
+ test_grep ! "$PROMISOR_B" packs-after &&
+ test_grep ! "$PROMISOR_C" packs-after &&
+ test_grep "$PROMISOR_D" packs-after &&
+ test_grep "$PROMISOR_E" packs-after &&
+
+ ls .git/objects/pack/*.promisor >promisors &&
+ test_line_count = 3 promisors &&
+
+ git cat-file --batch-all-objects --batch-check="%(objectname)" >objects-actual &&
+ test_cmp objects-expect objects-actual
+ )
+'
+
test_done