(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'test_description='> name:test_description) op: assign_op.Equal rhs: {(SQ <'test smart pushing over http via http-backend'>)} spids: [13] ) ] redirects: [] ) (C {<.>} {<'./test-lib.sh'>}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'ROOT_PATH='> name:ROOT_PATH) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName PWD))} spids: [23] ) ] redirects: [] ) (C {<.>} {(DQ ($ Id.VSub_DollarName TEST_DIRECTORY)) <'/lib-gpg.sh'>}) (C {<.>} {(DQ ($ Id.VSub_DollarName TEST_DIRECTORY)) <'/lib-httpd.sh'>}) (C {<.>} {(DQ ($ Id.VSub_DollarName TEST_DIRECTORY)) <'/lib-terminal.sh'>}) (C {<start_httpd>}) (C {<test_expect_success>} {(SQ <'setup remote repository'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH" &&\n'> <'\tmkdir test_repo &&\n'> <'\tcd test_repo &&\n'> <'\tgit init &&\n'> <'\t: >path1 &&\n'> <'\tgit add path1 &&\n'> <'\ttest_tick &&\n'> <'\tgit commit -m initial &&\n'> <'\tcd - &&\n'> <'\tgit clone --bare test_repo test_repo.git &&\n'> <'\tcd test_repo.git &&\n'> <'\tgit config http.receivepack true &&\n'> <'\tgit config core.logallrefupdates true &&\n'> <'\tORIG_HEAD=$(git rev-parse --verify HEAD) &&\n'> <'\tcd - &&\n'> <'\tmv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"\n'> ) } ) (C {<setup_askpass_helper>}) (command.Simple words: [{<cat>}] redirects: [ (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<exp>}) (redir op: <Id.Redir_DLess '<<'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {<EOF>} here_end_span_id: 93 stdin_parts: [ <'GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200\n'> <'POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200\n'> ] ) ) ] more_env: [] do_fork: T ) (C {<test_expect_success>} {(SQ <'no empty path components'>)} { (SQ <'\n'> <'\t# In the URL, add a trailing slash, and see if git appends yet another\n'> <'\t# slash.\n'> <'\tcd "$ROOT_PATH" &&\n'> <'\tgit clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&\n'> <'\n'> <'\tsed -e "\n'> <'\t\ts/^.* \\"//\n'> <'\t\ts/\\"//\n'> <'\t\ts/ [1-9][0-9]*\\$//\n'> <'\t\ts/^GET /GET /\n'> <'\t" >act <"$HTTPD_ROOT_PATH"/access.log &&\n'> <'\n'> <'\t# Clear the log, so that it does not affect the "used receive-pack\n'> <'\t# service" test which reads the log too.\n'> <'\t#\n'> <'\t# We do this before the actual comparison to ensure the log is cleared.\n'> <'\techo > "$HTTPD_ROOT_PATH"/access.log &&\n'> <'\n'> <'\ttest_cmp exp act\n'> ) } ) (C {<test_expect_success>} {(SQ <'clone remote repository'>)} { (SQ <'\n'> <'\trm -rf test_repo_clone &&\n'> <'\tgit clone $HTTPD_URL/smart/test_repo.git test_repo_clone &&\n'> <'\t(\n'> <'\t\tcd test_repo_clone && git config push.default matching\n'> <'\t)\n'> ) } ) (C {<test_expect_success>} {(SQ <'push to remote repository (standard)'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\t: >path2 &&\n'> <'\tgit add path2 &&\n'> <'\ttest_tick &&\n'> <'\tgit commit -m path2 &&\n'> <'\tHEAD=$(git rev-parse --verify HEAD) &&\n'> <'\tGIT_TRACE_CURL=true git push -v -v 2>err &&\n'> <'\t! grep "Expect: 100-continue" err &&\n'> <'\tgrep "POST git-receive-pack ([0-9]* bytes)" err &&\n'> <'\t(cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&\n'> <'\t test $HEAD = $(git rev-parse --verify HEAD))\n'> ) } ) (C {<test_expect_success>} {(SQ <'push already up-to-date'>)} {(SQ <'\n'> <'\tgit push\n'>)}) (C {<test_expect_success>} {(SQ <'create and delete remote branch'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\tgit checkout -b dev &&\n'> <'\t: >path3 &&\n'> <'\tgit add path3 &&\n'> <'\ttest_tick &&\n'> <'\tgit commit -m dev &&\n'> <'\tgit push origin dev &&\n'> <'\tgit push origin :dev &&\n'> <'\ttest_must_fail git show-ref --verify refs/remotes/origin/dev\n'> ) } ) (command.Simple words: [{<cat>}] redirects: [ (redir op: <Id.Redir_Great '>'> loc: (redir_loc.Fd fd:1) arg: {(DQ ($ Id.VSub_DollarName HTTPD_DOCUMENT_ROOT_PATH) <'/test_repo.git/hooks/update'>)} ) (redir op: <Id.Redir_DLess '<<'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {<EOF>} here_end_span_id: 208 stdin_parts: [<'#!/bin/sh\n'> <'exit 1\n'>] ) ) ] more_env: [] do_fork: T ) (C {<chmod>} {<a> <Id.Lit_Other '+'> <x>} {(DQ ($ Id.VSub_DollarName HTTPD_DOCUMENT_ROOT_PATH) <'/test_repo.git/hooks/update'>)} ) (command.Simple words: [{<cat>}] redirects: [ (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<exp>}) (redir op: <Id.Redir_DLess '<<'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {<EOF>} here_end_span_id: 238 stdin_parts: [ <'remote: error: hook declined to update refs/heads/dev2\n'> <'To http://127.0.0.1:'> ($ Id.VSub_DollarName LIB_HTTPD_PORT) <'/smart/test_repo.git\n'> <' ! [remote rejected] dev2 -> dev2 (hook declined)\n'> <'error: failed to push some refs to \'http://127.0.0.1:'> ($ Id.VSub_DollarName LIB_HTTPD_PORT) <'/smart/test_repo.git\'\n'> ] ) ) ] more_env: [] do_fork: T ) (C {<test_expect_success>} {(SQ <'rejected update prints status'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\tgit checkout -b dev2 &&\n'> <'\t: >path4 &&\n'> <'\tgit add path4 &&\n'> <'\ttest_tick &&\n'> <'\tgit commit -m dev2 &&\n'> <'\ttest_must_fail git push origin dev2 2>act &&\n'> <'\tsed -e "/^remote: /s/ *$//" <act >cmp &&\n'> <'\ttest_i18ncmp exp cmp\n'> ) } ) (C {<rm>} {<-f>} {(DQ ($ Id.VSub_DollarName HTTPD_DOCUMENT_ROOT_PATH) <'/test_repo.git/hooks/update'>)} ) (command.Simple words: [{<cat>}] redirects: [ (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<exp>}) (redir op: <Id.Redir_DLess '<<'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {<EOF>} here_end_span_id: 290 stdin_parts: [ <'\n'> <'GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200\n'> <'POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200\n'> <'GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200\n'> <'POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200\n'> <'GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200\n'> <'GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200\n'> <'POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200\n'> <'GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200\n'> <'POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200\n'> <'GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200\n'> <'POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200\n'> ] ) ) ] more_env: [] do_fork: T ) (C {<test_expect_success>} {(SQ <'used receive-pack service'>)} { (SQ <'\n'> <'\tsed -e "\n'> <'\t\ts/^.* \\"//\n'> <'\t\ts/\\"//\n'> <'\t\ts/ [1-9][0-9]*\\$//\n'> <'\t\ts/^GET /GET /\n'> <'\t" >act <"$HTTPD_ROOT_PATH"/access.log &&\n'> <'\ttest_cmp exp act\n'> ) } ) (C {<test_http_push_nonff>} {(DQ ($ Id.VSub_DollarName HTTPD_DOCUMENT_ROOT_PATH)) <'/test_repo.git'>} {(DQ ($ Id.VSub_DollarName ROOT_PATH)) <'/test_repo_clone'>} {<master>} {<success>} ) (C {<test_expect_success>} {(SQ <'push fails for non-fast-forward refs unmatched by remote helper'>)} { (SQ <'\n'> <'\t# create a dissimilarly-named remote ref so that git is unable to match the\n'> <'\t# two refs (viz. local, remote) unless an explicit refspec is provided.\n'> <'\tgit push origin master:retsam &&\n'> <'\n'> <'\techo "change changed" > path2 &&\n'> <'\tgit commit -a -m path2 --amend &&\n'> <'\n'> <'\t# push master too; this ensures there is at least one '> ) (DQ <'\'push\''>) (SQ <' command to\n'> <'\t# the remote helper and triggers interaction with the helper.\n'> <'\ttest_must_fail git push -v origin +master master:retsam >output 2>&1'> ) } ) (C {<test_expect_success>} {(SQ <'push fails for non-fast-forward refs unmatched by remote helper: remote output'>)} { (SQ <'\n'> < '\tgrep "^ + [a-f0-9]*\\.\\.\\.[a-f0-9]* *master -> master (forced update)$" output &&\n' > <'\tgrep "^ ! \\[rejected\\] *master -> retsam (non-fast-forward)$" output\n'> ) } ) (C {<test_expect_success>} {(SQ <'push fails for non-fast-forward refs unmatched by remote helper: our output'>)} {(SQ <'\n'> <'\ttest_i18ngrep "Updates were rejected because" \\\n'> <'\t\toutput\n'>)} ) (C {<test_expect_success>} {(SQ <'push (chunked)'>)} { (SQ <'\n'> <'\tgit checkout master &&\n'> <'\ttest_commit commit path3 &&\n'> <'\tHEAD=$(git rev-parse --verify HEAD) &&\n'> <'\ttest_config http.postbuffer 4 &&\n'> <'\tgit push -v -v origin $BRANCH 2>err &&\n'> <'\tgrep "POST git-receive-pack (chunked)" err &&\n'> <'\t(cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&\n'> <'\t test $HEAD = $(git rev-parse --verify HEAD))\n'> ) } ) (C {<test_expect_success>} {(SQ <'push --all can push to empty repo'>)} { (SQ <'\n'> <'\td=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&\n'> <'\tgit init --bare "$d" &&\n'> <'\tgit --git-dir="$d" config http.receivepack true &&\n'> <'\tgit push --all "$HTTPD_URL"/smart/empty-all.git\n'> ) } ) (C {<test_expect_success>} {(SQ <'push --mirror can push to empty repo'>)} { (SQ <'\n'> <'\td=$HTTPD_DOCUMENT_ROOT_PATH/empty-mirror.git &&\n'> <'\tgit init --bare "$d" &&\n'> <'\tgit --git-dir="$d" config http.receivepack true &&\n'> <'\tgit push --mirror "$HTTPD_URL"/smart/empty-mirror.git\n'> ) } ) (C {<test_expect_success>} {(SQ <'push --all to repo with alternates'>)} { (SQ <'\n'> <'\ts=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&\n'> <'\td=$HTTPD_DOCUMENT_ROOT_PATH/alternates-all.git &&\n'> <'\tgit clone --bare --shared "$s" "$d" &&\n'> <'\tgit --git-dir="$d" config http.receivepack true &&\n'> <'\tgit --git-dir="$d" repack -adl &&\n'> <'\tgit push --all "$HTTPD_URL"/smart/alternates-all.git\n'> ) } ) (C {<test_expect_success>} {(SQ <'push --mirror to repo with alternates'>)} { (SQ <'\n'> <'\ts=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&\n'> <'\td=$HTTPD_DOCUMENT_ROOT_PATH/alternates-mirror.git &&\n'> <'\tgit clone --bare --shared "$s" "$d" &&\n'> <'\tgit --git-dir="$d" config http.receivepack true &&\n'> <'\tgit --git-dir="$d" repack -adl &&\n'> <'\tgit push --mirror "$HTTPD_URL"/smart/alternates-mirror.git\n'> ) } ) (C {<test_expect_success>} {<TTY>} {(SQ <'push shows progress when stderr is a tty'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\ttest_commit noisy &&\n'> <'\ttest_terminal git push >output 2>&1 &&\n'> <'\ttest_i18ngrep "^Writing objects" output\n'> ) } ) (C {<test_expect_success>} {<TTY>} {(SQ <'push --quiet silences status and progress'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\ttest_commit quiet &&\n'> <'\ttest_terminal git push --quiet >output 2>&1 &&\n'> <'\ttest_cmp /dev/null output\n'> ) } ) (C {<test_expect_success>} {<TTY>} {(SQ <'push --no-progress silences progress but not status'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\ttest_commit no-progress &&\n'> <'\ttest_terminal git push --no-progress >output 2>&1 &&\n'> <'\ttest_i18ngrep "^To http" output &&\n'> <'\ttest_i18ngrep ! "^Writing objects"\n'> ) } ) (C {<test_expect_success>} {(SQ <'push --progress shows progress to non-tty'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\ttest_commit progress &&\n'> <'\tgit push --progress >output 2>&1 &&\n'> <'\ttest_i18ngrep "^To http" output &&\n'> <'\ttest_i18ngrep "^Writing objects" output\n'> ) } ) (C {<test_expect_success>} {(SQ <'http push gives sane defaults to reflog'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\ttest_commit reflog-test &&\n'> <'\tgit push "$HTTPD_URL"/smart/test_repo.git &&\n'> <'\tgit --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \\\n'> <'\t\tlog -g -1 --format="%gn <%ge>" >actual &&\n'> <'\techo "anonymous <anonymous@http.127.0.0.1>" >expect &&\n'> <'\ttest_cmp expect actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'http push respects GIT_COMMITTER_* in reflog'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH"/test_repo_clone &&\n'> <'\ttest_commit custom-reflog-test &&\n'> <'\tgit push "$HTTPD_URL"/smart_custom_env/test_repo.git &&\n'> <'\tgit --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \\\n'> <'\t\tlog -g -1 --format="%gn <%ge>" >actual &&\n'> <'\techo "Custom User <custom@example.com>" >expect &&\n'> <'\ttest_cmp expect actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'push over smart http with auth'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH/test_repo_clone" &&\n'> <'\techo push-auth-test >expect &&\n'> <'\ttest_commit push-auth-test &&\n'> <'\tset_askpass user@host pass@host &&\n'> <'\tgit push "$HTTPD_URL"/auth/smart/test_repo.git &&\n'> <'\tgit --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \\\n'> <'\t\tlog -1 --format=%s >actual &&\n'> <'\texpect_askpass both user@host &&\n'> <'\ttest_cmp expect actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'push to auth-only-for-push repo'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH/test_repo_clone" &&\n'> <'\techo push-half-auth >expect &&\n'> <'\ttest_commit push-half-auth &&\n'> <'\tset_askpass user@host pass@host &&\n'> <'\tgit push "$HTTPD_URL"/auth-push/smart/test_repo.git &&\n'> <'\tgit --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \\\n'> <'\t\tlog -1 --format=%s >actual &&\n'> <'\texpect_askpass both user@host &&\n'> <'\ttest_cmp expect actual\n'> ) } ) (C {<test_expect_success>} {(SQ <'create repo without http.receivepack set'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH" &&\n'> <'\tgit init half-auth &&\n'> <'\t(\n'> <'\t\tcd half-auth &&\n'> <'\t\ttest_commit one\n'> <'\t) &&\n'> <'\tgit clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"\n'> ) } ) (C {<test_expect_success>} {(SQ <'clone via half-auth-complete does not need password'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH" &&\n'> <'\tset_askpass wrong &&\n'> <'\tgit clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \\\n'> <'\t\thalf-auth-clone &&\n'> <'\texpect_askpass none\n'> ) } ) (C {<test_expect_success>} {(SQ <'push into half-auth-complete requires password'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH/half-auth-clone" &&\n'> <'\techo two >expect &&\n'> <'\ttest_commit two &&\n'> <'\tset_askpass user@host pass@host &&\n'> <'\tgit push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&\n'> <'\tgit --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \\\n'> <'\t\tlog -1 --format=%s >actual &&\n'> <'\texpect_askpass both user@host &&\n'> <'\ttest_cmp expect actual\n'> ) } ) (C {<test_expect_success>} {<CMDLINE_LIMIT>} {(SQ <'push 2000 tags over http'>)} { (SQ <'\n'> <'\tsha1=$(git rev-parse HEAD) &&\n'> <'\ttest_seq 2000 |\n'> <'\t sort |\n'> <'\t sed "s|.*|$sha1 refs/tags/really-long-tag-name-&|" \\\n'> <'\t >.git/packed-refs &&\n'> <'\trun_with_limited_cmdline git push --mirror\n'> ) } ) (C {<test_expect_success>} {<GPG>} {(SQ <'push with post-receive to inspect certificate'>)} { (SQ <'\n'> <'\t(\n'> <'\t\tcd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&\n'> <'\t\tmkdir -p hooks &&\n'> <'\t\twrite_script hooks/post-receive <<-\\EOF &&\n'> <'\t\t# discard the update list\n'> <'\t\tcat >/dev/null\n'> <'\t\t# record the push certificate\n'> <'\t\tif test -n "${GIT_PUSH_CERT-}"\n'> <'\t\tthen\n'> <'\t\t\tgit cat-file blob $GIT_PUSH_CERT >../push-cert\n'> <'\t\tfi &&\n'> <'\t\tcat >../push-cert-status <<E_O_F\n'> <'\t\tSIGNER=${GIT_PUSH_CERT_SIGNER-nobody}\n'> <'\t\tKEY=${GIT_PUSH_CERT_KEY-nokey}\n'> <'\t\tSTATUS=${GIT_PUSH_CERT_STATUS-nostatus}\n'> <'\t\tNONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}\n'> <'\t\tNONCE=${GIT_PUSH_CERT_NONCE-nononce}\n'> <'\t\tE_O_F\n'> <'\t\tEOF\n'> <'\n'> <'\t\tgit config receive.certnonceseed sekrit &&\n'> <'\t\tgit config receive.certnonceslop 30\n'> <'\t) &&\n'> <'\tcd "$ROOT_PATH/test_repo_clone" &&\n'> <'\ttest_commit cert-test &&\n'> <'\tgit push --signed "$HTTPD_URL/smart/test_repo.git" &&\n'> <'\t(\n'> <'\t\tcd "$HTTPD_DOCUMENT_ROOT_PATH" &&\n'> <'\t\tcat <<-\\EOF &&\n'> <'\t\tSIGNER=C O Mitter <committer@example.com>\n'> <'\t\tKEY=13B6F51ECDDE430D\n'> <'\t\tSTATUS=G\n'> <'\t\tNONCE_STATUS=OK\n'> <'\t\tEOF\n'> <'\t\tsed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" push-cert\n'> <'\t) >expect &&\n'> <'\ttest_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH/push-cert-status"\n'> ) } ) (C {<test_expect_success>} {(SQ <'push status output scrubs password'>)} { (SQ <'\n'> <'\tcd "$ROOT_PATH/test_repo_clone" &&\n'> <'\tgit push --porcelain \\\n'> <'\t\t"$HTTPD_URL_USER_PASS/smart/test_repo.git" \\\n'> <'\t\t+HEAD:scrub >status &&\n'> <'\t# should have been scrubbed down to vanilla URL\n'> <'\tgrep "^To $HTTPD_URL/smart/test_repo.git" status\n'> ) } ) (C {<stop_httpd>}) (C {<test_done>}) ] )