]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5541-http-push-smart.sh
Start the 2.46 cycle
[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' '
6789275d 156 test_grep "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
acf8ea23
JT
235 # Create d/f conflict to break ref updates for other on the remote site.
236 git -C "$d" update-ref -d refs/heads/other &&
237 git -C "$d" update-ref refs/heads/other/conflict HEAD &&
6f119424 238
239 # add the new commit to other
240 git branch -f other collateral &&
241
242 # --atomic should cause entire push to be rejected
243 test_must_fail git push --atomic "$up" atomic other 2>output &&
244
acf8ea23 245 # The atomic and other branches should not be created upstream.
6f119424 246 test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
acf8ea23 247 test_must_fail git -C "$d" show-ref --verify refs/heads/other &&
6f119424 248
249 # the failed refs should be indicated to the user
250 grep "^ ! .*rejected.* other -> other .*atomic transaction failed" output &&
251
252 # the collateral failure refs should be indicated to the user
253 grep "^ ! .*rejected.* atomic -> atomic .*atomic transaction failed" output
254'
255
02f79147
JK
256test_expect_success 'push --all can push to empty repo' '
257 d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
258 git init --bare "$d" &&
259 git --git-dir="$d" config http.receivepack true &&
260 git push --all "$HTTPD_URL"/smart/empty-all.git
261'
262
263test_expect_success 'push --mirror can push to empty repo' '
264 d=$HTTPD_DOCUMENT_ROOT_PATH/empty-mirror.git &&
265 git init --bare "$d" &&
266 git --git-dir="$d" config http.receivepack true &&
267 git push --mirror "$HTTPD_URL"/smart/empty-mirror.git
268'
269
270test_expect_success 'push --all to repo with alternates' '
271 s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
272 d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-all.git &&
273 git clone --bare --shared "$s" "$d" &&
274 git --git-dir="$d" config http.receivepack true &&
275 git --git-dir="$d" repack -adl &&
276 git push --all "$HTTPD_URL"/smart/alternates-all.git
277'
278
279test_expect_success 'push --mirror to repo with alternates' '
280 s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
281 d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-mirror.git &&
282 git clone --bare --shared "$s" "$d" &&
283 git --git-dir="$d" config http.receivepack true &&
284 git --git-dir="$d" repack -adl &&
285 git push --mirror "$HTTPD_URL"/smart/alternates-mirror.git
286'
287
e304aeba
JK
288test_expect_success TTY 'push shows progress when stderr is a tty' '
289 cd "$ROOT_PATH"/test_repo_clone &&
290 test_commit noisy &&
291 test_terminal git push >output 2>&1 &&
6789275d 292 test_grep "^Writing objects" output
e304aeba
JK
293'
294
295test_expect_success TTY 'push --quiet silences status and progress' '
c207e34f
CB
296 cd "$ROOT_PATH"/test_repo_clone &&
297 test_commit quiet &&
e304aeba 298 test_terminal git push --quiet >output 2>&1 &&
ec21ac8c 299 test_must_be_empty output
c207e34f
CB
300'
301
e304aeba
JK
302test_expect_success TTY 'push --no-progress silences progress but not status' '
303 cd "$ROOT_PATH"/test_repo_clone &&
304 test_commit no-progress &&
305 test_terminal git push --no-progress >output 2>&1 &&
6789275d
JH
306 test_grep "^To http" output &&
307 test_grep ! "^Writing objects" output
e304aeba
JK
308'
309
310test_expect_success 'push --progress shows progress to non-tty' '
311 cd "$ROOT_PATH"/test_repo_clone &&
312 test_commit progress &&
313 git push --progress >output 2>&1 &&
6789275d
JH
314 test_grep "^To http" output &&
315 test_grep "^Writing objects" output
e304aeba
JK
316'
317
e32a4581
JK
318test_expect_success 'http push gives sane defaults to reflog' '
319 cd "$ROOT_PATH"/test_repo_clone &&
320 test_commit reflog-test &&
321 git push "$HTTPD_URL"/smart/test_repo.git &&
322 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
323 log -g -1 --format="%gn <%ge>" >actual &&
324 echo "anonymous <anonymous@http.127.0.0.1>" >expect &&
325 test_cmp expect actual
326'
327
328test_expect_success 'http push respects GIT_COMMITTER_* in reflog' '
329 cd "$ROOT_PATH"/test_repo_clone &&
330 test_commit custom-reflog-test &&
331 git push "$HTTPD_URL"/smart_custom_env/test_repo.git &&
332 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
333 log -g -1 --format="%gn <%ge>" >actual &&
334 echo "Custom User <custom@example.com>" >expect &&
335 test_cmp expect actual
336'
337
6ac2b3ae
JK
338test_expect_success 'push over smart http with auth' '
339 cd "$ROOT_PATH/test_repo_clone" &&
340 echo push-auth-test >expect &&
341 test_commit push-auth-test &&
afbf5ca5 342 set_askpass user@host pass@host &&
6ac2b3ae
JK
343 git push "$HTTPD_URL"/auth/smart/test_repo.git &&
344 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
345 log -1 --format=%s >actual &&
346 expect_askpass both user@host &&
347 test_cmp expect actual
348'
349
b81401c1 350test_expect_success 'push to auth-only-for-push repo' '
4c71009d
JK
351 cd "$ROOT_PATH/test_repo_clone" &&
352 echo push-half-auth >expect &&
353 test_commit push-half-auth &&
afbf5ca5 354 set_askpass user@host pass@host &&
4c71009d
JK
355 git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
356 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
357 log -1 --format=%s >actual &&
358 expect_askpass both user@host &&
359 test_cmp expect actual
360'
361
b0808819
JK
362test_expect_success 'create repo without http.receivepack set' '
363 cd "$ROOT_PATH" &&
364 git init half-auth &&
365 (
366 cd half-auth &&
367 test_commit one
368 ) &&
369 git clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"
370'
371
372test_expect_success 'clone via half-auth-complete does not need password' '
373 cd "$ROOT_PATH" &&
374 set_askpass wrong &&
375 git clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \
376 half-auth-clone &&
377 expect_askpass none
378'
379
380test_expect_success 'push into half-auth-complete requires password' '
381 cd "$ROOT_PATH/half-auth-clone" &&
382 echo two >expect &&
383 test_commit two &&
afbf5ca5 384 set_askpass user@host pass@host &&
b0808819
JK
385 git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
386 git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
387 log -1 --format=%s >actual &&
388 expect_askpass both user@host &&
389 test_cmp expect actual
390'
391
26be19ba
JK
392test_expect_success CMDLINE_LIMIT 'push 2000 tags over http' '
393 sha1=$(git rev-parse HEAD) &&
394 test_seq 2000 |
395 sort |
396 sed "s|.*|$sha1 refs/tags/really-long-tag-name-&|" \
397 >.git/packed-refs &&
398 run_with_limited_cmdline git push --mirror
399'
400
0ea47f9d 401test_expect_success GPG 'push with post-receive to inspect certificate' '
f6db603c 402 test_hook -C "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git post-receive <<-\EOF &&
0ea47f9d
JH
403 # discard the update list
404 cat >/dev/null
405 # record the push certificate
406 if test -n "${GIT_PUSH_CERT-}"
407 then
408 git cat-file blob $GIT_PUSH_CERT >../push-cert
409 fi &&
410 cat >../push-cert-status <<E_O_F
411 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
412 KEY=${GIT_PUSH_CERT_KEY-nokey}
413 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
5732373d
JH
414 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
415 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
0ea47f9d 416 E_O_F
f6db603c
ÆAB
417 EOF
418 (
419 cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
5732373d
JH
420 git config receive.certnonceseed sekrit &&
421 git config receive.certnonceslop 30
0ea47f9d
JH
422 ) &&
423 cd "$ROOT_PATH/test_repo_clone" &&
424 test_commit cert-test &&
425 git push --signed "$HTTPD_URL/smart/test_repo.git" &&
426 (
427 cd "$HTTPD_DOCUMENT_ROOT_PATH" &&
5732373d 428 cat <<-\EOF &&
0ea47f9d
JH
429 SIGNER=C O Mitter <committer@example.com>
430 KEY=13B6F51ECDDE430D
431 STATUS=G
5732373d 432 NONCE_STATUS=OK
0ea47f9d 433 EOF
5732373d 434 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" push-cert
0ea47f9d
JH
435 ) >expect &&
436 test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH/push-cert-status"
437'
438
882d49ca 439test_expect_success 'push status output scrubs password' '
68f3c079
JK
440 cd "$ROOT_PATH/test_repo_clone" &&
441 git push --porcelain \
442 "$HTTPD_URL_USER_PASS/smart/test_repo.git" \
443 +HEAD:scrub >status &&
882d49ca
JK
444 # should have been scrubbed down to vanilla URL
445 grep "^To $HTTPD_URL/smart/test_repo.git" status
446'
447
46da295a
JS
448test_expect_success 'clone/fetch scrubs password from reflogs' '
449 cd "$ROOT_PATH" &&
450 git clone "$HTTPD_URL_USER_PASS/smart/test_repo.git" \
451 reflog-test &&
452 cd reflog-test &&
453 test_commit prepare-for-force-fetch &&
454 git switch -c away &&
455 git fetch "$HTTPD_URL_USER_PASS/smart/test_repo.git" \
028cb644 456 +main:main &&
46da295a 457 # should have been scrubbed down to vanilla URL
028cb644 458 git log -g main >reflog &&
46da295a
JS
459 grep "$HTTPD_URL" reflog &&
460 ! grep "$HTTPD_URL_USER_PASS" reflog
461'
462
cd85b447 463test_expect_success 'Non-ASCII branch name can be used with --force-with-lease' '
464 cd "$ROOT_PATH" &&
465 git clone "$HTTPD_URL_USER_PASS/smart/test_repo.git" non-ascii &&
466 cd non-ascii &&
467 git checkout -b rama-de-árbol &&
468 test_commit F &&
469 git push --force-with-lease origin rama-de-árbol &&
470 git ls-remote origin refs/heads/rama-de-árbol >actual &&
471 git ls-remote . refs/heads/rama-de-árbol >expect &&
472 test_cmp expect actual &&
473 git push --delete --force-with-lease origin rama-de-árbol &&
474 git ls-remote origin refs/heads/rama-de-árbol >actual &&
475 test_must_be_empty actual
476'
477
8301266a
JS
478test_expect_success 'colorize errors/hints' '
479 cd "$ROOT_PATH"/test_repo_clone &&
480 test_must_fail git -c color.transport=always -c color.advice=always \
481 -c color.push=always \
028cb644 482 push origin origin/main^:main 2>act &&
8301266a 483 test_decode_color <act >decoded &&
6789275d
JH
484 test_grep "<RED>.*rejected.*<RESET>" decoded &&
485 test_grep "<RED>error: failed to push some refs" decoded &&
486 test_grep "<YELLOW>hint: " decoded &&
487 test_grep ! "^hint: " decoded
8301266a
JS
488'
489
e4c9538a
JK
490test_expect_success 'report error server does not provide ref status' '
491 git init "$HTTPD_DOCUMENT_ROOT_PATH/no_report" &&
492 git -C "$HTTPD_DOCUMENT_ROOT_PATH/no_report" config http.receivepack true &&
493 test_must_fail git push --porcelain \
494 $HTTPD_URL_USER_PASS/smart/no_report \
495 HEAD:refs/tags/will-fail >actual &&
496 test_must_fail git -C "$HTTPD_DOCUMENT_ROOT_PATH/no_report" \
497 rev-parse --verify refs/tags/will-fail &&
498 cat >expect <<-EOF &&
499 To $HTTPD_URL/smart/no_report
c5c3486f 500 ! HEAD:refs/tags/will-fail [remote failure] (remote failed to report status)
e4c9538a
JK
501 Done
502 EOF
503 test_cmp expect actual
504'
505
7da4e228 506test_done