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