(CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <'test smart pushing over http via http-backend'>)} spids: [13] ) ] spids: [13] ) (C {(.)} {(./test-lib.sh)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:ROOT_PATH) op: Equal rhs: {(DQ ($ VSub_Name '$PWD'))} spids: [23] ) ] spids: [23] ) (C {(.)} {(DQ ($ VSub_Name '$TEST_DIRECTORY')) (/lib-gpg.sh)}) (C {(.)} {(DQ ($ VSub_Name '$TEST_DIRECTORY')) (/lib-httpd.sh)}) (C {(.)} {(DQ ($ VSub_Name '$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)}) (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id:Redir_Great fd:-1 arg_word:{(exp)} spids:[84]) (HereDoc op_id: Redir_DLess fd: -1 body: { (DQ ('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') ) } do_expansion: True here_end: EOF was_filled: True spids: [87] ) ] ) (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'> ) } ) (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(DQ ($ VSub_Name '$HTTPD_DOCUMENT_ROOT_PATH') (/test_repo.git/hooks/update))} spids: [195] ) (HereDoc op_id: Redir_DLess fd: -1 body: {(DQ ('#!/bin/sh\n') ('exit 1\n'))} do_expansion: True here_end: EOF was_filled: True spids: [201] ) ] ) (C {(chmod)} {(a) (Lit_Other '+') (x)} {(DQ ($ VSub_Name '$HTTPD_DOCUMENT_ROOT_PATH') (/test_repo.git/hooks/update))} ) (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id:Redir_Great fd:-1 arg_word:{(exp)} spids:[221]) (HereDoc op_id: Redir_DLess fd: -1 body: { (DQ ('remote: error: hook declined to update refs/heads/dev2\n') ('To http://127.0.0.1:') ($ VSub_Name '$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:") ($ VSub_Name '$LIB_HTTPD_PORT') ("/smart/test_repo.git'\n") ) } do_expansion: True here_end: EOF was_filled: True spids: [224] ) ] ) (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 ($ VSub_Name '$HTTPD_DOCUMENT_ROOT_PATH') (/test_repo.git/hooks/update))}) (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id:Redir_Great fd:-1 arg_word:{(exp)} spids:[268]) (HereDoc op_id: Redir_DLess fd: -1 body: { (DQ ('\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') ) } do_expansion: True here_end: EOF was_filled: True spids: [271] ) ] ) (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 ($ VSub_Name '$HTTPD_DOCUMENT_ROOT_PATH')) (/test_repo.git)} {(DQ ($ VSub_Name '$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)}) ] )