pack-bitmap-write: learn pack.writeBitmapLookupTable and add tests

Teach Git to provide a way for users to enable/disable bitmap lookup
table extension by providing a config option named 'writeBitmapLookupTable'.
Default is false.

Also add test to verify writting of lookup table.

Mentored-by: Taylor Blau <me@ttaylorr.com>
Co-Mentored-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Co-Authored-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Abhradeep Chakraborty <chakrabortyabhradeep79@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Abhradeep Chakraborty 2022-08-14 16:55:09 +00:00 committed by Junio C Hamano
parent 93eb41e240
commit 76f14b777c
9 changed files with 772 additions and 622 deletions

View File

@ -164,6 +164,13 @@ When writing a multi-pack reachability bitmap, no new namehashes are
computed; instead, any namehashes stored in an existing bitmap are computed; instead, any namehashes stored in an existing bitmap are
permuted into their appropriate location when writing a new bitmap. permuted into their appropriate location when writing a new bitmap.
pack.writeBitmapLookupTable::
When true, Git will include a "lookup table" section in the
bitmap index (if one is written). This table is used to defer
loading individual bitmaps as late as possible. This can be
beneficial in repositories that have relatively large bitmap
indexes. Defaults to false.
pack.writeReverseIndex:: pack.writeReverseIndex::
When true, git will write a corresponding .rev file (see: When true, git will write a corresponding .rev file (see:
link:../technical/pack-format.html[Documentation/technical/pack-format.txt]) link:../technical/pack-format.html[Documentation/technical/pack-format.txt])

View File

