Raw
1 #!/bin/sh
2
3 : ${HTTP_PROTO:=HTTP/1.1}
4 test_description="test smart fetching over http via http-backend ($HTTP_PROTO)"
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 . ./test-lib.sh
9 . "$TEST_DIRECTORY"/lib-httpd.sh
10
11 if ! test_have_prereq PERL_TEST_HELPERS
12 then
13 skip_all='skipping http fetch smart tests; Perl not available'
14 test_done
15 fi
16
17 test "$HTTP_PROTO" = "HTTP/2" && enable_http2
18 start_httpd
19
20 test_expect_success HTTP2 'enable client-side http/2' '
21 git config --global http.version HTTP/2
22 '
23
24 test_expect_success 'setup repository' '
25 git config push.default matching &&
26 echo content >file &&
27 git add file &&
28 git commit -m one
29 '
30
31 test_expect_success 'create http-accessible bare repository' '
32 mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
33 (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
34 git --bare init
35 ) &&
36 git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
37 git push public main:main
38 '
39
40 setup_askpass_helper
41
42 test_expect_success 'clone http repository' '
43 if test_have_prereq HTTP2 && test "$HTTPD_PROTO" = "https"
44 then
45 # ALPN lets us immediately use HTTP/2; likewise, POSTs with
46 # bodies can use it because they do not need to upgrade
47 INITIAL_PROTO=HTTP/2
48 else
49 # either we are not using HTTP/2, or the initial
50 # request is sent via HTTP/1.1 and asks for upgrade
51 INITIAL_PROTO=HTTP/1.1
52 fi &&
53
54 cat >exp.raw <<-EOF &&
55 > GET /smart/repo.git/info/refs?service=git-upload-pack $INITIAL_PROTO
56 > accept: */*
57 > accept-encoding: ENCODINGS
58 > accept-language: ko-KR, *;q=0.9
59 > pragma: no-cache
60 {V2} > git-protocol: version=2
61 < $HTTP_PROTO 200 OK
62 < pragma: no-cache
63 < cache-control: no-cache, max-age=0, must-revalidate
64 < content-type: application/x-git-upload-pack-advertisement
65 > POST /smart/repo.git/git-upload-pack $INITIAL_PROTO
66 > accept-encoding: ENCODINGS
67 > content-type: application/x-git-upload-pack-request
68 > accept: application/x-git-upload-pack-result
69 > accept-language: ko-KR, *;q=0.9
70 {V2} > git-protocol: version=2
71 > content-length: xxx
72 < $INITIAL_PROTO 200 OK
73 < pragma: no-cache
74 < cache-control: no-cache, max-age=0, must-revalidate
75 < content-type: application/x-git-upload-pack-result
76 {V2} > POST /smart/repo.git/git-upload-pack $INITIAL_PROTO
77 {V2} > accept-encoding: ENCODINGS
78 {V2} > content-type: application/x-git-upload-pack-request
79 {V2} > accept: application/x-git-upload-pack-result
80 {V2} > accept-language: ko-KR, *;q=0.9
81 {V2} > git-protocol: version=2
82 {V2} > content-length: xxx
83 {V2} < $INITIAL_PROTO 200 OK
84 {V2} < pragma: no-cache
85 {V2} < cache-control: no-cache, max-age=0, must-revalidate
86 {V2} < content-type: application/x-git-upload-pack-result
87 EOF
88
89 if test "$GIT_TEST_PROTOCOL_VERSION" = 0
90 then
91 sed "/^{V2}/d" <exp.raw >exp
92 else
93 sed "s/^{V2} //" <exp.raw >exp
94 fi &&
95
96 GIT_TRACE_CURL=true LANGUAGE="ko_KR.UTF-8" \
97 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
98 test_cmp file clone/file &&
99 tr '\''\015'\'' Q <err |
100 perl -pe '\''
101 s/(Send|Recv) header: ([A-Za-z0-9-]+):/
102 "$1 header: " . lc($2) . ":"
103 /e;
104 '\'' |
105 sed -e "
106 s/Q\$//
107 /^[^<=]/d
108 /^== Info:/d
109 /^=> Send header, /d
110 /^=> Send header:$/d
111 /^<= Recv header, /d
112 /^<= Recv header:$/d
113 s/=> Send header: //
114 s/= Recv header://
115 /^<= Recv data/d
116 /^=> Send data/d
117 /^<= Recv SSL data/d
118 /^=> Send SSL data/d
119 /^$/d
120 /^< $/d
121
122 /^[^><]/{
123 s/^/> /
124 }
125
126 /^< HTTP/ {
127 s/200$/200 OK/
128 }
129 /^< HTTP\\/1.1 101/d
130 /^[><] connection: /d
131 /^[><] upgrade: /d
132 /^> http2-settings: /d
133
134 /^> user-agent: /d
135 /^> host: /d
136 /^> POST /,$ {
137 /^> Accept: [*]\\/[*]/d
138 }
139 s/^> content-length: .*/> content-length: xxx/
140 /^> 00..want /d
141 /^> 00.*done/d
142
143 /^< server: /d
144 /^< expires: /d
145 /^< date: /d
146 /^< content-length: /d
147 /^< transfer-encoding: /d
148 " >actual &&
149
150 sed -e "s/^> accept-encoding: .*/> accept-encoding: ENCODINGS/" \
151 actual >actual.smudged &&
152 test_cmp exp actual.smudged &&
153
154 grep "accept-encoding:.*gzip" actual >actual.gzip
155 '
156
157 test_expect_success 'fetch changes via http' '
158 echo content >>file &&
159 git commit -a -m two &&
160 git push public &&
161 (cd clone && git pull) &&
162 test_cmp file clone/file
163 '
164
165 test_expect_success 'used upload-pack service' '
166 strip_access_log >log &&
167 test_grep "GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/[0-9.]* 200" log &&
168 test_grep "POST /smart/repo.git/git-upload-pack HTTP/[0-9.]* 200" log
169 '
170
171 test_expect_success 'follow redirects (301)' '
172 git clone $HTTPD_URL/smart-redir-perm/repo.git --quiet repo-p
173 '
174
175 test_expect_success 'follow redirects (302)' '
176 git clone $HTTPD_URL/smart-redir-temp/repo.git --quiet repo-t
177 '
178
179 test_expect_success 'redirects re-root further requests' '
180 git clone $HTTPD_URL/smart-redir-limited/repo.git repo-redir-limited
181 '
182
183 test_expect_success 're-rooting dies on insane schemes' '
184 test_must_fail git clone $HTTPD_URL/insane-redir/repo.git insane
185 '
186
187 test_expect_success 'clone from password-protected repository' '
188 echo two >expect &&
189 set_askpass user@host pass@host &&
190 git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
191 expect_askpass both user%40host &&
192 git --git-dir=smart-auth log -1 --format=%s >actual &&
193 test_cmp expect actual
194 '
195
196 test_expect_success 'credential.interactive=false skips askpass' '
197 set_askpass bogus nonsense &&
198 (
199 GIT_TRACE2_EVENT="$(pwd)/interactive-true" &&
200 export GIT_TRACE2_EVENT &&
201 test_must_fail git clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-true-dir &&
202 test_region credential interactive interactive-true &&
203
204 GIT_TRACE2_EVENT="$(pwd)/interactive-false" &&
205 export GIT_TRACE2_EVENT &&
206 test_must_fail git -c credential.interactive=false \
207 clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-false-dir &&
208 test_region ! credential interactive interactive-false &&
209
210 GIT_TRACE2_EVENT="$(pwd)/interactive-never" &&
211 export GIT_TRACE2_EVENT &&
212 test_must_fail git -c credential.interactive=never \
213 clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-never-dir &&
214 test_region ! credential interactive interactive-never
215 )
216 '
217
218 test_expect_success 'clone from auth-only-for-push repository' '
219 echo two >expect &&
220 set_askpass wrong &&
221 git clone --bare "$HTTPD_URL/auth-push/smart/repo.git" smart-noauth &&
222 expect_askpass none &&
223 git --git-dir=smart-noauth log -1 --format=%s >actual &&
224 test_cmp expect actual
225 '
226
227 test_expect_success 'clone from auth-only-for-objects repository' '
228 echo two >expect &&
229 set_askpass user@host pass@host &&
230 git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
231 expect_askpass both user%40host &&
232 git --git-dir=half-auth log -1 --format=%s >actual &&
233 test_cmp expect actual
234 '
235
236 test_expect_success 'no-op half-auth fetch does not require a password' '
237 set_askpass wrong &&
238
239 # NEEDSWORK: When using HTTP(S), protocol v0 supports a "half-auth"
240 # configuration with authentication required only when downloading
241 # objects and not refs, by having the HTTP server only require
242 # authentication for the "git-upload-pack" path and not "info/refs".
243 # This is not possible with protocol v2, since both objects and refs
244 # are obtained from the "git-upload-pack" path. A solution to this is
245 # to teach the server and client to be able to inline ls-refs requests
246 # as an Extra Parameter (see "git help gitformat-pack-protocol"), so that
247 # "info/refs" can serve refs, just like it does in protocol v0.
248 GIT_TEST_PROTOCOL_VERSION=0 git --git-dir=half-auth fetch &&
249 expect_askpass none
250 '
251
252 test_expect_success 'redirects send auth to new location' '
253 set_askpass user@host pass@host &&
254 git -c credential.useHttpPath=true \
255 clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
256 expect_askpass both user%40host auth/smart/repo.git
257 '
258
259 test_expect_success 'GIT_TRACE_CURL redacts auth details' '
260 rm -rf redact-auth trace &&
261 set_askpass user@host pass@host &&
262 GIT_TRACE_CURL="$(pwd)/trace" git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
263 expect_askpass both user%40host &&
264
265 # Ensure that there is no "Basic" followed by a base64 string, but that
266 # the auth details are redacted
267 test_grep ! -i "Authorization: Basic [0-9a-zA-Z+/]" trace &&
268 test_grep -i "Authorization: Basic <redacted>" trace
269 '
270
271 test_expect_success 'GIT_CURL_VERBOSE redacts auth details' '
272 rm -rf redact-auth trace &&
273 set_askpass user@host pass@host &&
274 GIT_CURL_VERBOSE=1 git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth 2>trace &&
275 expect_askpass both user%40host &&
276
277 # Ensure that there is no "Basic" followed by a base64 string, but that
278 # the auth details are redacted
279 test_grep ! -i "Authorization: Basic [0-9a-zA-Z+/]" trace &&
280 test_grep -i "Authorization: Basic <redacted>" trace
281 '
282
283 test_expect_success 'GIT_TRACE_CURL does not redact auth details if GIT_TRACE_REDACT=0' '
284 rm -rf redact-auth trace &&
285 set_askpass user@host pass@host &&
286 GIT_TRACE_REDACT=0 GIT_TRACE_CURL="$(pwd)/trace" \
287 git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
288 expect_askpass both user%40host &&
289
290 test_grep -i "Authorization: Basic [0-9a-zA-Z+/]" trace
291 '
292
293 test_expect_success 'disable dumb http on server' '
294 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
295 config http.getanyfile false
296 '
297
298 test_expect_success 'GIT_SMART_HTTP can disable smart http' '
299 (GIT_SMART_HTTP=0 &&
300 export GIT_SMART_HTTP &&
301 cd clone &&
302 test_must_fail git fetch)
303 '
304
305 test_expect_success 'invalid Content-Type rejected' '
306 test_must_fail git clone $HTTPD_URL/broken_smart/repo.git 2>actual &&
307 test_grep "not valid:" actual
308 '
309
310 test_expect_success 'create namespaced refs' '
311 test_commit namespaced &&
312 git push public HEAD:refs/namespaces/ns/refs/heads/main &&
313 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
314 symbolic-ref refs/namespaces/ns/HEAD refs/namespaces/ns/refs/heads/main
315 '
316
317 test_expect_success 'smart clone respects namespace' '
318 git clone "$HTTPD_URL/smart_namespace/repo.git" ns-smart &&
319 echo namespaced >expect &&
320 git --git-dir=ns-smart/.git log -1 --format=%s >actual &&
321 test_cmp expect actual
322 '
323
324 test_expect_success 'dumb clone via http-backend respects namespace' '
325 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
326 config http.getanyfile true &&
327 GIT_SMART_HTTP=0 git clone \
328 "$HTTPD_URL/smart_namespace/repo.git" ns-dumb &&
329 echo namespaced >expect &&
330 git --git-dir=ns-dumb/.git log -1 --format=%s >actual &&
331 test_cmp expect actual
332 '
333
334 test_expect_success 'cookies stored in http.cookiefile when http.savecookies set' '
335 cat >cookies.txt <<-\EOF &&
336 127.0.0.1 FALSE /smart_cookies FALSE 0 othername othervalue
337 EOF
338 sort >expect_cookies.txt <<-\EOF &&
339 127.0.0.1 FALSE /smart_cookies FALSE 0 othername othervalue
340 127.0.0.1 FALSE /smart_cookies/repo.git FALSE 0 name value
341 127.0.0.1 FALSE /smart_cookies/repo.git/info FALSE 0 name value
342 EOF
343 git config http.cookiefile cookies.txt &&
344 git config http.savecookies true &&
345
346 test_when_finished "
347 git --git-dir=\"\$HTTPD_DOCUMENT_ROOT_PATH/repo.git\" \
348 tag -d cookie-tag
349 " &&
350 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
351 tag -m "foo" cookie-tag &&
352 git fetch $HTTPD_URL/smart_cookies/repo.git cookie-tag &&
353
354 # Strip trailing slashes from cookie paths to handle output from both
355 # old curl ("/smart_cookies/") and new ("/smart_cookies").
356 HT=" " &&
357 grep "^[^#]" cookies.txt | sed "s,/$HT,$HT," | sort >cookies_clean.txt &&
358 test_cmp expect_cookies.txt cookies_clean.txt
359 '
360
361 test_expect_success 'transfer.hiderefs works over smart-http' '
362 test_commit hidden &&
363 test_commit visible &&
364 git push public HEAD^:refs/heads/a HEAD:refs/heads/b &&
365 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
366 config transfer.hiderefs refs/heads/a &&
367 git clone --bare "$HTTPD_URL/smart/repo.git" hidden.git &&
368 test_must_fail git -C hidden.git rev-parse --verify a &&
369 git -C hidden.git rev-parse --verify b
370 '
371
372 # create an arbitrary number of tags, numbered from tag-$1 to tag-$2
373 create_tags () {
374 rm -f marks &&
375 for i in $(test_seq "$1" "$2")
376 do
377 # don't use here-doc, because it requires a process
378 # per loop iteration
379 echo "commit refs/heads/too-many-refs-$1" &&
380 echo "mark :$i" &&
381 echo "committer git <git@example.com> $i +0000" &&
382 echo "data 0" &&
383 echo "M 644 inline bla.txt" &&
384 echo "data 4" &&
385 echo "bla" &&
386 # make every commit dangling by always
387 # rewinding the branch after each commit
388 echo "reset refs/heads/too-many-refs-$1" &&
389 echo "from :$1"
390 done | git fast-import --export-marks=marks &&
391
392 # now assign tags to all the dangling commits we created above
393 tag=$(perl -e "print \"bla\" x 30") &&
394 sed -e "s|^:\([^ ]*\) \(.*\)$|create refs/tags/$tag-\1 \2|" <marks >input &&
395 git update-ref --stdin <input &&
396 rm input
397 }
398
399 test_expect_success 'create 2,000 tags in the repo' '
400 git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/many-tags.git" &&
401 (
402 cd "$HTTPD_DOCUMENT_ROOT_PATH/many-tags.git" &&
403 create_tags 1 2000
404 )
405 '
406
407 test_expect_success CMDLINE_LIMIT \
408 'clone the 2,000 tag repo to check OS command line overflow' '
409 run_with_limited_cmdline git clone $HTTPD_URL/smart/many-tags.git too-many-refs &&
410 (
411 cd too-many-refs &&
412 git for-each-ref refs/tags >actual &&
413 test_line_count = 2000 actual
414 )
415 '
416
417 test_expect_success 'large fetch-pack requests can be sent using chunked encoding' '
418 GIT_TRACE_CURL=true git -c http.postbuffer=65536 \
419 clone --bare "$HTTPD_URL/smart/repo.git" split.git 2>err &&
420 {
421 test_have_prereq HTTP2 ||
422 test_grep "^=> Send header: Transfer-Encoding: chunked" err
423 }
424 '
425
426 test_expect_success 'test allowreachablesha1inwant' '
427 test_when_finished "rm -rf test_reachable.git" &&
428 server="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
429 main_sha=$(git -C "$server" rev-parse refs/heads/main) &&
430 git -C "$server" config uploadpack.allowreachablesha1inwant 1 &&
431
432 git init --bare test_reachable.git &&
433 git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" &&
434 git -C test_reachable.git fetch origin "$main_sha"
435 '
436
437 test_expect_success 'test allowreachablesha1inwant with unreachable' '
438 test_when_finished "rm -rf test_reachable.git; git reset --hard $(git rev-parse HEAD)" &&
439
440 #create unreachable sha
441 echo content >file2 &&
442 git add file2 &&
443 git commit -m two &&
444 git push public HEAD:refs/heads/doomed &&
445 git push public :refs/heads/doomed &&
446
447 server="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
448 main_sha=$(git -C "$server" rev-parse refs/heads/main) &&
449 git -C "$server" config uploadpack.allowreachablesha1inwant 1 &&
450
451 git init --bare test_reachable.git &&
452 git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" &&
453 # Some protocol versions (e.g. 2) support fetching
454 # unadvertised objects, so restrict this test to v0.
455 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
456 git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
457 '
458
459 test_expect_success 'test allowanysha1inwant with unreachable' '
460 test_when_finished "rm -rf test_reachable.git; git reset --hard $(git rev-parse HEAD)" &&
461
462 #create unreachable sha
463 echo content >file2 &&
464 git add file2 &&
465 git commit -m two &&
466 git push public HEAD:refs/heads/doomed &&
467 git push public :refs/heads/doomed &&
468
469 server="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
470 main_sha=$(git -C "$server" rev-parse refs/heads/main) &&
471 git -C "$server" config uploadpack.allowreachablesha1inwant 1 &&
472
473 git init --bare test_reachable.git &&
474 git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" &&
475 # Some protocol versions (e.g. 2) support fetching
476 # unadvertised objects, so restrict this test to v0.
477 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
478 git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" &&
479
480 git -C "$server" config uploadpack.allowanysha1inwant 1 &&
481 git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
482 '
483
484 test_expect_success EXPENSIVE 'http can handle enormous ref negotiation' '
485 test_when_finished "rm -f tags" &&
486 (
487 cd "$HTTPD_DOCUMENT_ROOT_PATH/many-tags.git" &&
488 create_tags 2001 50000
489 ) &&
490 git -C too-many-refs fetch -q --tags &&
491 (
492 cd "$HTTPD_DOCUMENT_ROOT_PATH/many-tags.git" &&
493 create_tags 50001 100000
494 ) &&
495 git -C too-many-refs fetch -q --tags &&
496 git -C too-many-refs for-each-ref refs/tags >tags &&
497 test_line_count = 100000 tags
498 '
499
500 test_expect_success 'custom http headers' '
501 test_must_fail git -c http.extraheader="x-magic-two: cadabra" \
502 fetch "$HTTPD_URL/smart_headers/repo.git" &&
503 git -c http.extraheader="x-magic-one: abra" \
504 -c http.extraheader="x-magic-two: cadabra" \
505 fetch "$HTTPD_URL/smart_headers/repo.git" &&
506 git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub &&
507 git config -f .gitmodules submodule.sub.path sub &&
508 git config -f .gitmodules submodule.sub.url \
509 "$HTTPD_URL/smart_headers/repo.git" &&
510 git submodule init sub &&
511 test_must_fail git submodule update sub &&
512 git -c http.extraheader="x-magic-one: abra" \
513 -c http.extraheader="x-magic-two: cadabra" \
514 submodule update sub
515 '
516
517 test_expect_success 'using fetch command in remote-curl updates refs' '
518 SERVER="$HTTPD_DOCUMENT_ROOT_PATH/twobranch" &&
519 rm -rf "$SERVER" client &&
520
521 git init "$SERVER" &&
522 test_commit -C "$SERVER" foo &&
523 git -C "$SERVER" update-ref refs/heads/anotherbranch foo &&
524
525 git clone $HTTPD_URL/smart/twobranch client &&
526
527 test_commit -C "$SERVER" bar &&
528 git -C client -c protocol.version=0 fetch &&
529
530 git -C "$SERVER" rev-parse main >expect &&
531 git -C client rev-parse origin/main >actual &&
532 test_cmp expect actual
533 '
534
535 test_expect_success 'fetch by SHA-1 without tag following' '
536 SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
537 rm -rf "$SERVER" client &&
538
539 git init "$SERVER" &&
540 test_commit -C "$SERVER" foo &&
541
542 git clone $HTTPD_URL/smart/server client &&
543
544 test_commit -C "$SERVER" bar &&
545 git -C "$SERVER" rev-parse bar >bar_hash &&
546 git -C client -c protocol.version=0 fetch \
547 --no-tags origin $(cat bar_hash)
548 '
549
550 test_expect_success 'cookies are redacted by default' '
551 rm -rf clone &&
552 echo "Set-Cookie: Foo=1" >cookies &&
553 echo "Set-Cookie: Bar=2" >>cookies &&
554 GIT_TRACE_CURL=true \
555 git -c "http.cookieFile=$(pwd)/cookies" clone \
556 $HTTPD_URL/smart/repo.git clone 2>err &&
557 test_grep -i "Cookie:.*Foo=<redacted>" err &&
558 test_grep -i "Cookie:.*Bar=<redacted>" err &&
559 test_grep ! -i "Cookie:.*Foo=1" err &&
560 test_grep ! -i "Cookie:.*Bar=2" err
561 '
562
563 test_expect_success 'empty values of cookies are also redacted' '
564 rm -rf clone &&
565 echo "Set-Cookie: Foo=" >cookies &&
566 GIT_TRACE_CURL=true \
567 git -c "http.cookieFile=$(pwd)/cookies" clone \
568 $HTTPD_URL/smart/repo.git clone 2>err &&
569 test_grep -i "Cookie:.*Foo=<redacted>" err
570 '
571
572 test_expect_success 'GIT_TRACE_REDACT=0 disables cookie redaction' '
573 rm -rf clone &&
574 echo "Set-Cookie: Foo=1" >cookies &&
575 echo "Set-Cookie: Bar=2" >>cookies &&
576 GIT_TRACE_REDACT=0 GIT_TRACE_CURL=true \
577 git -c "http.cookieFile=$(pwd)/cookies" clone \
578 $HTTPD_URL/smart/repo.git clone 2>err &&
579 test_grep -i "Cookie:.*Foo=1" err &&
580 test_grep -i "Cookie:.*Bar=2" err
581 '
582
583 test_expect_success 'GIT_TRACE_CURL_NO_DATA prevents data from being traced' '
584 rm -rf clone &&
585 GIT_TRACE_CURL=true \
586 git clone $HTTPD_URL/smart/repo.git clone 2>err &&
587 test_grep "=> Send data" err &&
588
589 rm -rf clone &&
590 GIT_TRACE_CURL=true GIT_TRACE_CURL_NO_DATA=1 \
591 git clone $HTTPD_URL/smart/repo.git clone 2>err &&
592 test_grep ! "=> Send data" err
593 '
594
595 test_expect_success 'server-side error detected' '
596 test_must_fail git clone $HTTPD_URL/error_smart/repo.git 2>actual &&
597 test_grep "server-side error" actual
598 '
599
600 test_expect_success 'http auth remembers successful credentials' '
601 rm -f .git-credentials &&
602 test_config credential.helper store &&
603
604 # the first request prompts the user...
605 set_askpass user@host pass@host &&
606 git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
607 expect_askpass both user%40host &&
608
609 # ...and the second one uses the stored value rather than
610 # prompting the user.
611 set_askpass bogus-user bogus-pass &&
612 git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
613 expect_askpass none
614 '
615
616 test_expect_success 'http auth forgets bogus credentials' '
617 # seed credential store with bogus values. In real life,
618 # this would probably come from a password which worked
619 # for a previous request.
620 rm -f .git-credentials &&
621 test_config credential.helper store &&
622 {
623 echo "url=$HTTPD_URL" &&
624 echo "username=bogus" &&
625 echo "password=bogus"
626 } | git credential approve &&
627
628 # we expect this to use the bogus values and fail, never even
629 # prompting the user...
630 set_askpass user@host pass@host &&
631 test_must_fail git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
632 expect_askpass none &&
633
634 # ...but now we should have forgotten the bad value, causing
635 # us to prompt the user again.
636 set_askpass user@host pass@host &&
637 git ls-remote "$HTTPD_URL/auth/smart/repo.git" >/dev/null &&
638 expect_askpass both user%40host
639 '
640
641 test_expect_success 'client falls back from v2 to v0 to match server' '
642 GIT_TRACE_PACKET=$PWD/trace \
643 GIT_TEST_PROTOCOL_VERSION=2 \
644 git clone $HTTPD_URL/smart_v0/repo.git repo-v0 &&
645 # check for v0; there the HEAD symref is communicated in the capability
646 # line; v2 uses a different syntax on each ref advertisement line
647 test_grep symref=HEAD:refs/heads/ trace
648 '
649
650 test_expect_success 'create empty http-accessible SHA-256 repository' '
651 mkdir "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
652 (cd "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
653 git --bare init --object-format=sha256
654 )
655 '
656
657 test_expect_success 'clone empty SHA-256 repository with protocol v2' '
658 rm -fr sha256 &&
659 echo sha256 >expected &&
660 git -c protocol.version=2 clone "$HTTPD_URL/smart/sha256.git" &&
661 git -C sha256 rev-parse --show-object-format >actual &&
662 test_cmp actual expected &&
663 git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
664 test_must_be_empty actual
665 '
666
667 test_expect_success 'clone empty SHA-256 repository with protocol v0' '
668 rm -fr sha256 &&
669 echo sha256 >expected &&
670 GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=0 clone "$HTTPD_URL/smart/sha256.git" &&
671 git -C sha256 rev-parse --show-object-format >actual &&
672 test_cmp actual expected &&
673 git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
674 test_must_be_empty actual
675 '
676
677 test_expect_success 'passing hostname resolution information works' '
678 BOGUS_HOST=gitbogusexamplehost.invalid &&
679 BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&
680 git -c "http.curloptResolve=$BOGUS_HOST:$LIB_HTTPD_PORT:127.0.0.1" ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null
681 '
682
683 # here user%40host is the URL-encoded version of user@host,
684 # which is our intentionally-odd username to catch parsing errors
685 url_user=$HTTPD_URL_USER/auth/smart/repo.git
686 url_userpass=$HTTPD_URL_USER_PASS/auth/smart/repo.git
687 url_userblank=$HTTPD_PROTO://user%40host:@$HTTPD_DEST/auth/smart/repo.git
688 message="URL .*:<redacted>@.* uses plaintext credentials"
689
690 test_expect_success 'clone warns or fails when using username:password' '
691 test_when_finished "rm -rf attempt*" &&
692
693 git -c transfer.credentialsInUrl=allow \
694 clone $url_userpass attempt1 2>err &&
695 test_grep ! "$message" err &&
696
697 git -c transfer.credentialsInUrl=warn \
698 clone $url_userpass attempt2 2>err &&
699 grep "warning: $message" err >warnings &&
700 test_line_count -ge 1 warnings &&
701
702 test_must_fail git -c transfer.credentialsInUrl=die \
703 clone $url_userpass attempt3 2>err &&
704 grep "fatal: $message" err >warnings &&
705 test_line_count -ge 1 warnings &&
706
707 test_must_fail git -c transfer.credentialsInUrl=die \
708 clone $url_userblank attempt4 2>err &&
709 grep "fatal: $message" err >warnings &&
710 test_line_count -ge 1 warnings
711 '
712
713 test_expect_success 'clone does not detect username:password when it is https://username@domain:port/' '
714 test_when_finished "rm -rf attempt1" &&
715
716 # we are relying on lib-httpd for url construction, so document our
717 # assumptions
718 case "$HTTPD_URL_USER" in
719 *:[0-9]*) : ok ;;
720 *) BUG "httpd url does not have port: $HTTPD_URL_USER"
721 esac &&
722
723 git -c transfer.credentialsInUrl=warn clone $url_user attempt1 2>err &&
724 test_grep ! "uses plaintext credentials" err
725 '
726
727 test_expect_success 'fetch warns or fails when using username:password' '
728 git -c transfer.credentialsInUrl=allow fetch $url_userpass 2>err &&
729 test_grep ! "$message" err &&
730
731 git -c transfer.credentialsInUrl=warn fetch $url_userpass 2>err &&
732 grep "warning: $message" err >warnings &&
733 test_line_count -ge 1 warnings &&
734
735 test_must_fail git -c transfer.credentialsInUrl=die \
736 fetch $url_userpass 2>err &&
737 grep "fatal: $message" err >warnings &&
738 test_line_count -ge 1 warnings &&
739
740 test_must_fail git -c transfer.credentialsInUrl=die \
741 fetch $url_userblank 2>err &&
742 grep "fatal: $message" err >warnings &&
743 test_line_count -ge 1 warnings
744 '
745
746
747 test_expect_success 'push warns or fails when using username:password' '
748 git -c transfer.credentialsInUrl=allow push $url_userpass 2>err &&
749 test_grep ! "$message" err &&
750
751 git -c transfer.credentialsInUrl=warn push $url_userpass 2>err &&
752 grep "warning: $message" err >warnings &&
753
754 test_must_fail git -c transfer.credentialsInUrl=die \
755 push $url_userpass 2>err &&
756 grep "fatal: $message" err >warnings &&
757 test_line_count -ge 1 warnings
758 '
759
760 test_expect_success 'no empty path components' '
761 # In the URL, add a trailing slash, and see if git appends yet another
762 # slash.
763 git clone $HTTPD_URL/smart/repo.git/ clone-with-slash &&
764
765 strip_access_log >log &&
766 test_grep ! "//" log
767 '
768
769 test_expect_success 'tag following always works over v0 http' '
770 upstream=$HTTPD_DOCUMENT_ROOT_PATH/tags &&
771 git init "$upstream" &&
772 (
773 cd "$upstream" &&
774 git commit --allow-empty -m base &&
775 git tag not-annotated &&
776 git tag -m foo annotated
777 ) &&
778 git init tags &&
779 git -C tags -c protocol.version=0 \
780 fetch --depth 1 $HTTPD_URL/smart/tags \
781 refs/tags/annotated:refs/tags/annotated &&
782 git -C "$upstream" for-each-ref refs/tags >expect &&
783 git -C tags for-each-ref >actual &&
784 test_cmp expect actual
785 '
786
787 test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '
788 nongit git \
789 -c remote.origin.url="$HTTPD_URL/smart/repo.git" \
790 -c remote.origin.fetch=anything \
791 ls-remote origin
792 '
793
794 test_done