3 test_description='upload-pack ref-in-want'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
11 sed -n -e '/wanted-refs/,/0001/{
15 }' <out | test-tool pkt-line unpack >actual_refs
18 get_actual_commits () {
19 test-tool pkt-line unpack-sideband <out >o.pack &&
20 git index-pack o.pack &&
21 git verify-pack -v o.idx >objs &&
22 sed -n -e 's/\([0-9a-f][0-9a-f]*\) commit .*/\1/p' objs >objs.sed &&
23 sort >actual_commits <objs.sed
28 test_cmp expected_refs actual_refs &&
30 sort expected_commits >sorted_commits &&
31 test_cmp sorted_commits actual_commits
37 if test "$(test_oid algo)" != sha1
39 echo "object-format=$(test_oid algo)"
49 test_expect_success 'setup repository' '
52 git checkout -b o/foo &&
55 git checkout -b o/bar b &&
57 git checkout -b baz a &&
63 test_expect_success 'config controls ref-in-want advertisement' '
64 test-tool serve-v2 --advertise-capabilities >out &&
65 perl -ne "/ref-in-want/ and print" out >out.filter &&
66 test_must_be_empty out.filter &&
68 git config uploadpack.allowRefInWant false &&
69 test-tool serve-v2 --advertise-capabilities >out &&
70 perl -ne "/ref-in-want/ and print" out >out.filter &&
71 test_must_be_empty out.filter &&
73 git config uploadpack.allowRefInWant true &&
74 test-tool serve-v2 --advertise-capabilities >out &&
75 perl -ne "/ref-in-want/ and print" out >out.filter &&
76 test_file_not_empty out.filter
79 test_expect_success 'invalid want-ref line' '
80 test-tool pkt-line pack >in <<-EOF &&
81 $(write_command fetch)
84 want-ref refs/heads/non-existent
89 test_must_fail test-tool serve-v2 --stateless-rpc 2>out <in &&
90 grep "unknown ref" out
93 test_expect_success 'basic want-ref' '
94 oid=$(git rev-parse f) &&
95 cat >expected_refs <<-EOF &&
98 git rev-parse f >expected_commits &&
100 oid=$(git rev-parse a) &&
101 test-tool pkt-line pack >in <<-EOF &&
102 $(write_command fetch)
105 want-ref refs/heads/main
111 test-tool serve-v2 --stateless-rpc >out <in &&
115 test_expect_success 'multiple want-ref lines' '
116 oid_c=$(git rev-parse c) &&
117 oid_d=$(git rev-parse d) &&
118 cat >expected_refs <<-EOF &&
119 $oid_c refs/heads/o/foo
120 $oid_d refs/heads/o/bar
122 git rev-parse c d >expected_commits &&
124 oid=$(git rev-parse b) &&
125 test-tool pkt-line pack >in <<-EOF &&
126 $(write_command fetch)
129 want-ref refs/heads/o/foo
130 want-ref refs/heads/o/bar
136 test-tool serve-v2 --stateless-rpc >out <in &&
140 test_expect_success 'mix want and want-ref' '
141 oid=$(git rev-parse f) &&
142 cat >expected_refs <<-EOF &&
145 git rev-parse e f >expected_commits &&
147 test-tool pkt-line pack >in <<-EOF &&
148 $(write_command fetch)
151 want-ref refs/heads/main
152 want $(git rev-parse e)
153 have $(git rev-parse a)
158 test-tool serve-v2 --stateless-rpc >out <in &&
162 test_expect_success 'want-ref with ref we already have commit for' '
163 oid=$(git rev-parse c) &&
164 cat >expected_refs <<-EOF &&
165 $oid refs/heads/o/foo
169 oid=$(git rev-parse c) &&
170 test-tool pkt-line pack >in <<-EOF &&
171 $(write_command fetch)
174 want-ref refs/heads/o/foo
180 test-tool serve-v2 --stateless-rpc >out <in &&
185 LOCAL_PRISTINE="$(pwd)/local_pristine"
202 test_expect_success 'setup repos for fetching with ref-in-want tests' '
204 git init -b main "$REPO" &&
208 # Local repo with many commits (so that negotiation will take
209 # more than 1 request/response pair)
210 rm -rf "$LOCAL_PRISTINE" &&
211 git clone "file://$REPO" "$LOCAL_PRISTINE" &&
212 cd "$LOCAL_PRISTINE" &&
213 git checkout -b side &&
214 test_commit_bulk --id=s 33 &&
216 # Add novel commits to upstream
219 git checkout -b o/foo &&
222 git checkout -b o/bar b &&
224 git checkout -b baz a &&
229 git -C "$REPO" config uploadpack.allowRefInWant true &&
230 git -C "$LOCAL_PRISTINE" config protocol.version 2
233 test_expect_success 'fetching with exact OID' '
234 test_when_finished "rm -f log" &&
237 cp -r "$LOCAL_PRISTINE" local &&
238 oid=$(git -C "$REPO" rev-parse d) &&
239 GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin \
240 "$oid":refs/heads/actual &&
242 git -C "$REPO" rev-parse "d" >expected &&
243 git -C local rev-parse refs/heads/actual >actual &&
244 test_cmp expected actual &&
248 test_expect_success 'fetching multiple refs' '
249 test_when_finished "rm -f log" &&
252 cp -r "$LOCAL_PRISTINE" local &&
253 GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin main baz &&
255 git -C "$REPO" rev-parse "main" "baz" >expected &&
256 git -C local rev-parse refs/remotes/origin/main refs/remotes/origin/baz >actual &&
257 test_cmp expected actual &&
258 grep "want-ref refs/heads/main" log &&
259 grep "want-ref refs/heads/baz" log
262 test_expect_success 'fetching ref and exact OID' '
263 test_when_finished "rm -f log" &&
266 cp -r "$LOCAL_PRISTINE" local &&
267 oid=$(git -C "$REPO" rev-parse b) &&
268 GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin \
269 main "$oid":refs/heads/actual &&
271 git -C "$REPO" rev-parse "main" "b" >expected &&
272 git -C local rev-parse refs/remotes/origin/main refs/heads/actual >actual &&
273 test_cmp expected actual &&
274 grep "want $oid" log &&
275 grep "want-ref refs/heads/main" log
278 test_expect_success 'fetching with wildcard that does not match any refs' '
279 test_when_finished "rm -f log" &&
282 cp -r "$LOCAL_PRISTINE" local &&
283 git -C local fetch origin refs/heads/none*:refs/heads/* >out &&
284 test_must_be_empty out
287 test_expect_success 'fetching with wildcard that matches multiple refs' '
288 test_when_finished "rm -f log" &&
291 cp -r "$LOCAL_PRISTINE" local &&
292 GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin refs/heads/o*:refs/heads/o* &&
294 git -C "$REPO" rev-parse "o/foo" "o/bar" >expected &&
295 git -C local rev-parse "o/foo" "o/bar" >actual &&
296 test_cmp expected actual &&
297 grep "want-ref refs/heads/o/foo" log &&
298 grep "want-ref refs/heads/o/bar" log
301 . "$TEST_DIRECTORY"/lib-httpd.sh
304 REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo"
305 LOCAL_PRISTINE="$(pwd)/local_pristine"
307 test_expect_success 'setup repos for change-while-negotiating test' '
309 git init -b main "$REPO" &&
311 >.git/git-daemon-export-ok &&
315 # Local repo with many commits (so that negotiation will take
316 # more than 1 request/response pair)
317 rm -rf "$LOCAL_PRISTINE" &&
318 git clone "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" "$LOCAL_PRISTINE" &&
319 cd "$LOCAL_PRISTINE" &&
320 git checkout -b side &&
321 test_commit_bulk --id=s 33 &&
323 # Add novel commits to upstream
330 git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_perl/repo" &&
331 git -C "$LOCAL_PRISTINE" config protocol.version 2
335 # Simulate that the server initially reports $2 as the ref
336 # corresponding to $1, and after that, $1 as the ref corresponding to
337 # $1. This corresponds to the real-life situation where the server's
338 # repository appears to change during negotiation, for example, when
339 # different servers in a load-balancing arrangement serve (stateless)
340 # RPCs during a single negotiation.
341 oid1=$(git -C "$REPO" rev-parse $1) &&
342 oid2=$(git -C "$REPO" rev-parse $2) &&
343 echo "s/$oid1/$oid2/" >"$HTTPD_ROOT_PATH/one-time-perl"
346 test_expect_success 'server is initially ahead - no ref in want' '
347 git -C "$REPO" config uploadpack.allowRefInWant false &&
349 cp -r "$LOCAL_PRISTINE" local &&
350 inconsistency main $(test_oid numeric) &&
351 test_must_fail git -C local fetch 2>err &&
352 test_i18ngrep "fatal: remote error: upload-pack: not our ref" err
355 test_expect_success 'server is initially ahead - ref in want' '
356 git -C "$REPO" config uploadpack.allowRefInWant true &&
358 cp -r "$LOCAL_PRISTINE" local &&
359 inconsistency main $(test_oid numeric) &&
360 git -C local fetch &&
362 git -C "$REPO" rev-parse --verify main >expected &&
363 git -C local rev-parse --verify refs/remotes/origin/main >actual &&
364 test_cmp expected actual
367 test_expect_success 'server is initially behind - no ref in want' '
368 git -C "$REPO" config uploadpack.allowRefInWant false &&
370 cp -r "$LOCAL_PRISTINE" local &&
371 inconsistency main "main^" &&
372 git -C local fetch &&
374 git -C "$REPO" rev-parse --verify "main^" >expected &&
375 git -C local rev-parse --verify refs/remotes/origin/main >actual &&
376 test_cmp expected actual
379 test_expect_success 'server is initially behind - ref in want' '
380 git -C "$REPO" config uploadpack.allowRefInWant true &&
382 cp -r "$LOCAL_PRISTINE" local &&
383 inconsistency main "main^" &&
384 git -C local fetch &&
386 git -C "$REPO" rev-parse --verify "main" >expected &&
387 git -C local rev-parse --verify refs/remotes/origin/main >actual &&
388 test_cmp expected actual
391 test_expect_success 'server loses a ref - ref in want' '
392 git -C "$REPO" config uploadpack.allowRefInWant true &&
394 cp -r "$LOCAL_PRISTINE" local &&
395 echo "s/main/rain/" >"$HTTPD_ROOT_PATH/one-time-perl" &&
396 test_must_fail git -C local fetch 2>err &&
398 test_i18ngrep "fatal: remote error: unknown ref refs/heads/rain" err
401 # DO NOT add non-httpd-specific tests here, because the last part of this
402 # test script is only executed when httpd is available and enabled.