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