]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5541-http-push-smart.sh
Merge branch 'jk/http-test-fixes'
[thirdparty/git.git] / t / t5541-http-push-smart.sh
CommitLineData
7da4e228
SP
1#!/bin/sh
2#
3# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
4#
5
6test_description='test smart pushing over http via http-backend'
028cb644 7GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
334afbc7
JS
8export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
9
7da4e228
SP
10. ./test-lib.sh
11
7da4e228 12ROOT_PATH="$PWD"
0ea47f9d 13. "$TEST_DIRECTORY"/lib-gpg.sh
7da4e228 14. "$TEST_DIRECTORY"/lib-httpd.sh
d336572f 15. "$TEST_DIRECTORY"/lib-terminal.sh
7da4e228
SP
16start_httpd
17
18test_expect_success 'setup remote repository' '
19 cd "$ROOT_PATH" &&
20 mkdir test_repo &&
21 cd test_repo &&
22 git init &&
23 : >path1 &&
24 git add path1 &&
25 test_tick &&
26 git commit -m initial &&
27 cd - &&
28 git clone --bare test_repo test_repo.git &&
29 cd test_repo.git &&
30 git config http.receivepack true &&
e32a4581 31 git config core.logallrefupdates true &&
7da4e228
SP
32 ORIG_HEAD=$(git rev-parse --verify HEAD) &&
33 cd - &&
34 mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
35'
36
6ac2b3ae
JK
37setup_askpass_helper
38
9ee6bcd3
TRC
39test_expect_success 'clone remote repository' '
40 rm -rf test_repo_clone &&
f2c2c901
MM
41 git clone $HTTPD_URL/smart/test_repo.git test_repo_clone &&
42 (
43 cd test_repo_clone && git config push.default matching
44 )
7da4e228
SP
45'
46
0cc6330d 47test_expect_success 'push to remote repository (standard)' '
77fb36aa
JK
48 # Clear the log, so that the "used receive-pack service" test below
49 # sees just what we did here.
50 >"$HTTPD_ROOT_PATH"/access.log &&
51
7da4e228
SP
52 cd "$ROOT_PATH"/test_repo_clone &&
53 : >path2 &&
54 git add path2 &&
55 test_tick &&
56 git commit -m path2 &&
57 HEAD=$(git rev-parse --verify HEAD) &&
4eee6c6d 58 GIT_TRACE_CURL=true git push -v -v 2>err &&
0cc6330d
TRC
59 ! grep "Expect: 100-continue" err &&
60 grep "POST git-receive-pack ([0-9]* bytes)" err &&
7da4e228
SP
61 (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
62 test $HEAD = $(git rev-parse --verify HEAD))
63'
64
77fb36aa
JK
65test_expect_success 'used receive-pack service' '
66 cat >exp <<-\EOF &&
67 GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
68 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
69 EOF
70
6ec90b5b 71 check_access_log exp
77fb36aa
JK
72'
73
b0c4adcd
LL
74test_expect_success 'push to remote repository (standard) with sending Accept-Language' '
75 cat >exp <<-\EOF &&
76 => Send header: Accept-Language: ko-KR, *;q=0.9
77 => Send header: Accept-Language: ko-KR, *;q=0.9
78 EOF
79
80 cd "$ROOT_PATH"/test_repo_clone &&
81 : >path_lang &&
82 git add path_lang &&
83 test_tick &&
84 git commit -m path_lang &&
85 HEAD=$(git rev-parse --verify HEAD) &&
86 GIT_TRACE_CURL=true LANGUAGE="ko_KR.UTF-8" git push -v -v 2>err &&
87 ! grep "Expect: 100-continue" err &&
88
89 grep "=> Send header: Accept-Language:" err >err.language &&
90 test_cmp exp err.language
91'
92
7da4e228
SP
93test_expect_success 'push already up-to-date' '
94 git push
95'
96
97test_expect_success 'create and delete remote branch' '
98 cd "$ROOT_PATH"/test_repo_clone &&
99 git checkout -b dev &&
100 : >path3 &&
101 git add path3 &&
102 test_tick &&
103 git commit -m dev &&
104 git push origin dev &&
105 git push origin :dev &&
106 test_must_fail git show-ref --verify refs/remotes/origin/dev
107'
108
c36c6285
ÆAB
109test_expect_success 'setup rejected update hook' '
110 test_hook --setup -C "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" update <<-\EOF &&
111 exit 1
112 EOF
5238cbf6 113
c36c6285
ÆAB
114 cat >exp <<-EOF
115 remote: error: hook declined to update refs/heads/dev2
116 To http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git
117 ! [remote rejected] dev2 -> dev2 (hook declined)
118 error: failed to push some refs to '\''http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git'\''
119 EOF
120'
5238cbf6
SP
121
122test_expect_success 'rejected update prints status' '
123 cd "$ROOT_PATH"/test_repo_clone &&
124 git checkout -b dev2 &&
125 : >path4 &&
126 git add path4 &&
127 test_tick &&
128 git commit -m dev2 &&
129 test_must_fail git push origin dev2 2>act &&
130 sed -e "/^remote: /s/ *$//" <act >cmp &&
1108cea7 131 test_cmp exp cmp
5238cbf6
SP
132'
133rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
134
6cbd6e92 135test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
028cb644 136 "$ROOT_PATH"/test_repo_clone main success
19452374 137
08d63a42 138test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' '
7b69079b
TRC
139 # create a dissimilarly-named remote ref so that git is unable to match the
140 # two refs (viz. local, remote) unless an explicit refspec is provided.
028cb644 141 git push origin main:niam &&
7b69079b
TRC
142
143 echo "change changed" > path2 &&
144 git commit -a -m path2 --amend &&
145
028cb644 146 # push main too; this ensures there is at least one '"'push'"' command to
7b69079b 147 # the remote helper and triggers interaction with the helper.
028cb644 148 test_must_fail git push -v origin +main main:niam >output 2>&1'
7b69079b 149
b32227e7 150test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: remote output' '
028cb644
JS
151 grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *main -> main (forced update)$" output &&
152 grep "^ ! \[rejected\] *main -> niam (non-fast-forward)$" output
b32227e7 153'
7b69079b 154
b3e1900a 155test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' '
0aff719f 156 test_i18ngrep "Updates were rejected because" \
9567f082 157 output
7b69079b
TRC
158'
159
0cc6330d 160test_expect_success 'push (chunked)' '
028cb644 161 git checkout main &&
0cc6330d
TRC
162 test_commit commit path3 &&
163 HEAD=$(git rev-parse --verify HEAD) &&
8677b777 164 test_config http.postbuffer 4 &&
0cc6330d
TRC
165 git push -v -v origin $BRANCH 2>err &&
166 grep "POST git-receive-pack (chunked)" err &&
167 (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
168 test $HEAD = $(git rev-parse --verify HEAD))
169'
170
028cb644
JS
171## References of remote: atomic1(1) main(2) collateral(2) other(2)
172## References of local : atomic2(2) main(1) collateral(3) other(2) collateral1(3) atomic(1)
173## Atomic push : main(1) collateral(3) atomic(1)
f38b1684 174test_expect_success 'push --atomic also prevents branch creation, reports collateral' '
3bca1e7f
ES
175 # Setup upstream repo - empty for now
176 d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git &&
177 git init --bare "$d" &&
178 test_config -C "$d" http.receivepack true &&
179 up="$HTTPD_URL"/smart/atomic-branches.git &&
180
6f119424 181 # Tell "$up" about three branches for now
3bca1e7f
ES
182 test_commit atomic1 &&
183 test_commit atomic2 &&
184 git branch collateral &&
6f119424 185 git branch other &&
028cb644 186 git push "$up" atomic1 main collateral other &&
f38b1684 187 git tag -d atomic1 &&
3bca1e7f
ES
188
189 # collateral is a valid push, but should be failed by atomic push
190 git checkout collateral &&
191 test_commit collateral1 &&
192
028cb644
JS
193 # Make main incompatible with upstream to provoke atomic
194 git checkout main &&
3bca1e7f
ES
195 git reset --hard HEAD^ &&
196
197 # Add a new branch which should be failed by atomic push. This is a
198 # regression case.
199 git branch atomic &&
200
201 # --atomic should cause entire push to be rejected
028cb644 202 test_must_fail git push --atomic "$up" main atomic collateral 2>output &&
3bca1e7f
ES
203
204 # the new branch should not have been created upstream
205 test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
206
207 # upstream should still reflect atomic2, the last thing we pushed
208 # successfully
209 git rev-parse atomic2 >expected &&
028cb644
JS
210 # on main...
211 git -C "$d" rev-parse refs/heads/main >actual &&
3bca1e7f
ES
212 test_cmp expected actual &&
213 # ...and collateral.
214 git -C "$d" rev-parse refs/heads/collateral >actual &&
215 test_cmp expected actual &&
216
217 # the failed refs should be indicated to the user
028cb644 218 grep "^ ! .*rejected.* main -> main" output &&
3bca1e7f
ES
219
220 # the collateral failure refs should be indicated to the user
221 grep "^ ! .*rejected.* atomic -> atomic .*atomic push failed" output &&
f38b1684
JX
222 grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output &&
223
224 # never report what we do not push
225 ! grep "^ ! .*rejected.* atomic1 " output &&
226 ! grep "^ ! .*rejected.* other " output
3bca1e7f
ES
227'
228
6f119424 229test_expect_success 'push --atomic fails on server-side errors' '
230 # Use previously set up repository
231 d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git &&
232 test_config -C "$d" http.receivepack true &&
233 up="$HTTPD_URL"/smart/atomic-branches.git &&
234
235 # break ref updates for other on the remote site
236 mkdir "$d/refs/heads/other.lock" &&
237
238 # add the new commit to other
239 git branch -f other collateral &&
240
241 # --atomic should cause entire push to be rejected
242 test_must_fail git push --atomic "$up" atomic other 2>output &&
243
244 # the new branch should not have been created upstream
245 test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
246
247 # upstream should still reflect atomic2, the last thing we pushed
248 # successfully
249 git rev-parse atomic2 >expected &&
250 # ...to other.
251 git -C "$d" rev-parse refs/heads/other >actual &&
252 test_cmp expected actual &&
253
254 # the new branch should not have been created upstream
255 test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
256
257 # the failed refs should be indicated to the user
258 grep "^ ! .*rejected.* other -> other .*atomic transaction failed" output &&
259
260 # the collateral failure refs should be indicated to the user
261 grep "^ ! .*rejected.* atomic -> atomic .*atomic transaction failed" output
262'
263
02f79147
JK
264test_expect_success 'push --all can push to empty repo' '
265 d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
266 git init --bare "$d" &&
267 git --git-dir="$d" config http.receivepack true &&
268 git push --all "$HTTPD_URL"/smart/empty-all.git
269'
270
271test_expect_success 'push --mirror can push to empty repo' '
272 d=$HTTPD_DOCUMENT_ROOT_PATH/empty-mirror.git &&
273 git init --bare "$d" &&
274 git --git-dir="$d" config http.receivepack true &&
275 git push --mirror "$HTTPD_URL"/smart/empty-mirror.git
276'
277
278test_expect_success 'push --all to repo with alternates' '
279 s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
280 d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-all.git &&
281 git clone --bare --shared "$s" "$d" &&
282 git --git-dir="$d" config http.receivepack true &&
283 git --git-dir="$d" repack -adl &&
284 git push --all "$HTTPD_URL"/smart/alternates-all.git
285'
286
287test_expect_success 'push --mirror to repo with alternates' '
288 s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
289 d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-mirror.git &&
290 git clone --bare --shared "$s" "$d" &&
291 git --git-dir="$d" config http.receivepack true &&
292 git --git-dir="$d" repack -adl &&
293 git push --mirror "$HTTPD_URL"/smart/alternates-mirror.git
294'
295
e304aeba
JK
296test_expect_success TTY 'push shows progress when stderr is a tty' '
297 cd "$ROOT_PATH"/test_repo_clone &&
298 test_commit noisy &&
299 test_terminal git push >output 2>&1 &&
bbf47568 300 test_i18ngrep "^Writing objects" output
e304aeba
JK
301'
302
303test_expect_success TTY 'push --quiet silences status and progress' '
c207e34f
CB
304 cd "$ROOT_PATH"/test_repo_clone &&
305 test_commit quiet &&
e304aeba 306 test_terminal git push --quiet >output 2>&1 &&
ec21ac8c 307 test_must_be_empty output
c207e34f
CB
308'
309
e304aeba
JK
310test_expect_success TTY 'push --no-progress silences progress but not status' '
311 cd "$ROOT_PATH"/test_repo_clone &&
312 test_commit no-progress &&
313 test_terminal git push --no-progress >output 2>&1 &&
415c7dd0 314 test_i18ngrep "^To http" output &&
bbf47568 315 test_i18ngrep ! "^Writing objects" output
e304aeba
JK
316'
317
318test_expect_success 'push --progress shows progress to non-tty' '
319 cd "$ROOT_PATH"/test_repo_clone &&
320 test_commit progress &&
321 git push --progress >output 2>&1 &&
415c7dd0 322 test_i18ngrep "^To http" output &&
bbf47568 323 test_i18ngrep "^Writing objects" output
e304aeba
JK
324'
325
e32a4581
JK
326test_expect_success 'http push gives sane defaults to reflog' '
327 cd "$ROOT_PATH"/test_repo_clone &&
328 test_commit reflog-test &&
329 git push "$HTTPD_URL"/smart/test_repo.git &&
330 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
331 log -g -1 --format="%gn <%ge>" >actual &&
332 echo "anonymous <anonymous@http.127.0.0.1>" >expect &&
333 test_cmp expect actual
334'
335
336test_expect_success 'http push respects GIT_COMMITTER_* in reflog' '
337 cd "$ROOT_PATH"/test_repo_clone &&
338 test_commit custom-reflog-test &&
339 git push "$HTTPD_URL"/smart_custom_env/test_repo.git &&
340 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
341 log -g -1 --format="%gn <%ge>" >actual &&
342 echo "Custom User <custom@example.com>" >expect &&
343 test_cmp expect actual
344'
345
6ac2b3ae
JK
346test_expect_success 'push over smart http with auth' '
347 cd "$ROOT_PATH/test_repo_clone" &&
348 echo push-auth-test >expect &&
349 test_commit push-auth-test &&
afbf5ca5 350 set_askpass user@host pass@host &&
6ac2b3ae
JK
351 git push "$HTTPD_URL"/auth/smart/test_repo.git &&
352 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
353 log -1 --format=%s >actual &&
354 expect_askpass both user@host &&
355 test_cmp expect actual
356'
357
b81401c1 358test_expect_success 'push to auth-only-for-push repo' '
4c71009d
JK
359 cd "$ROOT_PATH/test_repo_clone" &&
360 echo push-half-auth >expect &&
361 test_commit push-half-auth &&
afbf5ca5 362 set_askpass user@host pass@host &&
4c71009d
JK
363 git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
364 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
365 log -1 --format=%s >actual &&
366 expect_askpass both user@host &&
367 test_cmp expect actual
368'
369
b0808819
JK
370test_expect_success 'create repo without http.receivepack set' '
371 cd "$ROOT_PATH" &&
372 git init half-auth &&
373 (
374 cd half-auth &&
375 test_commit one
376 ) &&
377 git clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"
378'
379
380test_expect_success 'clone via half-auth-complete does not need password' '
381 cd "$ROOT_PATH" &&
382 set_askpass wrong &&
383 git clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \
384 half-auth-clone &&
385 expect_askpass none
386'
387
388test_expect_success 'push into half-auth-complete requires password' '
389 cd "$ROOT_PATH/half-auth-clone" &&
390 echo two >expect &&
391 test_commit two &&
afbf5ca5 392 set_askpass user@host pass@host &&
b0808819
JK
393 git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
394 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
395 log -1 --format=%s >actual &&
396 expect_askpass both user@host &&
397 test_cmp expect actual
398'
399
26be19ba
JK
400test_expect_success CMDLINE_LIMIT 'push 2000 tags over http' '
401 sha1=$(git rev-parse HEAD) &&
402 test_seq 2000 |
403 sort |
404 sed "s|.*|$sha1 refs/tags/really-long-tag-name-&|" \
405 >.git/packed-refs &&
406 run_with_limited_cmdline git push --mirror
407'
408
0ea47f9d 409test_expect_success GPG 'push with post-receive to inspect certificate' '
f6db603c 410 test_hook -C "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git post-receive <<-\EOF &&
0ea47f9d
JH
411 # discard the update list
412 cat >/dev/null
413 # record the push certificate
414 if test -n "${GIT_PUSH_CERT-}"
415 then
416 git cat-file blob $GIT_PUSH_CERT >../push-cert
417 fi &&
418 cat >../push-cert-status <<E_O_F
419 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
420 KEY=${GIT_PUSH_CERT_KEY-nokey}
421 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
5732373d
JH
422 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
423 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
0ea47f9d 424 E_O_F
f6db603c
ÆAB
425 EOF
426 (
427 cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
5732373d
JH
428 git config receive.certnonceseed sekrit &&
429 git config receive.certnonceslop 30
0ea47f9d
JH
430 ) &&
431 cd "$ROOT_PATH/test_repo_clone" &&
432 test_commit cert-test &&
433 git push --signed "$HTTPD_URL/smart/test_repo.git" &&
434 (
435 cd "$HTTPD_DOCUMENT_ROOT_PATH" &&
5732373d 436 cat <<-\EOF &&
0ea47f9d
JH
437 SIGNER=C O Mitter <committer@example.com>
438 KEY=13B6F51ECDDE430D
439 STATUS=G
5732373d 440 NONCE_STATUS=OK
0ea47f9d 441 EOF
5732373d 442 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" push-cert
0ea47f9d
JH
443 ) >expect &&
444 test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH/push-cert-status"
445'
446
882d49ca 447test_expect_success 'push status output scrubs password' '
68f3c079
JK
448 cd "$ROOT_PATH/test_repo_clone" &&
449 git push --porcelain \
450 "$HTTPD_URL_USER_PASS/smart/test_repo.git" \
451 +HEAD:scrub >status &&
882d49ca
JK
452 # should have been scrubbed down to vanilla URL
453 grep "^To $HTTPD_URL/smart/test_repo.git" status
454'
455
46da295a
JS
456test_expect_success 'clone/fetch scrubs password from reflogs' '
457 cd "$ROOT_PATH" &&
458 git clone "$HTTPD_URL_USER_PASS/smart/test_repo.git" \
459 reflog-test &&
460 cd reflog-test &&
461 test_commit prepare-for-force-fetch &&
462 git switch -c away &&
463 git fetch "$HTTPD_URL_USER_PASS/smart/test_repo.git" \
028cb644 464 +main:main &&
46da295a 465 # should have been scrubbed down to vanilla URL
028cb644 466 git log -g main >reflog &&
46da295a
JS
467 grep "$HTTPD_URL" reflog &&
468 ! grep "$HTTPD_URL_USER_PASS" reflog
469'
470
cd85b447 471test_expect_success 'Non-ASCII branch name can be used with --force-with-lease' '
472 cd "$ROOT_PATH" &&
473 git clone "$HTTPD_URL_USER_PASS/smart/test_repo.git" non-ascii &&
474 cd non-ascii &&
475 git checkout -b rama-de-árbol &&
476 test_commit F &&
477 git push --force-with-lease origin rama-de-árbol &&
478 git ls-remote origin refs/heads/rama-de-árbol >actual &&
479 git ls-remote . refs/heads/rama-de-árbol >expect &&
480 test_cmp expect actual &&
481 git push --delete --force-with-lease origin rama-de-árbol &&
482 git ls-remote origin refs/heads/rama-de-árbol >actual &&
483 test_must_be_empty actual
484'
485
8301266a
JS
486test_expect_success 'colorize errors/hints' '
487 cd "$ROOT_PATH"/test_repo_clone &&
488 test_must_fail git -c color.transport=always -c color.advice=always \
489 -c color.push=always \
028cb644 490 push origin origin/main^:main 2>act &&
8301266a
JS
491 test_decode_color <act >decoded &&
492 test_i18ngrep "<RED>.*rejected.*<RESET>" decoded &&
493 test_i18ngrep "<RED>error: failed to push some refs" decoded &&
494 test_i18ngrep "<YELLOW>hint: " decoded &&
495 test_i18ngrep ! "^hint: " decoded
496'
497
e4c9538a
JK
498test_expect_success 'report error server does not provide ref status' '
499 git init "$HTTPD_DOCUMENT_ROOT_PATH/no_report" &&
500 git -C "$HTTPD_DOCUMENT_ROOT_PATH/no_report" config http.receivepack true &&
501 test_must_fail git push --porcelain \
502 $HTTPD_URL_USER_PASS/smart/no_report \
503 HEAD:refs/tags/will-fail >actual &&
504 test_must_fail git -C "$HTTPD_DOCUMENT_ROOT_PATH/no_report" \
505 rev-parse --verify refs/tags/will-fail &&
506 cat >expect <<-EOF &&
507 To $HTTPD_URL/smart/no_report
c5c3486f 508 ! HEAD:refs/tags/will-fail [remote failure] (remote failed to report status)
e4c9538a
JK
509 Done
510 EOF
511 test_cmp expect actual
512'
513
7da4e228 514test_done