(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:test_description) op: assign_op.Equal rhs: {(SQ <'signed push'>)} spids: [4] ) ] ) (C {<.>} {<'./test-lib.sh'>}) (C {<.>} {(DQ ($ Id.VSub_DollarName '$TEST_DIRECTORY')) <'/lib-gpg.sh'>}) (command.ShFunction name: prepare_dst body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp] children: [ (C {<rm>} {<-fr>} {<dst>}) (C {<test_create_repo>} {<dst>}) (C {<git>} {<push>} {<dst>} {<master> <Id.Lit_Colon ':'> <noop>} {<master> <Id.Lit_Colon ':'> <ff>} {<master> <Id.Lit_Colon ':'> <noff>} ) ] ) ] ) ) (C {<test_expect_success>} {<setup>} { (SQ <'\n'> <'\t# master, ff and noff branches pointing at the same commit\n'> <'\ttest_tick &&\n'> <'\tgit commit --allow-empty -m initial &&\n'> <'\n'> <'\tgit checkout -b noop &&\n'> <'\tgit checkout -b ff &&\n'> <'\tgit checkout -b noff &&\n'> <'\n'> <'\t# noop stays the same, ff advances, noff rewrites\n'> <'\ttest_tick &&\n'> <'\tgit commit --allow-empty --amend -m rewritten &&\n'> <'\tgit checkout ff &&\n'> <'\n'> <'\ttest_tick &&\n'> <'\tgit commit --allow-empty -m second\n'> ) } ) (C {<test_expect_success>} {(SQ <'unsigned push does not send push certificate'>)} { (SQ <'\n'> <'\tprepare_dst &&\n'> <'\tmkdir -p dst/.git/hooks &&\n'> <'\twrite_script dst/.git/hooks/post-receive <<-\\EOF &&\n'> <'\t# discard the update list\n'> <'\tcat >/dev/null\n'> <'\t# record the push certificate\n'> <'\tif test -n "${GIT_PUSH_CERT-}"\n'> <'\tthen\n'> <'\t\tgit cat-file blob $GIT_PUSH_CERT >../push-cert\n'> <'\tfi\n'> <'\tEOF\n'> <'\n'> <'\tgit push dst noop ff +noff &&\n'> <'\t! test -f dst/push-cert\n'> ) } ) (C {<test_expect_success>} {(SQ <'talking with a receiver without push certificate support'>)} { (SQ <'\n'> <'\tprepare_dst &&\n'> <'\tmkdir -p dst/.git/hooks &&\n'> <'\twrite_script dst/.git/hooks/post-receive <<-\\EOF &&\n'> <'\t# discard the update list\n'> <'\tcat >/dev/null\n'> <'\t# record the push certificate\n'> <'\tif test -n "${GIT_PUSH_CERT-}"\n'> <'\tthen\n'> <'\t\tgit cat-file blob $GIT_PUSH_CERT >../push-cert\n'> <'\tfi\n'> <'\tEOF\n'> <'\n'> <'\tgit push dst noop ff +noff &&\n'> <'\t! test -f dst/push-cert\n'> ) } ) (C {<test_expect_success>} {(SQ <'push --signed fails with a receiver without push certificate support'>)} { (SQ <'\n'> <'\tprepare_dst &&\n'> <'\tmkdir -p dst/.git/hooks &&\n'> <'\ttest_must_fail git push --signed dst noop ff +noff 2>err &&\n'> <'\ttest_i18ngrep "the receiving end does not support" err\n'> ) } ) (C {<test_expect_success>} {<GPG>} {(SQ <'no certificate for a signed push with no update'>)} { (SQ <'\n'> <'\tprepare_dst &&\n'> <'\tmkdir -p dst/.git/hooks &&\n'> <'\twrite_script dst/.git/hooks/post-receive <<-\\EOF &&\n'> <'\tif test -n "${GIT_PUSH_CERT-}"\n'> <'\tthen\n'> <'\t\tgit cat-file blob $GIT_PUSH_CERT >../push-cert\n'> <'\tfi\n'> <'\tEOF\n'> <'\tgit push dst noop &&\n'> <'\t! test -f dst/push-cert\n'> ) } ) (C {<test_expect_success>} {<GPG>} {(SQ <'signed push sends push certificate'>)} { (SQ <'\n'> <'\tprepare_dst &&\n'> <'\tmkdir -p dst/.git/hooks &&\n'> <'\tgit -C dst config receive.certnonceseed sekrit &&\n'> <'\twrite_script dst/.git/hooks/post-receive <<-\\EOF &&\n'> <'\t# discard the update list\n'> <'\tcat >/dev/null\n'> <'\t# record the push certificate\n'> <'\tif test -n "${GIT_PUSH_CERT-}"\n'> <'\tthen\n'> <'\t\tgit cat-file blob $GIT_PUSH_CERT >../push-cert\n'> <'\tfi &&\n'> <'\n'> <'\tcat >../push-cert-status <<E_O_F\n'> <'\tSIGNER=${GIT_PUSH_CERT_SIGNER-nobody}\n'> <'\tKEY=${GIT_PUSH_CERT_KEY-nokey}\n'> <'\tSTATUS=${GIT_PUSH_CERT_STATUS-nostatus}\n'> <'\tNONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}\n'> <'\tNONCE=${GIT_PUSH_CERT_NONCE-nononce}\n'> <'\tE_O_F\n'> <'\n'> <'\tEOF\n'> <'\n'> <'\tgit push --signed dst noop ff +noff &&\n'> <'\n'> <'\t(\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" dst/push-cert\n'> <'\t) >expect &&\n'> <'\n'> <'\tgrep "$(git rev-parse noop ff) refs/heads/ff" dst/push-cert &&\n'> <'\tgrep "$(git rev-parse noop noff) refs/heads/noff" dst/push-cert &&\n'> <'\ttest_cmp expect dst/push-cert-status\n'> ) } ) (C {<test_expect_success>} {<GPG>} {(SQ <'fail without key and heed user.signingkey'>)} { (SQ <'\n'> <'\tprepare_dst &&\n'> <'\tmkdir -p dst/.git/hooks &&\n'> <'\tgit -C dst config receive.certnonceseed sekrit &&\n'> <'\twrite_script dst/.git/hooks/post-receive <<-\\EOF &&\n'> <'\t# discard the update list\n'> <'\tcat >/dev/null\n'> <'\t# record the push certificate\n'> <'\tif test -n "${GIT_PUSH_CERT-}"\n'> <'\tthen\n'> <'\t\tgit cat-file blob $GIT_PUSH_CERT >../push-cert\n'> <'\tfi &&\n'> <'\n'> <'\tcat >../push-cert-status <<E_O_F\n'> <'\tSIGNER=${GIT_PUSH_CERT_SIGNER-nobody}\n'> <'\tKEY=${GIT_PUSH_CERT_KEY-nokey}\n'> <'\tSTATUS=${GIT_PUSH_CERT_STATUS-nostatus}\n'> <'\tNONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}\n'> <'\tNONCE=${GIT_PUSH_CERT_NONCE-nononce}\n'> <'\tE_O_F\n'> <'\n'> <'\tEOF\n'> <'\n'> <'\tunset GIT_COMMITTER_EMAIL &&\n'> <'\tgit config user.email hasnokey@nowhere.com &&\n'> <'\ttest_must_fail git push --signed dst noop ff +noff &&\n'> <'\tgit config user.signingkey committer@example.com &&\n'> <'\tgit push --signed dst noop ff +noff &&\n'> <'\n'> <'\t(\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" dst/push-cert\n'> <'\t) >expect &&\n'> <'\n'> <'\tgrep "$(git rev-parse noop ff) refs/heads/ff" dst/push-cert &&\n'> <'\tgrep "$(git rev-parse noop noff) refs/heads/noff" dst/push-cert &&\n'> <'\ttest_cmp expect dst/push-cert-status\n'> ) } ) (C {<test_done>}) ] )