]>
Commit | Line | Data |
---|---|---|
9eb0986f JK |
1 | #!/bin/sh |
2 | ||
3 | test_description='exercise delta islands' | |
4 | . ./test-lib.sh | |
5 | ||
6 | # returns true iff $1 is a delta based on $2 | |
7 | is_delta_base () { | |
8 | delta_base=$(echo "$1" | git cat-file --batch-check='%(deltabase)') && | |
9 | echo >&2 "$1 has base $delta_base" && | |
10 | test "$delta_base" = "$2" | |
11 | } | |
12 | ||
13 | # generate a commit on branch $1 with a single file, "file", whose | |
14 | # content is mostly based on the seed $2, but with a unique bit | |
15 | # of content $3 appended. This should allow us to see whether | |
16 | # blobs of different refs delta against each other. | |
17 | commit() { | |
18 | blob=$({ test-tool genrandom "$2" 10240 && echo "$3"; } | | |
19 | git hash-object -w --stdin) && | |
20 | tree=$(printf '100644 blob %s\tfile\n' "$blob" | git mktree) && | |
21 | commit=$(echo "$2-$3" | git commit-tree "$tree" ${4:+-p "$4"}) && | |
22 | git update-ref "refs/heads/$1" "$commit" && | |
23 | eval "$1"'=$(git rev-parse $1:file)' && | |
24 | eval "echo >&2 $1=\$$1" | |
25 | } | |
26 | ||
27 | test_expect_success 'setup commits' ' | |
28 | commit one seed 1 && | |
29 | commit two seed 12 | |
30 | ' | |
31 | ||
32 | # Note: This is heavily dependent on the "prefer larger objects as base" | |
33 | # heuristic. | |
34 | test_expect_success 'vanilla repack deltas one against two' ' | |
35 | git repack -adf && | |
36 | is_delta_base $one $two | |
37 | ' | |
38 | ||
39 | test_expect_success 'island repack with no island definition is vanilla' ' | |
40 | git repack -adfi && | |
41 | is_delta_base $one $two | |
42 | ' | |
43 | ||
44 | test_expect_success 'island repack with no matches is vanilla' ' | |
45 | git -c "pack.island=refs/foo" repack -adfi && | |
46 | is_delta_base $one $two | |
47 | ' | |
48 | ||
49 | test_expect_success 'separate islands disallows delta' ' | |
50 | git -c "pack.island=refs/heads/(.*)" repack -adfi && | |
51 | ! is_delta_base $one $two && | |
52 | ! is_delta_base $two $one | |
53 | ' | |
54 | ||
55 | test_expect_success 'same island allows delta' ' | |
56 | git -c "pack.island=refs/heads" repack -adfi && | |
57 | is_delta_base $one $two | |
58 | ' | |
59 | ||
60 | test_expect_success 'coalesce same-named islands' ' | |
61 | git \ | |
62 | -c "pack.island=refs/(.*)/one" \ | |
63 | -c "pack.island=refs/(.*)/two" \ | |
64 | repack -adfi && | |
65 | is_delta_base $one $two | |
66 | ' | |
67 | ||
68 | test_expect_success 'island restrictions drop reused deltas' ' | |
69 | git repack -adfi && | |
70 | is_delta_base $one $two && | |
71 | git -c "pack.island=refs/heads/(.*)" repack -adi && | |
72 | ! is_delta_base $one $two && | |
73 | ! is_delta_base $two $one | |
74 | ' | |
75 | ||
76 | test_expect_success 'island regexes are left-anchored' ' | |
77 | git -c "pack.island=heads/(.*)" repack -adfi && | |
78 | is_delta_base $one $two | |
79 | ' | |
80 | ||
81 | test_expect_success 'island regexes follow last-one-wins scheme' ' | |
82 | git \ | |
83 | -c "pack.island=refs/heads/(.*)" \ | |
84 | -c "pack.island=refs/heads/" \ | |
85 | repack -adfi && | |
86 | is_delta_base $one $two | |
87 | ' | |
88 | ||
89 | test_expect_success 'setup shared history' ' | |
90 | commit root shared root && | |
91 | commit one shared 1 root && | |
92 | commit two shared 12-long root | |
93 | ' | |
94 | ||
95 | # We know that $two will be preferred as a base from $one, | |
96 | # because we can transform it with a pure deletion. | |
97 | # | |
98 | # We also expect $root as a delta against $two by the "longest is base" rule. | |
99 | test_expect_success 'vanilla delta goes between branches' ' | |
100 | git repack -adf && | |
101 | is_delta_base $one $two && | |
102 | is_delta_base $root $two | |
103 | ' | |
104 | ||
105 | # Here we should allow $one to base itself on $root; even though | |
106 | # they are in different islands, the objects in $root are in a superset | |
107 | # of islands compared to those in $one. | |
108 | # | |
109 | # Similarly, $two can delta against $root by our rules. And unlike $one, | |
110 | # in which we are just allowing it, the island rules actually put $root | |
111 | # as a possible base for $two, which it would not otherwise be (due to the size | |
112 | # sorting). | |
113 | test_expect_success 'deltas allowed against superset islands' ' | |
114 | git -c "pack.island=refs/heads/(.*)" repack -adfi && | |
115 | is_delta_base $one $root && | |
116 | is_delta_base $two $root | |
117 | ' | |
118 | ||
119 | # We are going to test the packfile order here, so we again have to make some | |
120 | # assumptions. We assume that "$root", as part of our core "one", must come | |
121 | # before "$two". This should be guaranteed by the island code. However, for | |
122 | # this test to fail without islands, we are also assuming that it would not | |
123 | # otherwise do so. This is true by the current write order, which will put | |
124 | # commits (and their contents) before their parents. | |
125 | test_expect_success 'island core places core objects first' ' | |
126 | cat >expect <<-EOF && | |
127 | $root | |
128 | $two | |
129 | EOF | |
130 | git -c "pack.island=refs/heads/(.*)" \ | |
131 | -c "pack.islandcore=one" \ | |
132 | repack -adfi && | |
133 | git verify-pack -v .git/objects/pack/*.pack | | |
134 | cut -d" " -f1 | | |
135 | egrep "$root|$two" >actual && | |
136 | test_cmp expect actual | |
137 | ' | |
138 | ||
139 | test_expect_success 'unmatched island core is not fatal' ' | |
140 | git -c "pack.islandcore=one" repack -adfi | |
141 | ' | |
142 | ||
143 | test_done |