diff options
Diffstat (limited to 't/t9001-send-email.sh')
-rwxr-xr-x | t/t9001-send-email.sh | 466 |
1 files changed, 426 insertions, 40 deletions
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index d7634187aa..c09f375288 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -3,6 +3,11 @@ test_description='git send-email' . ./test-lib.sh +if ! test_have_prereq PERL; then + say 'skipping git send-email tests, perl not available' + test_done +fi + PROG='git send-email' test_expect_success \ 'prepare reference tree' \ @@ -35,6 +40,47 @@ test_expect_success 'Extract patches' ' patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1` ' +# Test no confirm early to ensure remaining tests will not hang +test_no_confirm () { + rm -f no_confirm_okay + echo n | \ + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --from="Example <from@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $@ \ + $patches > stdout && + test_must_fail grep "Send this email" stdout && + > no_confirm_okay +} + +# Exit immediately to prevent hang if a no-confirm test fails +check_no_confirm () { + test -f no_confirm_okay || { + say 'No confirm test failed; skipping remaining tests to prevent hanging' + test_done + } +} + +test_expect_success 'No confirm with --suppress-cc' ' + test_no_confirm --suppress-cc=sob +' +check_no_confirm + +test_expect_success 'No confirm with --confirm=never' ' + test_no_confirm --confirm=never +' +check_no_confirm + +# leave sendemail.confirm set to never after this so that none of the +# remaining tests prompt unintentionally. +test_expect_success 'No confirm with sendemail.confirm=never' ' + git config sendemail.confirm never && + test_no_confirm --compose --subject=foo +' +check_no_confirm + test_expect_success 'Send patches' ' git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors ' @@ -47,7 +93,41 @@ cat >expected <<\EOF EOF test_expect_success \ 'Verify commandline' \ - 'diff commandline1 expected' + 'test_cmp expected commandline1' + +test_expect_success 'Send patches with --envelope-sender' ' + clean_fake_sendmail && + git send-email --envelope-sender="Patch Contributer <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors +' + +cat >expected <<\EOF +!patch@example.com! +!-i! +!nobody@example.com! +!author@example.com! +!one@example.com! +!two@example.com! +EOF +test_expect_success \ + 'Verify commandline' \ + 'test_cmp expected commandline1' + +test_expect_success 'Send patches with --envelope-sender=auto' ' + clean_fake_sendmail && + git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors +' + +cat >expected <<\EOF +!nobody@example.com! +!-i! +!nobody@example.com! +!author@example.com! +!one@example.com! +!two@example.com! +EOF +test_expect_success \ + 'Verify commandline' \ + 'test_cmp expected commandline1' cat >expected-show-all-headers <<\EOF 0001-Second.patch @@ -57,10 +137,18 @@ cat >expected-show-all-headers <<\EOF Dry-OK. Log says: Server: relay.example.com MAIL FROM:<from@example.com> -RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<bcc@example.com> +RCPT TO:<to@example.com> +RCPT TO:<cc@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<bcc@example.com> From: Example <from@example.com> To: to@example.com -Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com +Cc: cc@example.com, + A <author@example.com>, + One <one@example.com>, + two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING Message-Id: MESSAGE-ID-STRING @@ -89,6 +177,38 @@ test_expect_success 'Show all headers' ' test_cmp expected-show-all-headers actual-show-all-headers ' +test_expect_success 'Prompting works' ' + clean_fake_sendmail && + (echo "Example <from@example.com>" + echo "to@example.com" + echo "" + ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches \ + 2>errors && + grep "^From: Example <from@example.com>\$" msgtxt1 && + grep "^To: to@example.com\$" msgtxt1 +' + +test_expect_success 'cccmd works' ' + clean_fake_sendmail && + cp $patches cccmd.patch && + echo cccmd--cccmd@example.com >>cccmd.patch && + { + echo "#!$SHELL_PATH" + echo sed -n -e s/^cccmd--//p \"\$1\" + } > cccmd-sed && + chmod +x cccmd-sed && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --cc-cmd=./cccmd-sed \ + --smtp-server="$(pwd)/fake.sendmail" \ + cccmd.patch \ + && + grep "^ cccmd@example.com" msgtxt1 +' + z8=zzzzzzzz z64=$z8$z8$z8$z8$z8$z8$z8$z8 z512=$z64$z64$z64$z64$z64$z64$z64$z64 @@ -116,7 +236,7 @@ test_expect_success 'Author From: in message body' ' --to=nobody@example.com \ --smtp-server="$(pwd)/fake.sendmail" \ $patches && - sed "1,/^$/d" < msgtxt1 > msgbody1 + sed "1,/^\$/d" < msgtxt1 > msgbody1 grep "From: A <author@example.com>" msgbody1 ' @@ -127,7 +247,7 @@ test_expect_success 'Author From: not in message body' ' --to=nobody@example.com \ --smtp-server="$(pwd)/fake.sendmail" \ $patches && - sed "1,/^$/d" < msgtxt1 > msgbody1 + sed "1,/^\$/d" < msgtxt1 > msgbody1 ! grep "From: A <author@example.com>" msgbody1 ' @@ -175,15 +295,13 @@ test_set_editor "$(pwd)/fake-editor" test_expect_success '--compose works' ' clean_fake_sendmail && - echo y | \ - GIT_SEND_EMAIL_NOTTY=1 \ - git send-email \ - --compose --subject foo \ - --from="Example <nobody@example.com>" \ - --to=nobody@example.com \ - --smtp-server="$(pwd)/fake.sendmail" \ - $patches \ - 2>errors + git send-email \ + --compose --subject foo \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches \ + 2>errors ' test_expect_success 'first message is compose text' ' @@ -202,10 +320,17 @@ cat >expected-suppress-sob <<\EOF Dry-OK. Log says: Server: relay.example.com MAIL FROM:<from@example.com> -RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com> +RCPT TO:<to@example.com> +RCPT TO:<cc@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> From: Example <from@example.com> To: to@example.com -Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com +Cc: cc@example.com, + A <author@example.com>, + One <one@example.com>, + two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING Message-Id: MESSAGE-ID-STRING @@ -217,7 +342,7 @@ EOF test_suppression () { git send-email \ --dry-run \ - --suppress-cc=$1 \ + --suppress-cc=$1 ${2+"--suppress-cc=$2"} \ --from="Example <from@example.com>" \ --to=to@example.com \ --smtp-server relay.example.com \ @@ -225,8 +350,8 @@ test_suppression () { sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \ -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \ -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \ - >actual-suppress-$1 && - test_cmp expected-suppress-$1 actual-suppress-$1 + >actual-suppress-$1${2+"-$2"} && + test_cmp expected-suppress-$1${2+"-$2"} actual-suppress-$1${2+"-$2"} } test_expect_success 'sendemail.cc set' ' @@ -242,10 +367,15 @@ cat >expected-suppress-sob <<\EOF Dry-OK. Log says: Server: relay.example.com MAIL FROM:<from@example.com> -RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> From: Example <from@example.com> To: to@example.com -Cc: A <author@example.com>, One <one@example.com>, two@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING Message-Id: MESSAGE-ID-STRING @@ -259,6 +389,41 @@ test_expect_success 'sendemail.cc unset' ' test_suppression sob ' +cat >expected-suppress-cccmd <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<committer@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com, + C O Mitter <committer@example.com> +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success 'sendemail.cccmd' ' + echo echo cc-cmd@example.com > cccmd && + chmod +x cccmd && + git config sendemail.cccmd ./cccmd && + test_suppression cccmd +' + cat >expected-suppress-all <<\EOF 0001-Second.patch Dry-OK. Log says: @@ -284,13 +449,21 @@ cat >expected-suppress-body <<\EOF (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' (mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' (mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +(cc-cmd) Adding cc: cc-cmd@example.com from: './cccmd' Dry-OK. Log says: Server: relay.example.com MAIL FROM:<from@example.com> -RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<cc-cmd@example.com> From: Example <from@example.com> To: to@example.com -Cc: A <author@example.com>, One <one@example.com>, two@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com, + cc-cmd@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING Message-Id: MESSAGE-ID-STRING @@ -303,6 +476,35 @@ test_expect_success '--suppress-cc=body' ' test_suppression body ' +cat >expected-suppress-body-cccmd <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=body --suppress-cc=cccmd' ' + test_suppression body cccmd +' + cat >expected-suppress-sob <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -311,10 +513,15 @@ cat >expected-suppress-sob <<\EOF Dry-OK. Log says: Server: relay.example.com MAIL FROM:<from@example.com> -RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> From: Example <from@example.com> To: to@example.com -Cc: A <author@example.com>, One <one@example.com>, two@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING Message-Id: MESSAGE-ID-STRING @@ -324,6 +531,7 @@ Result: OK EOF test_expect_success '--suppress-cc=sob' ' + git config --unset sendemail.cccmd test_suppression sob ' @@ -336,10 +544,17 @@ cat >expected-suppress-bodycc <<\EOF Dry-OK. Log says: Server: relay.example.com MAIL FROM:<from@example.com> -RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<committer@example.com> From: Example <from@example.com> To: to@example.com -Cc: A <author@example.com>, One <one@example.com>, two@example.com, C O Mitter <committer@example.com> +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com, + C O Mitter <committer@example.com> Subject: [PATCH 1/1] Second. Date: DATE-STRING Message-Id: MESSAGE-ID-STRING @@ -359,10 +574,13 @@ cat >expected-suppress-cc <<\EOF Dry-OK. Log says: Server: relay.example.com MAIL FROM:<from@example.com> -RCPT TO:<to@example.com>,<author@example.com>,<committer@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<committer@example.com> From: Example <from@example.com> To: to@example.com -Cc: A <author@example.com>, C O Mitter <committer@example.com> +Cc: A <author@example.com>, + C O Mitter <committer@example.com> Subject: [PATCH 1/1] Second. Date: DATE-STRING Message-Id: MESSAGE-ID-STRING @@ -375,15 +593,117 @@ test_expect_success '--suppress-cc=cc' ' test_suppression cc ' +test_confirm () { + echo y | \ + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $@ $patches > stdout && + grep "Send this email" stdout +} + +test_expect_success '--confirm=always' ' + test_confirm --confirm=always --suppress-cc=all +' + +test_expect_success '--confirm=auto' ' + test_confirm --confirm=auto +' + +test_expect_success '--confirm=cc' ' + test_confirm --confirm=cc +' + +test_expect_success '--confirm=compose' ' + test_confirm --confirm=compose --compose +' + +test_expect_success 'confirm by default (due to cc)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config --unset sendemail.confirm && + test_confirm + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm by default (due to --compose)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config --unset sendemail.confirm && + test_confirm --suppress-cc=all --compose + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm detects EOF (inform assumes y)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config --unset sendemail.confirm && + rm -fr outdir && + git format-patch -2 -o outdir && + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/*.patch < /dev/null + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm detects EOF (auto causes failure)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config sendemail.confirm auto && + GIT_SEND_EMAIL_NOTTY=1 && + export GIT_SEND_EMAIL_NOTTY && + test_must_fail git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches < /dev/null + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm doesnt loop forever' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config sendemail.confirm auto && + GIT_SEND_EMAIL_NOTTY=1 && + export GIT_SEND_EMAIL_NOTTY && + yes "bogus" | test_must_fail git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'utf8 Cc is rfc2047 encoded' ' + clean_fake_sendmail && + rm -fr outdir && + git format-patch -1 -o outdir --cc="àéìöú <utf8@example.com>" && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/*.patch && + grep "^ " msgtxt1 | + grep "=?UTF-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>" +' + test_expect_success '--compose adds MIME for utf8 body' ' clean_fake_sendmail && (echo "#!$SHELL_PATH" && echo "echo utf8 body: àéìöú >>\"\$1\"" ) >fake-editor-utf8 && chmod +x fake-editor-utf8 && - echo y | \ GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \ - GIT_SEND_EMAIL_NOTTY=1 \ git send-email \ --compose --subject foo \ --from="Example <nobody@example.com>" \ @@ -391,7 +711,7 @@ test_expect_success '--compose adds MIME for utf8 body' ' --smtp-server="$(pwd)/fake.sendmail" \ $patches && grep "^utf8 body" msgtxt1 && - grep "^Content-Type: text/plain; charset=utf-8" msgtxt1 + grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 ' test_expect_success '--compose respects user mime type' ' @@ -405,9 +725,7 @@ test_expect_success '--compose respects user mime type' ' echo " echo utf8 body: àéìöú) >\"\$1\"" ) >fake-editor-utf8-mime && chmod +x fake-editor-utf8-mime && - echo y | \ GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \ - GIT_SEND_EMAIL_NOTTY=1 \ git send-email \ --compose --subject foo \ --from="Example <nobody@example.com>" \ @@ -416,14 +734,12 @@ test_expect_success '--compose respects user mime type' ' $patches && grep "^utf8 body" msgtxt1 && grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 && - ! grep "^Content-Type: text/plain; charset=utf-8" msgtxt1 + ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 ' test_expect_success '--compose adds MIME for utf8 subject' ' clean_fake_sendmail && - echo y | \ GIT_EDITOR="\"$(pwd)/fake-editor\"" \ - GIT_SEND_EMAIL_NOTTY=1 \ git send-email \ --compose --subject utf8-sübjëct \ --from="Example <nobody@example.com>" \ @@ -431,7 +747,7 @@ test_expect_success '--compose adds MIME for utf8 subject' ' --smtp-server="$(pwd)/fake.sendmail" \ $patches && grep "^fake edit" msgtxt1 && - grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1 + grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1 ' test_expect_success 'detects ambiguous reference/file conflict' ' @@ -445,7 +761,7 @@ test_expect_success 'detects ambiguous reference/file conflict' ' test_expect_success 'feed two files' ' rm -fr outdir && git format-patch -2 -o outdir && - GIT_SEND_EMAIL_NOTTY=1 git send-email \ + git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ --to=nobody@example.com \ @@ -461,9 +777,79 @@ test_expect_success 'in-reply-to but no threading' ' --from="Example <nobody@example.com>" \ --to=nobody@example.com \ --in-reply-to="<in-reply-id@example.com>" \ - --no-thread \ + --nothread \ $patches | grep "In-Reply-To: <in-reply-id@example.com>" ' +test_expect_success 'no in-reply-to and no threading' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --nothread \ + $patches $patches >stdout && + ! grep "In-Reply-To: " stdout +' + +test_expect_success 'threading but no chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --thread \ + --nochain-reply-to \ + $patches $patches >stdout && + grep "In-Reply-To: " stdout +' + +test_expect_success 'warning with an implicit --chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + outdir/000?-*.patch 2>errors >out && + grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with an explicit --chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --chain-reply-to \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with an explicit --no-chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --nochain-reply-to \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with sendemail.chainreplyto = false' ' + git config sendemail.chainreplyto false && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with sendemail.chainreplyto = true' ' + git config sendemail.chainreplyto true && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + test_done |