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