Git fork
at reftables-rust 506 lines 16 kB view raw
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' 7GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 8export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 9 10. ./test-lib.sh 11 12ROOT_PATH="$PWD" 13. "$TEST_DIRECTORY"/lib-gpg.sh 14. "$TEST_DIRECTORY"/lib-httpd.sh 15. "$TEST_DIRECTORY"/lib-terminal.sh 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 && 31 git config core.logallrefupdates true && 32 ORIG_HEAD=$(git rev-parse --verify HEAD) && 33 cd - && 34 mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH" 35' 36 37setup_askpass_helper 38 39test_expect_success 'clone remote repository' ' 40 rm -rf test_repo_clone && 41 git clone $HTTPD_URL/smart/test_repo.git test_repo_clone && 42 ( 43 cd test_repo_clone && git config push.default matching 44 ) 45' 46 47test_expect_success 'push to remote repository (standard)' ' 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 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) && 58 GIT_TRACE_CURL=true git push -v -v 2>err && 59 ! grep "Expect: 100-continue" err && 60 grep "POST git-receive-pack ([0-9]* bytes)" err && 61 (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && 62 test $HEAD = $(git rev-parse --verify HEAD)) 63' 64 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 71 check_access_log exp 72' 73 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 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 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 113 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' 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 && 131 test_cmp exp cmp 132' 133rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" 134 135test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \ 136 "$ROOT_PATH"/test_repo_clone main success 137 138test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' ' 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. 141 git push origin main:niam && 142 143 echo "change changed" > path2 && 144 git commit -a -m path2 --amend && 145 146 # push main too; this ensures there is at least one '"'push'"' command to 147 # the remote helper and triggers interaction with the helper. 148 test_must_fail git push -v origin +main main:niam >output 2>&1' 149 150test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: remote output' ' 151 grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *main -> main (forced update)$" output && 152 grep "^ ! \[rejected\] *main -> niam (non-fast-forward)$" output 153' 154 155test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' ' 156 test_grep "Updates were rejected because" \ 157 output 158' 159 160test_expect_success 'push (chunked)' ' 161 git checkout main && 162 test_commit commit path3 && 163 HEAD=$(git rev-parse --verify HEAD) && 164 test_config http.postbuffer 4 && 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 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) 174test_expect_success 'push --atomic also prevents branch creation, reports collateral' ' 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 181 # Tell "$up" about three branches for now 182 test_commit atomic1 && 183 test_commit atomic2 && 184 git branch collateral && 185 git branch other && 186 git push "$up" atomic1 main collateral other && 187 git tag -d atomic1 && 188 189 # collateral is a valid push, but should be failed by atomic push 190 git checkout collateral && 191 test_commit collateral1 && 192 193 # Make main incompatible with upstream to provoke atomic 194 git checkout main && 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 202 test_must_fail git push --atomic "$up" main atomic collateral 2>output && 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 && 210 # on main... 211 git -C "$d" rev-parse refs/heads/main >actual && 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 218 grep "^ ! .*rejected.* main -> main" output && 219 220 # the collateral failure refs should be indicated to the user 221 grep "^ ! .*rejected.* atomic -> atomic .*atomic push failed" output && 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 227' 228 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 # 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 && 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 245 # The atomic and other branches should not be created upstream. 246 test_must_fail git -C "$d" show-ref --verify refs/heads/atomic && 247 test_must_fail git -C "$d" show-ref --verify refs/heads/other && 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 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 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 && 292 test_grep "^Writing objects" output 293' 294 295test_expect_success TTY 'push --quiet silences status and progress' ' 296 cd "$ROOT_PATH"/test_repo_clone && 297 test_commit quiet && 298 test_terminal git push --quiet >output 2>&1 && 299 test_must_be_empty output 300' 301 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 && 306 test_grep "^To http" output && 307 test_grep ! "^Writing objects" output 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 && 314 test_grep "^To http" output && 315 test_grep "^Writing objects" output 316' 317 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 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 && 342 set_askpass user@host pass@host && 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%40host && 347 test_cmp expect actual 348' 349 350test_expect_success 'push to auth-only-for-push repo' ' 351 cd "$ROOT_PATH/test_repo_clone" && 352 echo push-half-auth >expect && 353 test_commit push-half-auth && 354 set_askpass user@host pass@host && 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%40host && 359 test_cmp expect actual 360' 361 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 && 384 set_askpass user@host pass@host && 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%40host && 389 test_cmp expect actual 390' 391 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 401test_expect_success GPG 'push with post-receive to inspect certificate' ' 402 test_hook -C "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git post-receive <<-\EOF && 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} 414 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus} 415 NONCE=${GIT_PUSH_CERT_NONCE-nononce} 416 E_O_F 417 EOF 418 ( 419 cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && 420 git config receive.certnonceseed sekrit && 421 git config receive.certnonceslop 30 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" && 428 cat <<-\EOF && 429 SIGNER=C O Mitter <committer@example.com> 430 KEY=13B6F51ECDDE430D 431 STATUS=G 432 NONCE_STATUS=OK 433 EOF 434 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" push-cert 435 ) >expect && 436 test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH/push-cert-status" 437' 438 439test_expect_success 'push status output scrubs password' ' 440 cd "$ROOT_PATH/test_repo_clone" && 441 git push --porcelain \ 442 "$HTTPD_URL_USER_PASS/smart/test_repo.git" \ 443 +HEAD:scrub >status && 444 # should have been scrubbed down to vanilla URL 445 grep "^To $HTTPD_URL/smart/test_repo.git" status 446' 447 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" \ 456 +main:main && 457 # should have been scrubbed down to vanilla URL 458 git log -g main >reflog && 459 grep "$HTTPD_URL" reflog && 460 ! grep "$HTTPD_URL_USER_PASS" reflog 461' 462 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 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 \ 482 push origin origin/main^:main 2>act && 483 test_decode_color <act >decoded && 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 488' 489 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 500 ! HEAD:refs/tags/will-fail [remote failure] (remote failed to report status) 501 Done 502 EOF 503 test_cmp expect actual 504' 505 506test_done