Merge branch 'rj/sparse-flags'
[git] / t / t5320-delta-islands.sh
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