@ -87,6 +87,13 @@ static int git_multi_pack_index_write_config(const char *var, const char *value,
opts.flags &= ~MIDX_WRITE_BITMAP_HASH_CACHE; opts.flags &= ~MIDX_WRITE_BITMAP_HASH_CACHE;
} }
if (!strcmp(var, "pack.writebitmaplookuptable")) {
if (git_config_bool(var, value))
opts.flags |= MIDX_WRITE_BITMAP_LOOKUP_TABLE;
else
opts.flags &= ~MIDX_WRITE_BITMAP_LOOKUP_TABLE;
}
/* /*
* We should never make a fall-back call to 'git_default_config', since * We should never make a fall-back call to 'git_default_config', since
* this was already called in 'cmd_multi_pack_index()'. * this was already called in 'cmd_multi_pack_index()'.

View File

@ -3148,6 +3148,14 @@ static int git_pack_config(const char *k, const char *v, void *cb)
else else
write_bitmap_options &= ~BITMAP_OPT_HASH_CACHE; write_bitmap_options &= ~BITMAP_OPT_HASH_CACHE;
} }
if (!strcmp(k, "pack.writebitmaplookuptable")) {
if (git_config_bool(k, v))
write_bitmap_options |= BITMAP_OPT_LOOKUP_TABLE;
else
write_bitmap_options &= ~BITMAP_OPT_LOOKUP_TABLE;
}
if (!strcmp(k, "pack.usebitmaps")) { if (!strcmp(k, "pack.usebitmaps")) {
use_bitmap_index_default = git_config_bool(k, v); use_bitmap_index_default = git_config_bool(k, v);
return 0; return 0;

3
midx.c
View File

@ -1070,6 +1070,9 @@ static int write_midx_bitmap(const char *midx_name,
if (flags & MIDX_WRITE_BITMAP_HASH_CACHE) if (flags & MIDX_WRITE_BITMAP_HASH_CACHE)
options |= BITMAP_OPT_HASH_CACHE; options |= BITMAP_OPT_HASH_CACHE;
if (flags & MIDX_WRITE_BITMAP_LOOKUP_TABLE)
options |= BITMAP_OPT_LOOKUP_TABLE;
/* /*
* Build the MIDX-order index based on pdata.objects (which is already * Build the MIDX-order index based on pdata.objects (which is already
* in MIDX order; c.f., 'midx_pack_order_cmp()' for the definition of * in MIDX order; c.f., 'midx_pack_order_cmp()' for the definition of

1
midx.h
View File

@ -47,6 +47,7 @@ struct multi_pack_index {
#define MIDX_WRITE_REV_INDEX (1 << 1) #define MIDX_WRITE_REV_INDEX (1 << 1)
#define MIDX_WRITE_BITMAP (1 << 2) #define MIDX_WRITE_BITMAP (1 << 2)
#define MIDX_WRITE_BITMAP_HASH_CACHE (1 << 3) #define MIDX_WRITE_BITMAP_HASH_CACHE (1 << 3)
#define MIDX_WRITE_BITMAP_LOOKUP_TABLE (1 << 4)
const unsigned char *get_midx_checksum(struct multi_pack_index *m); const unsigned char *get_midx_checksum(struct multi_pack_index *m);
void get_midx_filename(struct strbuf *out, const char *object_dir); void get_midx_filename(struct strbuf *out, const char *object_dir);

View File

@ -26,22 +26,413 @@ has_any () {
grep -Ff "$1" "$2" grep -Ff "$1" "$2"
} }
setup_bitmap_history test_bitmap_cases () {
writeLookupTable=false
for i in "$@"
do
case "$i" in
"pack.writeBitmapLookupTable") writeLookupTable=true;;
esac
done
test_expect_success 'setup writing bitmaps during repack' ' test_expect_success 'setup test repository' '
git config repack.writeBitmaps true rm -fr * .git &&
' git init &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"'
'
setup_bitmap_history
test_expect_success 'full repack creates bitmaps' ' test_expect_success 'setup writing bitmaps during repack' '
GIT_TRACE2_EVENT="$(pwd)/trace" \ git config repack.writeBitmaps true
'
test_expect_success 'full repack creates bitmaps' '
GIT_TRACE2_EVENT="$(pwd)/trace" \
git repack -ad &&
ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output &&
grep "\"key\":\"num_selected_commits\",\"value\":\"106\"" trace &&
grep "\"key\":\"num_maximal_commits\",\"value\":\"107\"" trace
'
basic_bitmap_tests
test_expect_success 'pack-objects respects --local (non-local loose)' '
git init --bare alt.git &&
echo $(pwd)/alt.git/objects >.git/objects/info/alternates &&
echo content1 >file1 &&
# non-local loose object which is not present in bitmapped pack
altblob=$(GIT_DIR=alt.git git hash-object -w file1) &&
# non-local loose object which is also present in bitmapped pack
git cat-file blob $blob | GIT_DIR=alt.git git hash-object -w --stdin &&
git add file1 &&
test_tick &&
git commit -m commit_file1 &&
echo HEAD | git pack-objects --local --stdout --revs >1.pack &&
git index-pack 1.pack &&
list_packed_objects 1.idx >1.objects &&
printf "%s\n" "$altblob" "$blob" >nonlocal-loose &&
! has_any nonlocal-loose 1.objects
'
test_expect_success 'pack-objects respects --honor-pack-keep (local non-bitmapped pack)' '
echo content2 >file2 &&
blob2=$(git hash-object -w file2) &&
git add file2 &&
test_tick &&
git commit -m commit_file2 &&
printf "%s\n" "$blob2" "$bitmaptip" >keepobjects &&
pack2=$(git pack-objects pack2 <keepobjects) &&
mv pack2-$pack2.* .git/objects/pack/ &&
>.git/objects/pack/pack2-$pack2.keep &&
rm $(objpath $blob2) &&
echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >2a.pack &&
git index-pack 2a.pack &&
list_packed_objects 2a.idx >2a.objects &&
! has_any keepobjects 2a.objects
'
test_expect_success 'pack-objects respects --local (non-local pack)' '
mv .git/objects/pack/pack2-$pack2.* alt.git/objects/pack/ &&
echo HEAD | git pack-objects --local --stdout --revs >2b.pack &&
git index-pack 2b.pack &&
list_packed_objects 2b.idx >2b.objects &&
! has_any keepobjects 2b.objects
'
test_expect_success 'pack-objects respects --honor-pack-keep (local bitmapped pack)' '
ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output &&
packbitmap=$(basename $(cat output) .bitmap) &&
list_packed_objects .git/objects/pack/$packbitmap.idx >packbitmap.objects &&
test_when_finished "rm -f .git/objects/pack/$packbitmap.keep" &&
>.git/objects/pack/$packbitmap.keep &&
echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >3a.pack &&
git index-pack 3a.pack &&
list_packed_objects 3a.idx >3a.objects &&
! has_any packbitmap.objects 3a.objects
'
test_expect_success 'pack-objects respects --local (non-local bitmapped pack)' '
mv .git/objects/pack/$packbitmap.* alt.git/objects/pack/ &&
rm -f .git/objects/pack/multi-pack-index &&
test_when_finished "mv alt.git/objects/pack/$packbitmap.* .git/objects/pack/" &&
echo HEAD | git pack-objects --local --stdout --revs >3b.pack &&
git index-pack 3b.pack &&
list_packed_objects 3b.idx >3b.objects &&
! has_any packbitmap.objects 3b.objects
'
test_expect_success 'pack-objects to file can use bitmap' '
# make sure we still have 1 bitmap index from previous tests
ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output &&
# verify equivalent packs are generated with/without using bitmap index
packasha1=$(git pack-objects --no-use-bitmap-index --all packa </dev/null) &&
packbsha1=$(git pack-objects --use-bitmap-index --all packb </dev/null) &&
list_packed_objects packa-$packasha1.idx >packa.objects &&
list_packed_objects packb-$packbsha1.idx >packb.objects &&
test_cmp packa.objects packb.objects
'
test_expect_success 'full repack, reusing previous bitmaps' '
git repack -ad && git repack -ad &&
ls .git/objects/pack/ | grep bitmap >output && ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output && test_line_count = 1 output
grep "\"key\":\"num_selected_commits\",\"value\":\"106\"" trace && '
grep "\"key\":\"num_maximal_commits\",\"value\":\"107\"" trace
'
basic_bitmap_tests test_expect_success 'fetch (full bitmap)' '
git --git-dir=clone.git fetch origin second:second &&
git rev-parse HEAD >expect &&
git --git-dir=clone.git rev-parse HEAD >actual &&
test_cmp expect actual
'
test_expect_success 'create objects for missing-HAVE tests' '
blob=$(echo "missing have" | git hash-object -w --stdin) &&
tree=$(printf "100644 blob $blob\tfile\n" | git mktree) &&
parent=$(echo parent | git commit-tree $tree) &&
commit=$(echo commit | git commit-tree $tree -p $parent) &&
cat >revs <<-EOF
HEAD
^HEAD^
^$commit
EOF
'
test_expect_success 'pack-objects respects --incremental' '
cat >revs2 <<-EOF &&
HEAD
$commit
EOF
git pack-objects --incremental --stdout --revs <revs2 >4.pack &&
git index-pack 4.pack &&
list_packed_objects 4.idx >4.objects &&
test_line_count = 4 4.objects &&
git rev-list --objects $commit >revlist &&
cut -d" " -f1 revlist |sort >objects &&
test_cmp 4.objects objects
'
test_expect_success 'pack with missing blob' '
rm $(objpath $blob) &&
git pack-objects --stdout --revs <revs >/dev/null
'
test_expect_success 'pack with missing tree' '
rm $(objpath $tree) &&
git pack-objects --stdout --revs <revs >/dev/null
'
test_expect_success 'pack with missing parent' '
rm $(objpath $parent) &&
git pack-objects --stdout --revs <revs >/dev/null
'
test_expect_success JGIT,SHA1 'we can read jgit bitmaps' '
git clone --bare . compat-jgit.git &&
(
cd compat-jgit.git &&
rm -f objects/pack/*.bitmap &&
jgit gc &&
git rev-list --test-bitmap HEAD
)
'
test_expect_success JGIT,SHA1 'jgit can read our bitmaps' '
git clone --bare . compat-us.git &&
(
cd compat-us.git &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
git repack -adb &&
# jgit gc will barf if it does not like our bitmaps
jgit gc
)
'
test_expect_success 'splitting packs does not generate bogus bitmaps' '
test-tool genrandom foo $((1024 * 1024)) >rand &&
git add rand &&
git commit -m "commit with big file" &&
git -c pack.packSizeLimit=500k repack -adb &&
git init --bare no-bitmaps.git &&
git -C no-bitmaps.git fetch .. HEAD
'
test_expect_success 'set up reusable pack' '
rm -f .git/objects/pack/*.keep &&
git repack -adb &&
reusable_pack () {
git for-each-ref --format="%(objectname)" |
git pack-objects --delta-base-offset --revs --stdout "$@"
}
'
test_expect_success 'pack reuse respects --honor-pack-keep' '
test_when_finished "rm -f .git/objects/pack/*.keep" &&
for i in .git/objects/pack/*.pack
do
>${i%.pack}.keep || return 1
done &&
reusable_pack --honor-pack-keep >empty.pack &&
git index-pack empty.pack &&
git show-index <empty.idx >actual &&
test_must_be_empty actual
'
test_expect_success 'pack reuse respects --local' '
mv .git/objects/pack/* alt.git/objects/pack/ &&
test_when_finished "mv alt.git/objects/pack/* .git/objects/pack/" &&
reusable_pack --local >empty.pack &&
git index-pack empty.pack &&
git show-index <empty.idx >actual &&
test_must_be_empty actual
'
test_expect_success 'pack reuse respects --incremental' '
reusable_pack --incremental >empty.pack &&
git index-pack empty.pack &&
git show-index <empty.idx >actual &&
test_must_be_empty actual
'
test_expect_success 'truncated bitmap fails gracefully (ewah)' '
test_config pack.writebitmaphashcache false &&
git repack -ad &&
git rev-list --use-bitmap-index --count --all >expect &&
bitmap=$(ls .git/objects/pack/*.bitmap) &&
test_when_finished "rm -f $bitmap" &&
test_copy_bytes 256 <$bitmap >$bitmap.tmp &&
mv -f $bitmap.tmp $bitmap &&
git rev-list --use-bitmap-index --count --all >actual 2>stderr &&
test_cmp expect actual &&
test_i18ngrep corrupt.ewah.bitmap stderr
'
test_expect_success 'truncated bitmap fails gracefully (cache)' '
git repack -ad &&
git rev-list --use-bitmap-index --count --all >expect &&
bitmap=$(ls .git/objects/pack/*.bitmap) &&
test_when_finished "rm -f $bitmap" &&
test_copy_bytes 512 <$bitmap >$bitmap.tmp &&
mv -f $bitmap.tmp $bitmap &&
git rev-list --use-bitmap-index --count --all >actual 2>stderr &&
test_cmp expect actual &&
test_i18ngrep corrupted.bitmap.index stderr
'
# Create a state of history with these properties:
#
# - refs that allow a client to fetch some new history, while sharing some old
# history with the server; we use branches delta-reuse-old and
# delta-reuse-new here
#
# - the new history contains an object that is stored on the server as a delta
# against a base that is in the old history
#
# - the base object is not immediately reachable from the tip of the old
# history; finding it would involve digging down through history we know the
# other side has
#
# This should result in a state where fetching from old->new would not
# traditionally reuse the on-disk delta (because we'd have to dig to realize
# that the client has it), but we will do so if bitmaps can tell us cheaply
# that the other side has it.
test_expect_success 'set up thin delta-reuse parent' '
# This first commit contains the buried base object.
test-tool genrandom delta 16384 >file &&
git add file &&
git commit -m "delta base" &&
base=$(git rev-parse --verify HEAD:file) &&
# These intermediate commits bury the base back in history.
# This becomes the "old" state.
for i in 1 2 3 4 5
do
echo $i >file &&
git commit -am "intermediate $i" || return 1
done &&
git branch delta-reuse-old &&
# And now our new history has a delta against the buried base. Note
# that this must be smaller than the original file, since pack-objects
# prefers to create deltas from smaller objects to larger.
test-tool genrandom delta 16300 >file &&
git commit -am "delta result" &&
delta=$(git rev-parse --verify HEAD:file) &&
git branch delta-reuse-new &&
# Repack with bitmaps and double check that we have the expected delta
# relationship.
git repack -adb &&
have_delta $delta $base
'
# Now we can sanity-check the non-bitmap behavior (that the server is not able
# to reuse the delta). This isn't strictly something we care about, so this
# test could be scrapped in the future. But it makes sure that the next test is
# actually triggering the feature we want.
#
# Note that our tools for working with on-the-wire "thin" packs are limited. So
# we actually perform the fetch, retain the resulting pack, and inspect the
# result.
test_expect_success 'fetch without bitmaps ignores delta against old base' '
test_config pack.usebitmaps false &&
test_when_finished "rm -rf client.git" &&
git init --bare client.git &&
(
cd client.git &&
git config transfer.unpackLimit 1 &&
git fetch .. delta-reuse-old:delta-reuse-old &&
git fetch .. delta-reuse-new:delta-reuse-new &&
have_delta $delta $ZERO_OID
)
'
# And do the same for the bitmap case, where we do expect to find the delta.
test_expect_success 'fetch with bitmaps can reuse old base' '
test_config pack.usebitmaps true &&
test_when_finished "rm -rf client.git" &&
git init --bare client.git &&
(
cd client.git &&
git config transfer.unpackLimit 1 &&
git fetch .. delta-reuse-old:delta-reuse-old &&
git fetch .. delta-reuse-new:delta-reuse-new &&
have_delta $delta $base
)
'
test_expect_success 'pack.preferBitmapTips' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
# create enough commits that not all are receive bitmap
# coverage even if they are all at the tip of some reference.
test_commit_bulk --message="%s" 103 &&
git rev-list HEAD >commits.raw &&
sort <commits.raw >commits &&
git log --format="create refs/tags/%s %H" HEAD >refs &&
git update-ref --stdin <refs &&
git repack -adb &&
test-tool bitmap list-commits | sort >bitmaps &&
# remember which commits did not receive bitmaps
comm -13 bitmaps commits >before &&
test_file_not_empty before &&
# mark the commits which did not receive bitmaps as preferred,
# and generate the bitmap again
perl -pe "s{^}{create refs/tags/include/$. }" <before |
git update-ref --stdin &&
git -c pack.preferBitmapTips=refs/tags/include repack -adb &&
# finally, check that the commit(s) without bitmap coverage
# are not the same ones as before
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >after &&
! test_cmp before after
)
'
test_expect_success 'complains about multiple pack bitmaps' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit base &&
git repack -adb &&
bitmap="$(ls .git/objects/pack/pack-*.bitmap)" &&
mv "$bitmap" "$bitmap.bak" &&
test_commit other &&
git repack -ab &&
mv "$bitmap.bak" "$bitmap" &&
find .git/objects/pack -type f -name "*.pack" >packs &&
find .git/objects/pack -type f -name "*.bitmap" >bitmaps &&
test_line_count = 2 packs &&
test_line_count = 2 bitmaps &&
git rev-list --use-bitmap-index HEAD 2>err &&
grep "ignoring extra bitmap file" err
)
'
}
test_bitmap_cases
test_expect_success 'incremental repack fails when bitmaps are requested' ' test_expect_success 'incremental repack fails when bitmaps are requested' '
test_commit more-1 && test_commit more-1 &&
@ -54,375 +445,12 @@ test_expect_success 'incremental repack can disable bitmaps' '
git repack -d --no-write-bitmap-index git repack -d --no-write-bitmap-index
' '
test_expect_success 'pack-objects respects --local (non-local loose)' ' test_bitmap_cases "pack.writeBitmapLookupTable"
git init --bare alt.git &&
echo $(pwd)/alt.git/objects >.git/objects/info/alternates &&
echo content1 >file1 &&
# non-local loose object which is not present in bitmapped pack
altblob=$(GIT_DIR=alt.git git hash-object -w file1) &&
# non-local loose object which is also present in bitmapped pack
git cat-file blob $blob | GIT_DIR=alt.git git hash-object -w --stdin &&
git add file1 &&
test_tick &&
git commit -m commit_file1 &&
echo HEAD | git pack-objects --local --stdout --revs >1.pack &&
git index-pack 1.pack &&
list_packed_objects 1.idx >1.objects &&
printf "%s\n" "$altblob" "$blob" >nonlocal-loose &&
! has_any nonlocal-loose 1.objects
'
test_expect_success 'pack-objects respects --honor-pack-keep (local non-bitmapped pack)' ' test_expect_success 'verify writing bitmap lookup table when enabled' '
echo content2 >file2 && GIT_TRACE2_EVENT="$(pwd)/trace2" \
blob2=$(git hash-object -w file2) && git repack -ad &&
git add file2 && grep "\"label\":\"writing_lookup_table\"" trace2
test_tick &&
git commit -m commit_file2 &&
printf "%s\n" "$blob2" "$bitmaptip" >keepobjects &&
pack2=$(git pack-objects pack2 <keepobjects) &&
mv pack2-$pack2.* .git/objects/pack/ &&
>.git/objects/pack/pack2-$pack2.keep &&
rm $(objpath $blob2) &&
echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >2a.pack &&
git index-pack 2a.pack &&
list_packed_objects 2a.idx >2a.objects &&
! has_any keepobjects 2a.objects
'
test_expect_success 'pack-objects respects --local (non-local pack)' '
mv .git/objects/pack/pack2-$pack2.* alt.git/objects/pack/ &&
echo HEAD | git pack-objects --local --stdout --revs >2b.pack &&
git index-pack 2b.pack &&
list_packed_objects 2b.idx >2b.objects &&
! has_any keepobjects 2b.objects
'
test_expect_success 'pack-objects respects --honor-pack-keep (local bitmapped pack)' '
ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output &&
packbitmap=$(basename $(cat output) .bitmap) &&
list_packed_objects .git/objects/pack/$packbitmap.idx >packbitmap.objects &&
test_when_finished "rm -f .git/objects/pack/$packbitmap.keep" &&
>.git/objects/pack/$packbitmap.keep &&
echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >3a.pack &&
git index-pack 3a.pack &&
list_packed_objects 3a.idx >3a.objects &&
! has_any packbitmap.objects 3a.objects
'
test_expect_success 'pack-objects respects --local (non-local bitmapped pack)' '
mv .git/objects/pack/$packbitmap.* alt.git/objects/pack/ &&
rm -f .git/objects/pack/multi-pack-index &&
test_when_finished "mv alt.git/objects/pack/$packbitmap.* .git/objects/pack/" &&
echo HEAD | git pack-objects --local --stdout --revs >3b.pack &&
git index-pack 3b.pack &&
list_packed_objects 3b.idx >3b.objects &&
! has_any packbitmap.objects 3b.objects
'
test_expect_success 'pack-objects to file can use bitmap' '
# make sure we still have 1 bitmap index from previous tests
ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output &&
# verify equivalent packs are generated with/without using bitmap index
packasha1=$(git pack-objects --no-use-bitmap-index --all packa </dev/null) &&
packbsha1=$(git pack-objects --use-bitmap-index --all packb </dev/null) &&
list_packed_objects packa-$packasha1.idx >packa.objects &&
list_packed_objects packb-$packbsha1.idx >packb.objects &&
test_cmp packa.objects packb.objects
'
test_expect_success 'full repack, reusing previous bitmaps' '
git repack -ad &&
ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output
'
test_expect_success 'fetch (full bitmap)' '
git --git-dir=clone.git fetch origin second:second &&
git rev-parse HEAD >expect &&
git --git-dir=clone.git rev-parse HEAD >actual &&
test_cmp expect actual
'
test_expect_success 'create objects for missing-HAVE tests' '
blob=$(echo "missing have" | git hash-object -w --stdin) &&
tree=$(printf "100644 blob $blob\tfile\n" | git mktree) &&
parent=$(echo parent | git commit-tree $tree) &&
commit=$(echo commit | git commit-tree $tree -p $parent) &&
cat >revs <<-EOF
HEAD
^HEAD^
^$commit
EOF
'
test_expect_success 'pack-objects respects --incremental' '
cat >revs2 <<-EOF &&
HEAD
$commit
EOF
git pack-objects --incremental --stdout --revs <revs2 >4.pack &&
git index-pack 4.pack &&
list_packed_objects 4.idx >4.objects &&
test_line_count = 4 4.objects &&
git rev-list --objects $commit >revlist &&
cut -d" " -f1 revlist |sort >objects &&
test_cmp 4.objects objects
'
test_expect_success 'pack with missing blob' '
rm $(objpath $blob) &&
git pack-objects --stdout --revs <revs >/dev/null
'
test_expect_success 'pack with missing tree' '
rm $(objpath $tree) &&
git pack-objects --stdout --revs <revs >/dev/null
'
test_expect_success 'pack with missing parent' '
rm $(objpath $parent) &&
git pack-objects --stdout --revs <revs >/dev/null
'
test_expect_success JGIT,SHA1 'we can read jgit bitmaps' '
git clone --bare . compat-jgit.git &&
(
cd compat-jgit.git &&
rm -f objects/pack/*.bitmap &&
jgit gc &&
git rev-list --test-bitmap HEAD
)
'
test_expect_success JGIT,SHA1 'jgit can read our bitmaps' '
git clone --bare . compat-us.git &&
(
cd compat-us.git &&
git repack -adb &&
# jgit gc will barf if it does not like our bitmaps
jgit gc
)
'
test_expect_success 'splitting packs does not generate bogus bitmaps' '
test-tool genrandom foo $((1024 * 1024)) >rand &&
git add rand &&
git commit -m "commit with big file" &&
git -c pack.packSizeLimit=500k repack -adb &&
git init --bare no-bitmaps.git &&
git -C no-bitmaps.git fetch .. HEAD
'
test_expect_success 'set up reusable pack' '
rm -f .git/objects/pack/*.keep &&
git repack -adb &&
reusable_pack () {
git for-each-ref --format="%(objectname)" |
git pack-objects --delta-base-offset --revs --stdout "$@"
}
'
test_expect_success 'pack reuse respects --honor-pack-keep' '
test_when_finished "rm -f .git/objects/pack/*.keep" &&
for i in .git/objects/pack/*.pack
do
>${i%.pack}.keep || return 1
done &&
reusable_pack --honor-pack-keep >empty.pack &&
git index-pack empty.pack &&
git show-index <empty.idx >actual &&
test_must_be_empty actual
'
test_expect_success 'pack reuse respects --local' '
mv .git/objects/pack/* alt.git/objects/pack/ &&
test_when_finished "mv alt.git/objects/pack/* .git/objects/pack/" &&
reusable_pack --local >empty.pack &&
git index-pack empty.pack &&
git show-index <empty.idx >actual &&
test_must_be_empty actual
'
test_expect_success 'pack reuse respects --incremental' '
reusable_pack --incremental >empty.pack &&
git index-pack empty.pack &&
git show-index <empty.idx >actual &&
test_must_be_empty actual
'
test_expect_success 'truncated bitmap fails gracefully (ewah)' '
test_config pack.writebitmaphashcache false &&
git repack -ad &&
git rev-list --use-bitmap-index --count --all >expect &&
bitmap=$(ls .git/objects/pack/*.bitmap) &&
test_when_finished "rm -f $bitmap" &&
test_copy_bytes 256 <$bitmap >$bitmap.tmp &&
mv -f $bitmap.tmp $bitmap &&
git rev-list --use-bitmap-index --count --all >actual 2>stderr &&
test_cmp expect actual &&
test_i18ngrep corrupt.ewah.bitmap stderr
'
test_expect_success 'truncated bitmap fails gracefully (cache)' '
git repack -ad &&
git rev-list --use-bitmap-index --count --all >expect &&
bitmap=$(ls .git/objects/pack/*.bitmap) &&
test_when_finished "rm -f $bitmap" &&
test_copy_bytes 512 <$bitmap >$bitmap.tmp &&
mv -f $bitmap.tmp $bitmap &&
git rev-list --use-bitmap-index --count --all >actual 2>stderr &&
test_cmp expect actual &&
test_i18ngrep corrupted.bitmap.index stderr
'
# Create a state of history with these properties:
#
# - refs that allow a client to fetch some new history, while sharing some old
# history with the server; we use branches delta-reuse-old and
# delta-reuse-new here
#
# - the new history contains an object that is stored on the server as a delta
# against a base that is in the old history
#
# - the base object is not immediately reachable from the tip of the old
# history; finding it would involve digging down through history we know the
# other side has
#
# This should result in a state where fetching from old->new would not
# traditionally reuse the on-disk delta (because we'd have to dig to realize
# that the client has it), but we will do so if bitmaps can tell us cheaply
# that the other side has it.
test_expect_success 'set up thin delta-reuse parent' '
# This first commit contains the buried base object.
test-tool genrandom delta 16384 >file &&
git add file &&
git commit -m "delta base" &&
base=$(git rev-parse --verify HEAD:file) &&
# These intermediate commits bury the base back in history.
# This becomes the "old" state.
for i in 1 2 3 4 5
do
echo $i >file &&
git commit -am "intermediate $i" || return 1
done &&
git branch delta-reuse-old &&
# And now our new history has a delta against the buried base. Note
# that this must be smaller than the original file, since pack-objects
# prefers to create deltas from smaller objects to larger.
test-tool genrandom delta 16300 >file &&
git commit -am "delta result" &&
delta=$(git rev-parse --verify HEAD:file) &&
git branch delta-reuse-new &&
# Repack with bitmaps and double check that we have the expected delta
# relationship.
git repack -adb &&
have_delta $delta $base
'
# Now we can sanity-check the non-bitmap behavior (that the server is not able
# to reuse the delta). This isn't strictly something we care about, so this
# test could be scrapped in the future. But it makes sure that the next test is
# actually triggering the feature we want.
#
# Note that our tools for working with on-the-wire "thin" packs are limited. So
# we actually perform the fetch, retain the resulting pack, and inspect the
# result.
test_expect_success 'fetch without bitmaps ignores delta against old base' '
test_config pack.usebitmaps false &&
test_when_finished "rm -rf client.git" &&
git init --bare client.git &&
(
cd client.git &&
git config transfer.unpackLimit 1 &&
git fetch .. delta-reuse-old:delta-reuse-old &&
git fetch .. delta-reuse-new:delta-reuse-new &&
have_delta $delta $ZERO_OID
)
'
# And do the same for the bitmap case, where we do expect to find the delta.
test_expect_success 'fetch with bitmaps can reuse old base' '
test_config pack.usebitmaps true &&
test_when_finished "rm -rf client.git" &&
git init --bare client.git &&
(
cd client.git &&
git config transfer.unpackLimit 1 &&
git fetch .. delta-reuse-old:delta-reuse-old &&
git fetch .. delta-reuse-new:delta-reuse-new &&
have_delta $delta $base
)
'
test_expect_success 'pack.preferBitmapTips' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
# create enough commits that not all are receive bitmap
# coverage even if they are all at the tip of some reference.
test_commit_bulk --message="%s" 103 &&
git rev-list HEAD >commits.raw &&
sort <commits.raw >commits &&
git log --format="create refs/tags/%s %H" HEAD >refs &&
git update-ref --stdin <refs &&
git repack -adb &&
test-tool bitmap list-commits | sort >bitmaps &&
# remember which commits did not receive bitmaps
comm -13 bitmaps commits >before &&
test_file_not_empty before &&
# mark the commits which did not receive bitmaps as preferred,
# and generate the bitmap again
perl -pe "s{^}{create refs/tags/include/$. }" <before |
git update-ref --stdin &&
git -c pack.preferBitmapTips=refs/tags/include repack -adb &&
# finally, check that the commit(s) without bitmap coverage
# are not the same ones as before
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >after &&
! test_cmp before after
)
'
test_expect_success 'complains about multiple pack bitmaps' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
test_commit base &&
git repack -adb &&
bitmap="$(ls .git/objects/pack/pack-*.bitmap)" &&
mv "$bitmap" "$bitmap.bak" &&
test_commit other &&
git repack -ab &&
mv "$bitmap.bak" "$bitmap" &&
find .git/objects/pack -type f -name "*.pack" >packs &&
find .git/objects/pack -type f -name "*.bitmap" >bitmaps &&
test_line_count = 2 packs &&
test_line_count = 2 bitmaps &&
git rev-list --use-bitmap-index HEAD 2>err &&
grep "ignoring extra bitmap file" err
)
' '
test_done test_done

View File

@ -17,23 +17,40 @@ test_description='check bitmap operation with shallow repositories'
# the tree for A. But in a shallow one, we've grafted away # the tree for A. But in a shallow one, we've grafted away
# A, and fetching A to B requires that the other side send # A, and fetching A to B requires that the other side send
# us the tree for file=1. # us the tree for file=1.
test_expect_success 'setup shallow repo' ' test_shallow_bitmaps () {
echo 1 >file && writeLookupTable=false
git add file &&
git commit -m orig &&
echo 2 >file &&
git commit -a -m update &&
git clone --no-local --bare --depth=1 . shallow.git &&
echo 1 >file &&
git commit -a -m repeat
'
test_expect_success 'turn on bitmaps in the parent' ' for i in "$@"
git repack -adb do
' case $i in
"pack.writeBitmapLookupTable") writeLookupTable=true;;
esac
done
test_expect_success 'shallow fetch from bitmapped repo' ' test_expect_success 'setup shallow repo' '
(cd shallow.git && git fetch) rm -rf * .git &&
' git init &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
echo 1 >file &&
git add file &&
git commit -m orig &&
echo 2 >file &&
git commit -a -m update &&
git clone --no-local --bare --depth=1 . shallow.git &&
echo 1 >file &&
git commit -a -m repeat
'
test_expect_success 'turn on bitmaps in the parent' '
git repack -adb
'
test_expect_success 'shallow fetch from bitmapped repo' '
(cd shallow.git && git fetch)
'
}
test_shallow_bitmaps
test_shallow_bitmaps "pack.writeBitmapLookupTable"
test_done test_done

View File

@ -15,17 +15,24 @@ GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
sane_unset GIT_TEST_MIDX_WRITE_REV sane_unset GIT_TEST_MIDX_WRITE_REV
sane_unset GIT_TEST_MIDX_READ_RIDX sane_unset GIT_TEST_MIDX_READ_RIDX
midx_bitmap_core
bitmap_reuse_tests() { bitmap_reuse_tests() {
from=$1 from=$1
to=$2 to=$2
writeLookupTable=false
for i in $3-${$#}
do
case $i in
"pack.writeBitmapLookupTable") writeLookupTable=true;;
esac
done
test_expect_success "setup pack reuse tests ($from -> $to)" ' test_expect_success "setup pack reuse tests ($from -> $to)" '
rm -fr repo && rm -fr repo &&
git init repo && git init repo &&
( (
cd repo && cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit_bulk 16 && test_commit_bulk 16 &&
git tag old-tip && git tag old-tip &&
@ -43,6 +50,7 @@ bitmap_reuse_tests() {
test_expect_success "build bitmap from existing ($from -> $to)" ' test_expect_success "build bitmap from existing ($from -> $to)" '
( (
cd repo && cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit_bulk --id=further 16 && test_commit_bulk --id=further 16 &&
git tag new-tip && git tag new-tip &&
@ -59,6 +67,7 @@ bitmap_reuse_tests() {
test_expect_success "verify resulting bitmaps ($from -> $to)" ' test_expect_success "verify resulting bitmaps ($from -> $to)" '
( (
cd repo && cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
git for-each-ref && git for-each-ref &&
git rev-list --test-bitmap refs/tags/old-tip && git rev-list --test-bitmap refs/tags/old-tip &&
git rev-list --test-bitmap refs/tags/new-tip git rev-list --test-bitmap refs/tags/new-tip
@ -66,244 +75,294 @@ bitmap_reuse_tests() {
' '
} }
bitmap_reuse_tests 'pack' 'MIDX' test_midx_bitmap_cases () {
bitmap_reuse_tests 'MIDX' 'pack' writeLookupTable=false
bitmap_reuse_tests 'MIDX' 'MIDX' writeBitmapLookupTable=
test_expect_success 'missing object closure fails gracefully' ' for i in "$@"
rm -fr repo && do
git init repo && case $i in
test_when_finished "rm -fr repo" && "pack.writeBitmapLookupTable")
( writeLookupTable=true
cd repo && writeBitmapLookupTable="$i"
;;
esac
done
test_commit loose && test_expect_success 'setup test_repository' '
test_commit packed && rm -rf * .git &&
git init &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"'
'
# Do not pass "--revs"; we want a pack without the "loose" midx_bitmap_core
# commit.
git pack-objects $objdir/pack/pack <<-EOF &&
$(git rev-parse packed)
EOF
test_must_fail git multi-pack-index write --bitmap 2>err && bitmap_reuse_tests 'pack' 'MIDX' "$writeBitmapLookupTable"
grep "doesn.t have full closure" err && bitmap_reuse_tests 'MIDX' 'pack' "$writeBitmapLookupTable"
test_path_is_missing $midx bitmap_reuse_tests 'MIDX' 'MIDX' "$writeBitmapLookupTable"
)
'
midx_bitmap_partial_tests
test_expect_success 'removing a MIDX clears stale bitmaps' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
test_commit base &&
git repack &&
git multi-pack-index write --bitmap &&
# Write a MIDX and bitmap; remove the MIDX but leave the bitmap.
stale_bitmap=$midx-$(midx_checksum $objdir).bitmap &&
rm $midx &&
# Then write a new MIDX.
test_commit new &&
git repack &&
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test_path_is_missing $stale_bitmap
)
'
test_expect_success 'pack.preferBitmapTips' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
test_commit_bulk --message="%s" 103 &&
git log --format="%H" >commits.raw &&
sort <commits.raw >commits &&
git log --format="create refs/tags/%s %H" HEAD >refs &&
git update-ref --stdin <refs &&
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >before &&
test_line_count = 1 before &&
perl -ne "printf(\"create refs/tags/include/%d \", $.); print" \
<before | git update-ref --stdin &&
rm -fr $midx-$(midx_checksum $objdir).bitmap &&
rm -fr $midx &&
git -c pack.preferBitmapTips=refs/tags/include \
multi-pack-index write --bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >after &&
! test_cmp before after
)
'
test_expect_success 'writing a bitmap with --refs-snapshot' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
test_commit one &&
test_commit two &&
git rev-parse one >snapshot &&
git repack -ad &&
# First, write a MIDX which see both refs/tags/one and
# refs/tags/two (causing both of those commits to receive
# bitmaps).
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
grep "$(git rev-parse one)" bitmaps &&
grep "$(git rev-parse two)" bitmaps &&
rm -fr $midx-$(midx_checksum $objdir).bitmap &&
rm -fr $midx &&
# Then again, but with a refs snapshot which only sees
# refs/tags/one.
git multi-pack-index write --bitmap --refs-snapshot=snapshot &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
grep "$(git rev-parse one)" bitmaps &&
! grep "$(git rev-parse two)" bitmaps
)
'
test_expect_success 'write a bitmap with --refs-snapshot (preferred tips)' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
test_commit_bulk --message="%s" 103 &&
git log --format="%H" >commits.raw &&
sort <commits.raw >commits &&
git log --format="create refs/tags/%s %H" HEAD >refs &&
git update-ref --stdin <refs &&
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >before &&
test_line_count = 1 before &&
test_expect_success 'missing object closure fails gracefully' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
( (
grep -vf before commits.raw && cd repo &&
# mark missing commits as preferred git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
sed "s/^/+/" before
) >snapshot &&
rm -fr $midx-$(midx_checksum $objdir).bitmap && test_commit loose &&
rm -fr $midx && test_commit packed &&
git multi-pack-index write --bitmap --refs-snapshot=snapshot && # Do not pass "--revs"; we want a pack without the "loose"
test-tool bitmap list-commits | sort >bitmaps && # commit.
comm -13 bitmaps commits >after && git pack-objects $objdir/pack/pack <<-EOF &&
$(git rev-parse packed)
EOF
! test_cmp before after test_must_fail git multi-pack-index write --bitmap 2>err &&
) grep "doesn.t have full closure" err &&
' test_path_is_missing $midx
)
'
test_expect_success 'hash-cache values are propagated from pack bitmaps' ' midx_bitmap_partial_tests
test_expect_success 'removing a MIDX clears stale bitmaps' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit base &&
git repack &&
git multi-pack-index write --bitmap &&
# Write a MIDX and bitmap; remove the MIDX but leave the bitmap.
stale_bitmap=$midx-$(midx_checksum $objdir).bitmap &&
rm $midx &&
# Then write a new MIDX.
test_commit new &&
git repack &&
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test_path_is_missing $stale_bitmap
)
'
test_expect_success 'pack.preferBitmapTips' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit_bulk --message="%s" 103 &&
git log --format="%H" >commits.raw &&
sort <commits.raw >commits &&
git log --format="create refs/tags/%s %H" HEAD >refs &&
git update-ref --stdin <refs &&
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >before &&
test_line_count = 1 before &&
perl -ne "printf(\"create refs/tags/include/%d \", $.); print" \
<before | git update-ref --stdin &&
rm -fr $midx-$(midx_checksum $objdir).bitmap &&
rm -fr $midx &&
git -c pack.preferBitmapTips=refs/tags/include \
multi-pack-index write --bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >after &&
! test_cmp before after
)
'
test_expect_success 'writing a bitmap with --refs-snapshot' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit one &&
test_commit two &&
git rev-parse one >snapshot &&
git repack -ad &&
# First, write a MIDX which see both refs/tags/one and
# refs/tags/two (causing both of those commits to receive
# bitmaps).
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
grep "$(git rev-parse one)" bitmaps &&
grep "$(git rev-parse two)" bitmaps &&
rm -fr $midx-$(midx_checksum $objdir).bitmap &&
rm -fr $midx &&
# Then again, but with a refs snapshot which only sees
# refs/tags/one.
git multi-pack-index write --bitmap --refs-snapshot=snapshot &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
grep "$(git rev-parse one)" bitmaps &&
! grep "$(git rev-parse two)" bitmaps
)
'
test_expect_success 'write a bitmap with --refs-snapshot (preferred tips)' '
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit_bulk --message="%s" 103 &&
git log --format="%H" >commits.raw &&
sort <commits.raw >commits &&
git log --format="create refs/tags/%s %H" HEAD >refs &&
git update-ref --stdin <refs &&
git multi-pack-index write --bitmap &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >before &&
test_line_count = 1 before &&
(
grep -vf before commits.raw &&
# mark missing commits as preferred
sed "s/^/+/" before
) >snapshot &&
rm -fr $midx-$(midx_checksum $objdir).bitmap &&
rm -fr $midx &&
git multi-pack-index write --bitmap --refs-snapshot=snapshot &&
test-tool bitmap list-commits | sort >bitmaps &&
comm -13 bitmaps commits >after &&
! test_cmp before after
)
'
test_expect_success 'hash-cache values are propagated from pack bitmaps' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit base &&
test_commit base2 &&
git repack -adb &&
test-tool bitmap dump-hashes >pack.raw &&
test_file_not_empty pack.raw &&
sort pack.raw >pack.hashes &&
test_commit new &&
git repack &&
git multi-pack-index write --bitmap &&
test-tool bitmap dump-hashes >midx.raw &&
sort midx.raw >midx.hashes &&
# ensure that every namehash in the pack bitmap can be found in
# the midx bitmap (i.e., that there are no oid-namehash pairs
# unique to the pack bitmap).
comm -23 pack.hashes midx.hashes >dropped.hashes &&
test_must_be_empty dropped.hashes
)
'
test_expect_success 'no .bitmap is written without any objects' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
empty="$(git pack-objects $objdir/pack/pack </dev/null)" &&
cat >packs <<-EOF &&
pack-$empty.idx
EOF
git multi-pack-index write --bitmap --stdin-packs \
<packs 2>err &&
grep "bitmap without any objects" err &&
test_path_is_file $midx &&
test_path_is_missing $midx-$(midx_checksum $objdir).bitmap
)
'
test_expect_success 'graceful fallback when missing reverse index' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
test_commit base &&
# write a pack and MIDX bitmap containing base
git repack -adb &&
git multi-pack-index write --bitmap &&
GIT_TEST_MIDX_READ_RIDX=0 \
git rev-list --use-bitmap-index HEAD 2>err &&
! grep "ignoring extra bitmap file" err
)
'
}
test_midx_bitmap_cases
test_midx_bitmap_cases "pack.writeBitmapLookupTable"
test_expect_success 'multi-pack-index write writes lookup table if enabled' '
rm -fr repo && rm -fr repo &&
git init repo && git init repo &&
test_when_finished "rm -fr repo" && test_when_finished "rm -fr repo" &&
( (
cd repo && cd repo &&
test_commit base && test_commit base &&
test_commit base2 && git config pack.writeBitmapLookupTable true &&
git repack -adb && git repack -ad &&
GIT_TRACE2_EVENT="$(pwd)/trace" \
test-tool bitmap dump-hashes >pack.raw && git multi-pack-index write --bitmap &&
test_file_not_empty pack.raw && grep "\"label\":\"writing_lookup_table\"" trace
sort pack.raw >pack.hashes &&
test_commit new &&
git repack &&
git multi-pack-index write --bitmap &&
test-tool bitmap dump-hashes >midx.raw &&
sort midx.raw >midx.hashes &&
# ensure that every namehash in the pack bitmap can be found in
# the midx bitmap (i.e., that there are no oid-namehash pairs
# unique to the pack bitmap).
comm -23 pack.hashes midx.hashes >dropped.hashes &&
test_must_be_empty dropped.hashes
)
'
test_expect_success 'no .bitmap is written without any objects' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
empty="$(git pack-objects $objdir/pack/pack </dev/null)" &&
cat >packs <<-EOF &&
pack-$empty.idx
EOF
git multi-pack-index write --bitmap --stdin-packs \
<packs 2>err &&
grep "bitmap without any objects" err &&
test_path_is_file $midx &&
test_path_is_missing $midx-$(midx_checksum $objdir).bitmap
)
'
test_expect_success 'graceful fallback when missing reverse index' '
rm -fr repo &&
git init repo &&
test_when_finished "rm -fr repo" &&
(
cd repo &&
test_commit base &&
# write a pack and MIDX bitmap containing base
git repack -adb &&
git multi-pack-index write --bitmap &&
GIT_TEST_MIDX_READ_RIDX=0 \
git rev-list --use-bitmap-index HEAD 2>err &&
! grep "ignoring extra bitmap file" err
) )
' '

View File

@ -17,7 +17,27 @@ GIT_TEST_MIDX_READ_RIDX=0
export GIT_TEST_MIDX_WRITE_REV export GIT_TEST_MIDX_WRITE_REV
export GIT_TEST_MIDX_READ_RIDX export GIT_TEST_MIDX_READ_RIDX
midx_bitmap_core rev test_midx_bitmap_rev () {
midx_bitmap_partial_tests rev writeLookupTable=false
for i in "$@"
do
case $i in
"pack.writeBitmapLookupTable") writeLookupTable=true;;
esac
done
test_expect_success 'setup bitmap config' '
rm -rf * .git &&
git init &&
git config pack.writeBitmapLookupTable '"$writeLookupTable"'
'
midx_bitmap_core rev
midx_bitmap_partial_tests rev
}
test_midx_bitmap_rev
test_midx_bitmap_rev "pack.writeBitmapLookupTable"
test_done test_done