1
+#!/bin/sh
2
+
3
+test_description='handling of promisor remote advertisement'
4
+
5
+. ./test-lib.sh
6
+
7
+GIT_TEST_MULTI_PACK_INDEX=0
8
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
9
+
10
+# Setup the repository with three commits, this way HEAD is always
11
+# available and we can hide commit 1 or 2.
12
+test_expect_success 'setup: create "template" repository' '
13
+ git init template &&
14
+ test_commit -C template 1 &&
15
+ test_commit -C template 2 &&
16
+ test_commit -C template 3 &&
17
+ test-tool genrandom foo 10240 >template/foo &&
18
+ git -C template add foo &&
19
+ git -C template commit -m foo
20
+'
21
+
22
+# A bare repo will act as a server repo with unpacked objects.
23
+test_expect_success 'setup: create bare "server" repository' '
24
+ git clone --bare --no-local template server &&
25
+ mv server/objects/pack/pack-* . &&
26
+ packfile=$(ls pack-*.pack) &&
27
+ git -C server unpack-objects --strict <"$packfile"
28
+'
29
+
30
+check_missing_objects () {
31
+ git -C "$1" rev-list --objects --all --missing=print > all.txt &&
32
+ perl -ne 'print if s/^[?]//' all.txt >missing.txt &&
33
+ test_line_count = "$2" missing.txt &&
34
+ if test "$2" -lt 2
35
+ then
36
+ test "$3" = "$(cat missing.txt)"
37
+ else
38
+ test -f "$3" &&
39
+ sort <"$3" >expected_sorted &&
40
+ sort <missing.txt >actual_sorted &&
41
+ test_cmp expected_sorted actual_sorted
42
+ fi
43
+}
44
+
45
+initialize_server () {
46
+ count="$1"
47
+ missing_oids="$2"
48
+
49
+ # Repack everything first
50
+ git -C server -c repack.writebitmaps=false repack -a -d &&
51
+
52
+ # Remove promisor file in case they exist, useful when reinitializing
53
+ rm -rf server/objects/pack/*.promisor &&
54
+
55
+ # Repack without the largest object and create a promisor pack on server
56
+ git -C server -c repack.writebitmaps=false repack -a -d \
57
+ --filter=blob:limit=5k --filter-to="$(pwd)/pack" &&
58
+ promisor_file=$(ls server/objects/pack/*.pack | sed "s/\.pack/.promisor/") &&
59
+ >"$promisor_file" &&
60
+
61
+ # Check objects missing on the server
62
+ check_missing_objects server "$count" "$missing_oids"
63
+}
64
+
65
+copy_to_lop () {
66
+ oid_path="$(test_oid_to_path $1)" &&
67
+ path="server/objects/$oid_path" &&
68
+ path2="lop/objects/$oid_path" &&
69
+ mkdir -p $(dirname "$path2") &&
70
+ cp "$path" "$path2"
71
+}
72
+
73
+test_expect_success "setup for testing promisor remote advertisement" '
74
+ # Create another bare repo called "lop" (for Large Object Promisor)
75
+ git init --bare lop &&
76
+
77
+ # Copy the largest object from server to lop
78
+ obj="HEAD:foo" &&
79
+ oid="$(git -C server rev-parse $obj)" &&
80
+ copy_to_lop "$oid" &&
81
+
82
+ initialize_server 1 "$oid" &&
83
+
84
+ # Configure lop as promisor remote for server
85
+ git -C server remote add lop "file://$(pwd)/lop" &&
86
+ git -C server config remote.lop.promisor true &&
87
+
88
+ git -C lop config uploadpack.allowFilter true &&
89
+ git -C lop config uploadpack.allowAnySHA1InWant true &&
90
+ git -C server config uploadpack.allowFilter true &&
91
+ git -C server config uploadpack.allowAnySHA1InWant true
92
+'
93
+
94
+test_expect_success "clone with promisor.advertise set to 'true'" '
95
+ git -C server config promisor.advertise true &&
96
+
97
+ # Clone from server to create a client
98
+ GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \
99
+ -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \
100
+ -c remote.lop.url="file://$(pwd)/lop" \
101
+ -c promisor.acceptfromserver=All \
102
+ --no-local --filter="blob:limit=5k" server client &&
103
+ test_when_finished "rm -rf client" &&
104
+
105
+ # Check that the largest object is still missing on the server
106
+ check_missing_objects server 1 "$oid"
107
+'
108
+
109
+test_expect_success "clone with promisor.advertise set to 'false'" '
110
+ git -C server config promisor.advertise false &&
111
+
112
+ # Clone from server to create a client
113
+ GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \
114
+ -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \
115
+ -c remote.lop.url="file://$(pwd)/lop" \
116
+ -c promisor.acceptfromserver=All \
117
+ --no-local --filter="blob:limit=5k" server client &&
118
+ test_when_finished "rm -rf client" &&
119
+
120
+ # Check that the largest object is not missing on the server
121
+ check_missing_objects server 0 "" &&
122
+
123
+ # Reinitialize server so that the largest object is missing again
124
+ initialize_server 1 "$oid"
125
+'
126
+
127
+test_expect_success "clone with promisor.acceptfromserver set to 'None'" '
128
+ git -C server config promisor.advertise true &&
129
+
130
+ # Clone from server to create a client
131
+ GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \
132
+ -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \
133
+ -c remote.lop.url="file://$(pwd)/lop" \
134
+ -c promisor.acceptfromserver=None \
135
+ --no-local --filter="blob:limit=5k" server client &&
136
+ test_when_finished "rm -rf client" &&
137
+
138
+ # Check that the largest object is not missing on the server
139
+ check_missing_objects server 0 "" &&
140
+
141
+ # Reinitialize server so that the largest object is missing again
142
+ initialize_server 1 "$oid"
143
+'
144
+
145
+test_expect_success "init + fetch with promisor.advertise set to 'true'" '
146
+ git -C server config promisor.advertise true &&
147
+
148
+ test_when_finished "rm -rf client" &&
149
+ mkdir client &&
150
+ git -C client init &&
151
+ git -C client config remote.lop.promisor true &&
152
+ git -C client config remote.lop.fetch "+refs/heads/*:refs/remotes/lop/*" &&
153
+ git -C client config remote.lop.url "file://$(pwd)/lop" &&
154
+ git -C client config remote.server.url "file://$(pwd)/server" &&
155
+ git -C client config remote.server.fetch "+refs/heads/*:refs/remotes/server/*" &&
156
+ git -C client config promisor.acceptfromserver All &&
157
+ GIT_NO_LAZY_FETCH=0 git -C client fetch --filter="blob:limit=5k" server &&
158
+
159
+ # Check that the largest object is still missing on the server
160
+ check_missing_objects server 1 "$oid"
161
+'
162
+
163
+test_expect_success "clone with promisor.advertise set to 'true' but don't delete the client" '
164
+ git -C server config promisor.advertise true &&
165
+
166
+ # Clone from server to create a client
167
+ GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \
168
+ -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \
169
+ -c remote.lop.url="file://$(pwd)/lop" \
170
+ -c promisor.acceptfromserver=All \
171
+ --no-local --filter="blob:limit=5k" server client &&
172
+
173
+ # Check that the largest object is still missing on the server
174
+ check_missing_objects server 1 "$oid"
175
+'
176
+
177
+test_expect_success "setup for subsequent fetches" '
178
+ # Generate new commit with large blob
179
+ test-tool genrandom bar 10240 >template/bar &&
180
+ git -C template add bar &&
181
+ git -C template commit -m bar &&
182
+
183
+ # Fetch new commit with large blob
184
+ git -C server fetch origin &&
185
+ git -C server update-ref HEAD FETCH_HEAD &&
186
+ git -C server rev-parse HEAD >expected_head &&
187
+
188
+ # Repack everything twice and remove .promisor files before
189
+ # each repack. This makes sure everything gets repacked
190
+ # into a single packfile. The second repack is necessary
191
+ # because the first one fetches from lop and creates a new
192
+ # packfile and its associated .promisor file.
193
+
194
+ rm -f server/objects/pack/*.promisor &&
195
+ git -C server -c repack.writebitmaps=false repack -a -d &&
196
+ rm -f server/objects/pack/*.promisor &&
197
+ git -C server -c repack.writebitmaps=false repack -a -d &&
198
+
199
+ # Unpack everything
200
+ rm pack-* &&
201
+ mv server/objects/pack/pack-* . &&
202
+ packfile=$(ls pack-*.pack) &&
203
+ git -C server unpack-objects --strict <"$packfile" &&
204
+
205
+ # Copy new large object to lop
206
+ obj_bar="HEAD:bar" &&
207
+ oid_bar="$(git -C server rev-parse $obj_bar)" &&
208
+ copy_to_lop "$oid_bar" &&
209
+
210
+ # Reinitialize server so that the 2 largest objects are missing
211
+ printf "%s\n" "$oid" "$oid_bar" >expected_missing.txt &&
212
+ initialize_server 2 expected_missing.txt &&
213
+
214
+ # Create one more client
215
+ cp -r client client2
216
+'
217
+
218
+test_expect_success "subsequent fetch from a client when promisor.advertise is true" '
219
+ git -C server config promisor.advertise true &&
220
+
221
+ GIT_NO_LAZY_FETCH=0 git -C client pull origin &&
222
+
223
+ git -C client rev-parse HEAD >actual &&
224
+ test_cmp expected_head actual &&
225
+
226
+ cat client/bar >/dev/null &&
227
+
228
+ check_missing_objects server 2 expected_missing.txt
229
+'
230
+
231
+test_expect_success "subsequent fetch from a client when promisor.advertise is false" '
232
+ git -C server config promisor.advertise false &&
233
+
234
+ GIT_NO_LAZY_FETCH=0 git -C client2 pull origin &&
235
+
236
+ git -C client2 rev-parse HEAD >actual &&
237
+ test_cmp expected_head actual &&
238
+
239
+ cat client2/bar >/dev/null &&
240
+
241
+ check_missing_objects server 1 "$oid"
242
+'
243
+
244
+test_done