Skip to content

Commit d85cd18

Browse files
pks-tgitster
authored andcommitted
repack: disable writing bitmaps when doing a local repack
In order to write a bitmap, we need to have full coverage of all objects that are about to be packed. In the traditional non-multi-pack-index world this meant we need to do a full repack of all objects into a single packfile. But in the new multi-pack-index world we can get away with writing bitmaps when we have multiple packfiles as long as the multi-pack-index covers all objects. This is not always the case though. When asked to perform a repack of local objects, only, then we cannot guarantee to have full coverage of all objects regardless of whether we do a full repack or a repack with a multi-pack-index. The end result is that writing the bitmap will fail in both worlds: $ git multi-pack-index write --stdin-packs --bitmap <packfiles warning: Failed to write bitmap index. Packfile doesn't have full closure (object 1529341d78cf45377407369acb0f4ff2b5cdae42 is missing) error: could not write multi-pack bitmap Now there are two different ways to fix this. The first one would be to amend git-multi-pack-index(1) to disable writing bitmaps when we notice that we don't have full object coverage. - We don't have enough information in git-multi-pack-index(1) in order to tell whether the local repository _should_ have full coverage. Because even when connected to an alternate object directory, it may be the case that we still have all objects around in the main object database. - git-multi-pack-index(1) is quite a low-level tool. Automatically disabling functionality that it was asked to provide does not feel like the right thing to do. We can easily fix it at a higher level in git-repack(1) though. When asked to only include local objects via `-l` and when connected to an alternate object directory then we will override the user's ask and disable writing bitmaps with a warning. This is similar to what we do in git-pack-objects(1), where we also disable writing bitmaps in case we omit an object from the pack. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 932c16c commit d85cd18

File tree

5 files changed

+63
-0
lines changed

5 files changed

+63
-0
lines changed

builtin/repack.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,18 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
885885
if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx)
886886
die(_(incremental_bitmap_conflict_error));
887887

888+
if (write_bitmaps && po_args.local && has_alt_odb(the_repository)) {
889+
/*
890+
* When asked to do a local repack, but we have
891+
* packfiles that are inherited from an alternate, then
892+
* we cannot guarantee that the multi-pack-index would
893+
* have full coverage of all objects. We thus disable
894+
* writing bitmaps in that case.
895+
*/
896+
warning(_("disabling bitmap writing, as some objects are not being packed"));
897+
write_bitmaps = 0;
898+
}
899+
888900
if (write_midx && write_bitmaps) {
889901
struct strbuf path = STRBUF_INIT;
890902

object-file.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,12 @@ void prepare_alt_odb(struct repository *r)
944944
r->objects->loaded_alternates = 1;
945945
}
946946

947+
int has_alt_odb(struct repository *r)
948+
{
949+
prepare_alt_odb(r);
950+
return !!r->objects->odb->next;
951+
}
952+
947953
/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
948954
static int freshen_file(const char *fn)
949955
{

object-store.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ KHASH_INIT(odb_path_map, const char * /* key: odb_path */,
5656
struct object_directory *, 1, fspathhash, fspatheq)
5757

5858
void prepare_alt_odb(struct repository *r);
59+
int has_alt_odb(struct repository *r);
5960
char *compute_alternate_path(const char *path, struct strbuf *err);
6061
struct object_directory *find_odb(struct repository *r, const char *obj_dir);
6162
typedef int alt_odb_fn(struct object_directory *, void *);

t/t7700-repack.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,23 @@ test_expect_success SYMLINKS '--local keeps packs when alternate is objectdir '
106106
test_cmp expect actual
107107
'
108108

109+
test_expect_success '--local disables writing bitmaps when connected to alternate ODB' '
110+
test_when_finished "rm -rf shared member" &&
111+
112+
git init shared &&
113+
git clone --shared shared member &&
114+
(
115+
cd member &&
116+
test_commit "object" &&
117+
GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err &&
118+
cat >expect <<-EOF &&
119+
warning: disabling bitmap writing, as some objects are not being packed
120+
EOF
121+
test_cmp expect err &&
122+
test_path_is_missing .git/objects/pack-*.bitmap
123+
)
124+
'
125+
109126
test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
110127
mkdir alt_objects/pack &&
111128
mv .git/objects/pack/* alt_objects/pack &&

t/t7703-repack-geometric.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,4 +418,31 @@ test_expect_success '--geometric -l with non-intact geometric sequence across OD
418418
test_cmp expected-objects actual-objects
419419
'
420420

421+
test_expect_success '--geometric -l disables writing bitmaps with non-local packfiles' '
422+
test_when_finished "rm -fr shared member" &&
423+
424+
git init shared &&
425+
test_commit_bulk -C shared --start=1 1 &&
426+
427+
git clone --shared shared member &&
428+
test_commit_bulk -C member --start=2 1 &&
429+
430+
# When performing a geometric repack with `-l` while connected to an
431+
# alternate object database that has a packfile we do not have full
432+
# coverage of objects. As a result, we expect that writing the bitmap
433+
# will be disabled.
434+
git -C member repack -l --geometric=2 --write-midx --write-bitmap-index 2>err &&
435+
cat >expect <<-EOF &&
436+
warning: disabling bitmap writing, as some objects are not being packed
437+
EOF
438+
test_cmp expect err &&
439+
test_path_is_missing member/.git/objects/pack/multi-pack-index-*.bitmap &&
440+
441+
# On the other hand, when we repack without `-l`, we should see that
442+
# the bitmap gets created.
443+
git -C member repack --geometric=2 --write-midx --write-bitmap-index 2>err &&
444+
test_must_be_empty err &&
445+
test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap
446+
'
447+
421448
test_done

0 commit comments

Comments
 (0)