diff options
Diffstat (limited to 't')
| -rwxr-xr-x | t/t5331-pack-objects-stdin.sh | 122 | ||||
| -rwxr-xr-x | t/t7704-repack-cruft.sh | 145 |
2 files changed, 266 insertions, 1 deletions
diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh index b48c0cbe8f..4a8df5a389 100755 --- a/t/t5331-pack-objects-stdin.sh +++ b/t/t5331-pack-objects-stdin.sh @@ -64,7 +64,7 @@ test_expect_success '--stdin-packs is incompatible with --filter' ' cd stdin-packs && test_must_fail git pack-objects --stdin-packs --stdout \ --filter=blob:none </dev/null 2>err && - test_grep "cannot use --filter with --stdin-packs" err + test_grep "options .--stdin-packs. and .--filter. cannot be used together" err ) ' @@ -236,4 +236,124 @@ test_expect_success 'pack-objects --stdin with packfiles from main and alternate test_cmp expected-objects actual-objects ' +objdir=.git/objects +packdir=$objdir/pack + +objects_in_packs () { + for p in "$@" + do + git show-index <"$packdir/pack-$p.idx" || return 1 + done >objects.raw && + + cut -d' ' -f2 objects.raw | sort && + rm -f objects.raw +} + +test_expect_success '--stdin-packs=follow walks into unknown packs' ' + test_when_finished "rm -fr repo" && + + git init repo && + ( + cd repo && + + for c in A B C D + do + test_commit "$c" || return 1 + done && + + A="$(echo A | git pack-objects --revs $packdir/pack)" && + B="$(echo A..B | git pack-objects --revs $packdir/pack)" && + C="$(echo B..C | git pack-objects --revs $packdir/pack)" && + D="$(echo C..D | git pack-objects --revs $packdir/pack)" && + test_commit E && + + git prune-packed && + + cat >in <<-EOF && + pack-$B.pack + ^pack-$C.pack + pack-$D.pack + EOF + + # With just --stdin-packs, pack "A" is unknown to us, so + # only objects from packs "B" and "D" are included in + # the output pack. + P=$(git pack-objects --stdin-packs $packdir/pack <in) && + objects_in_packs $B $D >expect && + objects_in_packs $P >actual && + test_cmp expect actual && + + # But with --stdin-packs=follow, objects from both + # included packs reach objects from the unknown pack, so + # objects from pack "A" is included in the output pack + # in addition to the above. + P=$(git pack-objects --stdin-packs=follow $packdir/pack <in) && + objects_in_packs $A $B $D >expect && + objects_in_packs $P >actual && + test_cmp expect actual && + + # And with --unpacked, we will pick up objects from unknown + # packs that are reachable from loose objects. Loose object E + # reaches objects in pack A, but there are three excluded packs + # in between. + # + # The resulting pack should include objects reachable from E + # that are not present in packs B, C, or D, along with those + # present in pack A. + cat >in <<-EOF && + ^pack-$B.pack + ^pack-$C.pack + ^pack-$D.pack + EOF + + P=$(git pack-objects --stdin-packs=follow --unpacked \ + $packdir/pack <in) && + + { + objects_in_packs $A && + git rev-list --objects --no-object-names D..E + }>expect.raw && + sort expect.raw >expect && + objects_in_packs $P >actual && + test_cmp expect actual + ) +' + +stdin_packs__follow_with_only () { + rm -fr stdin_packs__follow_with_only && + git init stdin_packs__follow_with_only && + ( + cd stdin_packs__follow_with_only && + + test_commit A && + test_commit B && + + git rev-parse "$@" >B.objects && + + echo A | git pack-objects --revs $packdir/pack && + B="$(git pack-objects $packdir/pack <B.objects)" && + + git cat-file --batch-check="%(objectname)" --batch-all-objects >objs && + for obj in $(cat objs) + do + rm -f $objdir/$(test_oid_to_path $obj) || return 1 + done && + + ( cd $packdir && ls pack-*.pack ) >in && + git pack-objects --stdin-packs=follow --stdout >/dev/null <in + ) +} + +test_expect_success '--stdin-packs=follow tolerates missing blobs' ' + stdin_packs__follow_with_only HEAD HEAD^{tree} +' + +test_expect_success '--stdin-packs=follow tolerates missing trees' ' + stdin_packs__follow_with_only HEAD HEAD:B.t +' + +test_expect_success '--stdin-packs=follow tolerates missing commits' ' + stdin_packs__follow_with_only HEAD HEAD^{tree} +' + test_done diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh index 8aebfb45f5..aa2e2e6ad8 100755 --- a/t/t7704-repack-cruft.sh +++ b/t/t7704-repack-cruft.sh @@ -724,4 +724,149 @@ test_expect_success 'cruft repack respects --quiet' ' ) ' +setup_cruft_exclude_tests() { + git init "$1" && + ( + cd "$1" && + + git config repack.midxMustContainCruft false && + + test_commit one && + + test_commit --no-tag two && + two="$(git rev-parse HEAD)" && + test_commit --no-tag three && + three="$(git rev-parse HEAD)" && + git reset --hard one && + git reflog expire --all --expire=all && + + GIT_TEST_MULTI_PACK_INDEX=0 git repack --cruft -d && + + git merge $two && + test_commit four + ) +} + +test_expect_success 'repack --write-midx excludes cruft where possible' ' + setup_cruft_exclude_tests exclude-cruft-when-possible && + ( + cd exclude-cruft-when-possible && + + GIT_TEST_MULTI_PACK_INDEX=0 \ + git repack -d --geometric=2 --write-midx --write-bitmap-index && + + test-tool read-midx --show-objects $objdir >midx && + cruft="$(ls $packdir/*.mtimes)" && + test_grep ! "$(basename "$cruft" .mtimes).idx" midx && + + git rev-list --all --objects --no-object-names >reachable.raw && + sort reachable.raw >reachable.objects && + awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && + + test_cmp reachable.objects midx.objects + ) +' + +test_expect_success 'repack --write-midx includes cruft when instructed' ' + setup_cruft_exclude_tests exclude-cruft-when-instructed && + ( + cd exclude-cruft-when-instructed && + + GIT_TEST_MULTI_PACK_INDEX=0 \ + git -c repack.midxMustContainCruft=true repack \ + -d --geometric=2 --write-midx --write-bitmap-index && + + test-tool read-midx --show-objects $objdir >midx && + cruft="$(ls $packdir/*.mtimes)" && + test_grep "$(basename "$cruft" .mtimes).idx" midx && + + git cat-file --batch-check="%(objectname)" --batch-all-objects \ + >all.objects && + awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && + + test_cmp all.objects midx.objects + ) +' + +test_expect_success 'repack --write-midx includes cruft when necessary' ' + setup_cruft_exclude_tests exclude-cruft-when-necessary && + ( + cd exclude-cruft-when-necessary && + + test_path_is_file $(ls $packdir/pack-*.mtimes) && + ( cd $packdir && ls pack-*.idx ) | sort >packs.all && + git multi-pack-index write --stdin-packs --bitmap <packs.all && + + test_commit five && + GIT_TEST_MULTI_PACK_INDEX=0 \ + git repack -d --geometric=2 --write-midx --write-bitmap-index && + + test-tool read-midx --show-objects $objdir >midx && + awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && + git cat-file --batch-all-objects --batch-check="%(objectname)" \ + >expect.objects && + test_cmp expect.objects midx.objects && + + grep "^pack-" midx >midx.packs && + test_line_count = "$(($(wc -l <packs.all) + 1))" midx.packs + ) +' + +test_expect_success 'repack --write-midx includes cruft when already geometric' ' + git init repack--write-midx-geometric-noop && + ( + cd repack--write-midx-geometric-noop && + + git branch -M main && + test_commit A && + test_commit B && + + git checkout -B side && + test_commit --no-tag C && + C="$(git rev-parse HEAD)" && + + git checkout main && + git branch -D side && + git reflog expire --all --expire=all && + + # At this point we have two packs: one containing the + # objects belonging to commits A and B, and another + # (cruft) pack containing the objects belonging to + # commit C. + git repack --cruft -d && + + # Create a third pack which contains a merge commit + # making commit C reachable again. + # + # --no-ff is important here, as it ensures that we + # actually write a new object and subsequently a new + # pack to contain it. + git merge --no-ff $C && + git repack -d && + + ls $packdir/pack-*.idx | sort >packs.all && + cruft="$(ls $packdir/pack-*.mtimes)" && + cruft="${cruft%.mtimes}.idx" && + + for idx in $(grep -v $cruft <packs.all) + do + git show-index <$idx >out && + wc -l <out || return 1 + done >sizes.raw && + + # Make sure that there are two non-cruft packs, and + # that one of them contains at least twice as many + # objects as the other, ensuring that they are already + # in a geometric progression. + sort -n sizes.raw >sizes && + test_line_count = 2 sizes && + s1=$(head -n 1 sizes) && + s2=$(tail -n 1 sizes) && + test "$s2" -gt "$((2 * $s1))" && + + git -c repack.midxMustContainCruft=false repack --geometric=2 \ + --write-midx --write-bitmap-index + ) +' + test_done |
