mirror of
https://github.com/git/git
synced 2024-11-05 01:58:18 +00:00
7f97266ee1
Fix a leaking OID array in `write_pseudo_merges()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
450 lines
12 KiB
Bash
Executable file
450 lines
12 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='pseudo-merge bitmaps'
|
|
|
|
GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
|
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
. ./test-lib.sh
|
|
|
|
test_pseudo_merges () {
|
|
test-tool bitmap dump-pseudo-merges
|
|
}
|
|
|
|
test_pseudo_merge_commits () {
|
|
test-tool bitmap dump-pseudo-merge-commits "$1"
|
|
}
|
|
|
|
test_pseudo_merges_satisfied () {
|
|
test_trace2_data bitmap pseudo_merges_satisfied "$1"
|
|
}
|
|
|
|
test_pseudo_merges_cascades () {
|
|
test_trace2_data bitmap pseudo_merges_cascades "$1"
|
|
}
|
|
|
|
test_pseudo_merges_reused () {
|
|
test_trace2_data pack-bitmap-write building_bitmaps_pseudo_merge_reused "$1"
|
|
}
|
|
|
|
tag_everything () {
|
|
git rev-list --all --no-object-names >in &&
|
|
perl -lne '
|
|
print "create refs/tags/" . $. . " " . $1 if /([0-9a-f]+)/
|
|
' <in | git update-ref --stdin
|
|
}
|
|
|
|
test_expect_success 'setup' '
|
|
test_commit_bulk 512 &&
|
|
tag_everything
|
|
'
|
|
|
|
test_expect_success 'bitmap traversal without pseudo-merges' '
|
|
git repack -adb &&
|
|
|
|
git rev-list --count --all --objects >expect &&
|
|
|
|
: >trace2.txt &&
|
|
GIT_TRACE2_EVENT=$PWD/trace2.txt \
|
|
git rev-list --count --all --objects --use-bitmap-index >actual &&
|
|
|
|
test_pseudo_merges_satisfied 0 <trace2.txt &&
|
|
test_pseudo_merges_cascades 0 <trace2.txt &&
|
|
test_pseudo_merges >merges &&
|
|
test_must_be_empty merges &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'pseudo-merges accurately represent their objects' '
|
|
test_config bitmapPseudoMerge.test.pattern "refs/tags/" &&
|
|
test_config bitmapPseudoMerge.test.maxMerges 8 &&
|
|
test_config bitmapPseudoMerge.test.stableThreshold never &&
|
|
|
|
git repack -adb &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
test_line_count = 8 merges &&
|
|
|
|
for i in $(test_seq 0 $(($(wc -l <merges)-1)))
|
|
do
|
|
test-tool bitmap dump-pseudo-merge-commits $i >commits &&
|
|
|
|
git rev-list --objects --no-object-names --stdin <commits >expect.raw &&
|
|
test-tool bitmap dump-pseudo-merge-objects $i >actual.raw &&
|
|
|
|
sort -u <expect.raw >expect &&
|
|
sort -u <actual.raw >actual &&
|
|
|
|
test_cmp expect actual || return 1
|
|
done
|
|
'
|
|
|
|
test_expect_success 'bitmap traversal with pseudo-merges' '
|
|
: >trace2.txt &&
|
|
GIT_TRACE2_EVENT=$PWD/trace2.txt \
|
|
git rev-list --count --all --objects --use-bitmap-index >actual &&
|
|
git rev-list --count --all --objects >expect &&
|
|
|
|
test_pseudo_merges_satisfied 8 <trace2.txt &&
|
|
test_pseudo_merges_cascades 1 <trace2.txt &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'stale bitmap traversal with pseudo-merges' '
|
|
test_commit other &&
|
|
|
|
: >trace2.txt &&
|
|
GIT_TRACE2_EVENT=$PWD/trace2.txt \
|
|
git rev-list --count --all --objects --use-bitmap-index >actual &&
|
|
git rev-list --count --all --objects >expect &&
|
|
|
|
test_pseudo_merges_satisfied 8 <trace2.txt &&
|
|
test_pseudo_merges_cascades 1 <trace2.txt &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'bitmapPseudoMerge.sampleRate adjusts commit selection rate' '
|
|
test_config bitmapPseudoMerge.test.pattern "refs/tags/" &&
|
|
test_config bitmapPseudoMerge.test.maxMerges 1 &&
|
|
test_config bitmapPseudoMerge.test.stableThreshold never &&
|
|
|
|
commits_nr=$(git rev-list --all --count) &&
|
|
|
|
for rate in 1.0 0.5 0.25
|
|
do
|
|
git -c bitmapPseudoMerge.test.sampleRate=$rate repack -adb &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
test_line_count = 1 merges &&
|
|
test_pseudo_merge_commits 0 >commits &&
|
|
|
|
test-tool bitmap list-commits >bitmaps &&
|
|
bitmaps_nr="$(wc -l <bitmaps)" &&
|
|
|
|
perl -MPOSIX -e "print ceil(\$ARGV[0]*(\$ARGV[1]-\$ARGV[2]))" \
|
|
"$rate" "$commits_nr" "$bitmaps_nr" >expect &&
|
|
|
|
test $(cat expect) -eq $(wc -l <commits) || return 1
|
|
done
|
|
'
|
|
|
|
test_expect_success 'bitmapPseudoMerge.threshold excludes newer commits' '
|
|
git init pseudo-merge-threshold &&
|
|
(
|
|
cd pseudo-merge-threshold &&
|
|
|
|
new="1672549200" && # 2023-01-01
|
|
old="1641013200" && # 2022-01-01
|
|
|
|
GIT_COMMITTER_DATE="$new +0000" &&
|
|
export GIT_COMMITTER_DATE &&
|
|
test_commit_bulk --message="new" --notick 128 &&
|
|
|
|
GIT_COMMITTER_DATE="$old +0000" &&
|
|
export GIT_COMMITTER_DATE &&
|
|
test_commit_bulk --message="old" --notick 128 &&
|
|
|
|
tag_everything &&
|
|
|
|
git \
|
|
-c bitmapPseudoMerge.test.pattern="refs/tags/" \
|
|
-c bitmapPseudoMerge.test.maxMerges=1 \
|
|
-c bitmapPseudoMerge.test.threshold=$(($new - 1)) \
|
|
-c bitmapPseudoMerge.test.stableThreshold=never \
|
|
repack -adb &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
test_line_count = 1 merges &&
|
|
|
|
test_pseudo_merge_commits 0 >oids &&
|
|
git cat-file --batch <oids >commits &&
|
|
|
|
test $(wc -l <oids) = $(grep -c "^committer.*$old +0000$" commits)
|
|
)
|
|
'
|
|
|
|
test_expect_success 'bitmapPseudoMerge.stableThreshold creates stable groups' '
|
|
(
|
|
cd pseudo-merge-threshold &&
|
|
|
|
new="1672549200" && # 2023-01-01
|
|
mid="1654059600" && # 2022-06-01
|
|
old="1641013200" && # 2022-01-01
|
|
|
|
GIT_COMMITTER_DATE="$mid +0000" &&
|
|
export GIT_COMMITTER_DATE &&
|
|
test_commit_bulk --message="mid" --notick 128 &&
|
|
|
|
git for-each-ref --format="delete %(refname)" refs/tags >in &&
|
|
git update-ref --stdin <in &&
|
|
|
|
tag_everything &&
|
|
|
|
git \
|
|
-c bitmapPseudoMerge.test.pattern="refs/tags/" \
|
|
-c bitmapPseudoMerge.test.maxMerges=1 \
|
|
-c bitmapPseudoMerge.test.threshold=$(($new - 1)) \
|
|
-c bitmapPseudoMerge.test.stableThreshold=$(($mid - 1)) \
|
|
-c bitmapPseudoMerge.test.stableSize=10 \
|
|
repack -adb &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
merges_nr="$(wc -l <merges)" &&
|
|
|
|
for i in $(test_seq $(($merges_nr - 1)))
|
|
do
|
|
test_pseudo_merge_commits 0 >oids &&
|
|
git cat-file --batch <oids >commits &&
|
|
|
|
expect="$(grep -c "^committer.*$old +0000$" commits)" &&
|
|
actual="$(wc -l <oids)" &&
|
|
|
|
test $expect = $actual || return 1
|
|
done &&
|
|
|
|
test_pseudo_merge_commits $(($merges_nr - 1)) >oids &&
|
|
git cat-file --batch <oids >commits &&
|
|
test $(wc -l <oids) = $(grep -c "^committer.*$mid +0000$" commits)
|
|
)
|
|
'
|
|
|
|
test_expect_success 'out of order thresholds are rejected' '
|
|
test_must_fail git \
|
|
-c bitmapPseudoMerge.test.pattern="refs/*" \
|
|
-c bitmapPseudoMerge.test.threshold=1.month.ago \
|
|
-c bitmapPseudoMerge.test.stableThreshold=1.week.ago \
|
|
repack -adb 2>err &&
|
|
|
|
cat >expect <<-EOF &&
|
|
fatal: pseudo-merge group ${SQ}test${SQ} has unstable threshold before stable one
|
|
EOF
|
|
|
|
test_cmp expect err
|
|
'
|
|
|
|
test_expect_success 'pseudo-merge pattern with capture groups' '
|
|
git init pseudo-merge-captures &&
|
|
(
|
|
cd pseudo-merge-captures &&
|
|
|
|
test_commit_bulk 128 &&
|
|
tag_everything &&
|
|
|
|
for r in $(test_seq 8)
|
|
do
|
|
test_commit_bulk 16 &&
|
|
|
|
git rev-list HEAD~16.. >in &&
|
|
|
|
perl -lne "print \"create refs/remotes/$r/tags/\$. \$_\"" <in |
|
|
git update-ref --stdin || return 1
|
|
done &&
|
|
|
|
git \
|
|
-c bitmapPseudoMerge.tags.pattern="refs/remotes/([0-9]+)/tags/" \
|
|
-c bitmapPseudoMerge.tags.maxMerges=1 \
|
|
repack -adb &&
|
|
|
|
git for-each-ref --format="%(objectname) %(refname)" >refs &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
for m in $(test_seq 0 $(($(wc -l <merges) - 1)))
|
|
do
|
|
test_pseudo_merge_commits $m >oids &&
|
|
grep -f oids refs |
|
|
perl -lne "print \$1 if /refs\/remotes\/([0-9]+)/" |
|
|
sort -u || return 1
|
|
done >remotes &&
|
|
|
|
test $(wc -l <remotes) -eq $(sort -u <remotes | wc -l)
|
|
)
|
|
'
|
|
|
|
test_expect_success 'pseudo-merge overlap setup' '
|
|
git init pseudo-merge-overlap &&
|
|
(
|
|
cd pseudo-merge-overlap &&
|
|
|
|
test_commit_bulk 256 &&
|
|
tag_everything &&
|
|
|
|
git \
|
|
-c bitmapPseudoMerge.all.pattern="refs/" \
|
|
-c bitmapPseudoMerge.all.maxMerges=1 \
|
|
-c bitmapPseudoMerge.all.stableThreshold=never \
|
|
-c bitmapPseudoMerge.tags.pattern="refs/tags/" \
|
|
-c bitmapPseudoMerge.tags.maxMerges=1 \
|
|
-c bitmapPseudoMerge.tags.stableThreshold=never \
|
|
repack -adb
|
|
)
|
|
'
|
|
|
|
test_expect_success 'pseudo-merge overlap generates overlapping groups' '
|
|
(
|
|
cd pseudo-merge-overlap &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
test_line_count = 2 merges &&
|
|
|
|
test_pseudo_merge_commits 0 >commits-0.raw &&
|
|
test_pseudo_merge_commits 1 >commits-1.raw &&
|
|
|
|
sort commits-0.raw >commits-0 &&
|
|
sort commits-1.raw >commits-1 &&
|
|
|
|
comm -12 commits-0 commits-1 >overlap &&
|
|
|
|
test_line_count -gt 0 overlap
|
|
)
|
|
'
|
|
|
|
test_expect_success 'pseudo-merge overlap traversal' '
|
|
(
|
|
cd pseudo-merge-overlap &&
|
|
|
|
: >trace2.txt &&
|
|
GIT_TRACE2_EVENT=$PWD/trace2.txt \
|
|
git rev-list --count --all --objects --use-bitmap-index >actual &&
|
|
git rev-list --count --all --objects >expect &&
|
|
|
|
test_pseudo_merges_satisfied 2 <trace2.txt &&
|
|
test_pseudo_merges_cascades 1 <trace2.txt &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'pseudo-merge overlap stale traversal' '
|
|
(
|
|
cd pseudo-merge-overlap &&
|
|
|
|
test_commit other &&
|
|
|
|
: >trace2.txt &&
|
|
GIT_TRACE2_EVENT=$PWD/trace2.txt \
|
|
git rev-list --count --all --objects --use-bitmap-index >actual &&
|
|
git rev-list --count --all --objects >expect &&
|
|
|
|
test_pseudo_merges_satisfied 2 <trace2.txt &&
|
|
test_pseudo_merges_cascades 1 <trace2.txt &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'pseudo-merge reuse' '
|
|
git init pseudo-merge-reuse &&
|
|
(
|
|
cd pseudo-merge-reuse &&
|
|
|
|
stable="1641013200" && # 2022-01-01
|
|
unstable="1672549200" && # 2023-01-01
|
|
|
|
GIT_COMMITTER_DATE="$stable +0000" &&
|
|
export GIT_COMMITTER_DATE &&
|
|
test_commit_bulk --notick 128 &&
|
|
GIT_COMMITTER_DATE="$unstable +0000" &&
|
|
export GIT_COMMITTER_DATE &&
|
|
test_commit_bulk --notick 128 &&
|
|
|
|
tag_everything &&
|
|
|
|
git \
|
|
-c bitmapPseudoMerge.test.pattern="refs/tags/" \
|
|
-c bitmapPseudoMerge.test.maxMerges=1 \
|
|
-c bitmapPseudoMerge.test.threshold=now \
|
|
-c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \
|
|
-c bitmapPseudoMerge.test.stableSize=512 \
|
|
repack -adb &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
test_line_count = 2 merges &&
|
|
|
|
test_pseudo_merge_commits 0 >stable-oids.before &&
|
|
test_pseudo_merge_commits 1 >unstable-oids.before &&
|
|
|
|
: >trace2.txt &&
|
|
GIT_TRACE2_EVENT=$PWD/trace2.txt git \
|
|
-c bitmapPseudoMerge.test.pattern="refs/tags/" \
|
|
-c bitmapPseudoMerge.test.maxMerges=2 \
|
|
-c bitmapPseudoMerge.test.threshold=now \
|
|
-c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \
|
|
-c bitmapPseudoMerge.test.stableSize=512 \
|
|
repack -adb &&
|
|
|
|
test_pseudo_merges_reused 1 <trace2.txt &&
|
|
|
|
test_pseudo_merges >merges &&
|
|
test_line_count = 3 merges &&
|
|
|
|
test_pseudo_merge_commits 0 >stable-oids.after &&
|
|
for i in 1 2
|
|
do
|
|
test_pseudo_merge_commits $i || return 1
|
|
done >unstable-oids.after &&
|
|
|
|
sort -u <stable-oids.before >expect &&
|
|
sort -u <stable-oids.after >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
sort -u <unstable-oids.before >expect &&
|
|
sort -u <unstable-oids.after >actual &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'empty pseudo-merge group' '
|
|
git init pseudo-merge-empty-group &&
|
|
(
|
|
cd pseudo-merge-empty-group &&
|
|
|
|
# Ensure that a pseudo-merge group with no unstable
|
|
# commits does not generate an empty pseudo-merge
|
|
# bitmap.
|
|
git config bitmapPseudoMerge.empty.pattern refs/ &&
|
|
|
|
test_commit base &&
|
|
git repack -adb &&
|
|
|
|
test-tool bitmap dump-pseudo-merges >merges &&
|
|
test_line_count = 1 merges &&
|
|
|
|
test 0 -eq "$(grep -c commits=0 <merges)"
|
|
)
|
|
'
|
|
|
|
test_expect_success 'pseudo-merge closure' '
|
|
git init pseudo-merge-closure &&
|
|
(
|
|
cd pseudo-merge-closure &&
|
|
|
|
test_commit A &&
|
|
git repack -d &&
|
|
|
|
test_commit B &&
|
|
|
|
# Note that the contents of A is packed, but B is not. A
|
|
# (and the objects reachable from it) are thus visible
|
|
# to the MIDX, but the same is not true for B and its
|
|
# objects.
|
|
#
|
|
# Ensure that we do not attempt to create a pseudo-merge
|
|
# for B, depsite it matching the below pseudo-merge
|
|
# group pattern, as doing so would result in a failure
|
|
# to write a non-closed bitmap.
|
|
git config bitmapPseudoMerge.test.pattern refs/ &&
|
|
git config bitmapPseudoMerge.test.threshold now &&
|
|
|
|
git multi-pack-index write --bitmap &&
|
|
|
|
test-tool bitmap dump-pseudo-merges >pseudo-merges &&
|
|
test_line_count = 1 pseudo-merges &&
|
|
|
|
git rev-parse A >expect &&
|
|
|
|
test-tool bitmap list-commits >actual &&
|
|
test_cmp expect actual &&
|
|
test-tool bitmap dump-pseudo-merge-commits 0 >actual &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_done
|