object-file: convert 'switch' back to 'if'
[git/debian.git] / t / t5316-pack-delta-depth.sh
blobe9045009a1105d09caaea43b830548f77707b096
1 #!/bin/sh
3 test_description='pack-objects breaks long cross-pack delta chains'
4 . ./test-lib.sh
6 # This mirrors a repeated push setup:
8 # 1. A client repeatedly modifies some files, makes a
9 # commit, and pushes the result. It does this N times
10 # before we get around to repacking.
12 # 2. Each push generates a thin pack with the new version of
13 # various objects. Let's consider some file in the root tree
14 # which is updated in each commit.
16 # When generating push number X, we feed commit X-1 (and
17 # thus blob X-1) as a preferred base. The resulting pack has
18 # blob X as a thin delta against blob X-1.
20 # On the receiving end, "index-pack --fix-thin" will
21 # complete the pack with a base copy of blob X-1.
23 # 3. In older versions of git, if we used the delta from
24 # pack X, then we'd always find blob X-1 as a base in the
25 # same pack (and generate a fresh delta).
27 # But with the pack mru, we jump from delta to delta
28 # following the traversal order:
30 # a. We grab blob X from pack X as a delta, putting it at
31 # the tip of our mru list.
33 # b. Eventually we move onto commit X-1. We need other
34 # objects which are only in pack X-1 (in the test code
35 # below, it's the containing tree). That puts pack X-1
36 # at the tip of our mru list.
38 # c. Eventually we look for blob X-1, and we find the
39 # version in pack X-1 (because it's the mru tip).
41 # Now we have blob X as a delta against X-1, which is a delta
42 # against X-2, and so forth.
44 # In the real world, these small pushes would get exploded by
45 # unpack-objects rather than "index-pack --fix-thin", but the
46 # same principle applies to larger pushes (they only need one
47 # repeatedly-modified file to generate the delta chain).
49 test_expect_success 'create series of packs' '
50 test-tool genrandom foo 4096 >content &&
51 prev= &&
52 for i in $(test_seq 1 10)
54 cat content >file &&
55 echo $i >>file &&
56 git add file &&
57 git commit -m $i &&
58 cur=$(git rev-parse HEAD^{tree}) &&
60 if test -n "$prev"
61 then
62 echo "-$prev"
63 fi &&
64 echo $cur &&
65 echo "$(git rev-parse :file) file"
66 } | git pack-objects --stdout >tmp &&
67 GIT_TRACE2_EVENT=$PWD/trace \
68 git index-pack -v --stdin --fix-thin <tmp || return 1 &&
69 grep -c region_enter.*progress trace >enter &&
70 grep -c region_leave.*progress trace >leave &&
71 test_cmp enter leave &&
72 prev=$cur
73 done
76 max_chain() {
77 git index-pack --verify-stat-only "$1" >output &&
78 perl -lne '
79 BEGIN { $len = 0 }
80 /chain length = (\d+)/ and $len = $1;
81 END { print $len }
82 ' output
85 # Note that this whole setup is pretty reliant on the current
86 # packing heuristics. We double-check that our test case
87 # actually produces a long chain. If it doesn't, it should be
88 # adjusted (or scrapped if the heuristics have become too unreliable)
89 test_expect_success 'packing produces a long delta' '
90 # Use --window=0 to make sure we are seeing reused deltas,
91 # not computing a new long chain.
92 pack=$(git pack-objects --all --window=0 </dev/null pack) &&
93 echo 9 >expect &&
94 max_chain pack-$pack.pack >actual &&
95 test_cmp expect actual
98 test_expect_success '--depth limits depth' '
99 pack=$(git pack-objects --all --depth=5 </dev/null pack) &&
100 echo 5 >expect &&
101 max_chain pack-$pack.pack >actual &&
102 test_cmp expect actual
105 test_expect_success '--depth=0 disables deltas' '
106 pack=$(git pack-objects --all --depth=0 </dev/null pack) &&
107 echo 0 >expect &&
108 max_chain pack-$pack.pack >actual &&
109 test_cmp expect actual
112 test_expect_success 'negative depth disables deltas' '
113 pack=$(git pack-objects --all --depth=-1 </dev/null pack) &&
114 echo 0 >expect &&
115 max_chain pack-$pack.pack >actual &&
116 test_cmp expect actual
119 test_done