{"thread":{"id":"51687","subject":"[PATCH v2 0/4] format-patch: learn --infer-cover-subject option","startedAt":"2019-08-19T23:52:49Z","lastAt":"2019-10-15T03:45:52Z","messageCount":91,"participants":["Denton Liu","Eric Sunshine","Johannes Sixt","Junio C Hamano","Philip Oakley"],"isPatch":true,"patchVersion":2,"patchTotal":4},"messages":[{"id":"380748","messageId":"cover.1566258525.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":null,"subject":"[PATCH v2 0/4] format-patch: learn --infer-cover-subject option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T23:52:43Z","receivedAt":"2019-08-19T23:52:49Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Thanks for the review, Eric. I've incorporated all of your suggestions\nand, while I was doing that, I found a couple more places for cleanup.\n\nCurrently, format-patch only puts \"*** SUBJECT HERE ***\" when a cover\nletter is generated. However, it is already smart enough to be able to\npopulate the cover letter with the branch description so there's no\nreason why it cannot populate the subject as well.\n\nTeach format-patch the --infer-cover-subject and corresponding\nformat.inferCoverSubject configuration option which will read the\nsubject from the branch description using the same rules as for a commit\nmessage (that is, it will expect a subject line followed by a blank\nline).\n\nAlso includes some other cleanup along the way.\n\nThis was based on patches 1-3 of an earlier patchset I sent[1].\n\nChanges since v1:\n\n* Incorporate Eric's suggestions for cleanup in all patches\n\n* Add patch 3/4 to make it clear what is the default value for\n  format.coverLetter (since format.inferCoverSubject was borrowed from\n  this config but it also did not state what the default value was)\n\n* In 1/4, rename all instances of \"expected\" to \"expect\"\n\n[1]: https://public-inbox.org/git/cover.1558492582.git.liu.denton@gmail.com/\n\n\nDenton Liu (4):\n  t4014: clean up style\n  Doc: add more detail for git-format-patch\n  config/format.txt: make clear the default value of format.coverLetter\n  format-patch: learn --infer-cover-letter option\n\n Documentation/config/format.txt    |   7 +-\n Documentation/git-format-patch.txt |  27 +-\n builtin/log.c                      |  56 ++-\n t/t4014-format-patch.sh            | 766 ++++++++++++++++-------------\n 4 files changed, 481 insertions(+), 375 deletions(-)\n\nRange-diff against v1:\n1:  058f877c34 ! 1:  76a0a274fd t4014: clean up style\n    @@ Commit message\n         Change here-docs from `<<\\EOF` to `<<-\\EOF` so that they can be indented\n         along with the rest of the test case.\n     \n    -    Finally, refactor to remove Git commands upstream of pipe. This way, if\n    -    an invocation of a Git command fails, the return code won't be lost.\n    -    Keep upstream non-Git commands since we have to assume a base level of\n    -    sanity.\n    +    Convert all instances of `cnt=$(... | wc -l) && test $cnt = N` into\n    +    uses of `test_line_count()`.\n    +\n    +    For style, move the ending sq of test cases onto its own line whenever\n    +    they do not conform.\n    +\n    +    Rename output files from \"expected\" to \"expect\" to conform with the\n    +    usual convention.\n    +\n    +    Finally, refactor to remove Git commands upstream of pipe as well as Git\n    +    commands that are in a non-variable-assignment subshell (e.g. `echo\n    +    \"base-commit: $(git rev-parse HEAD)\"`. This way, if an invocation of a\n    +    Git command fails, the return code won't be lost. Keep upstream non-Git\n    +    commands since we have to assume a base level of sanity.\n     \n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n     \n    @@ t/t4014-format-patch.sh: test_expect_success setup '\n      \ttest_tick &&\n      \tgit commit -m \"Master accepts moral equivalent of #2\" &&\n      \n    +@@ t/t4014-format-patch.sh: test_expect_success setup '\n    + test_expect_success \"format-patch --ignore-if-in-upstream\" '\n    + \n    + \tgit format-patch --stdout master..side >patch0 &&\n    +-\tcnt=$(grep \"^From \" patch0 | wc -l) &&\n    +-\ttest $cnt = 3\n    +-\n    ++\tgrep \"^From \" patch0 >from0 &&\n    ++\ttest_line_count = 3 from0\n    + '\n    + \n    + test_expect_success \"format-patch --ignore-if-in-upstream\" '\n    + \n    + \tgit format-patch --stdout \\\n    + \t\t--ignore-if-in-upstream master..side >patch1 &&\n    +-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n    +-\ttest $cnt = 2\n    +-\n    ++\tgrep \"^From \" patch1 >from1 &&\n    ++\ttest_line_count = 2 from1\n    + '\n    + \n    + test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n    + \tgit tag -a v1 -m tag side &&\n    + \tgit tag -a v2 -m tag master &&\n    + \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n    +-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n    +-\ttest $cnt = 2\n    ++\tgrep \"^From \" patch1 >from1 &&\n    ++\ttest_line_count = 2 from1\n    + '\n    + \n    + test_expect_success \"format-patch doesn't consider merge commits\" '\n     @@ t/t4014-format-patch.sh: test_expect_success \"format-patch doesn't consider merge commits\" '\n      \tgit checkout -b merger master &&\n      \ttest_tick &&\n      \tgit merge --no-ff slave &&\n     -\tcnt=$(git format-patch -3 --stdout | grep \"^From \" | wc -l) &&\n    -+\tcnt=$(git format-patch -3 --stdout >patch && grep \"^From \" patch | wc -l) &&\n    - \ttest $cnt = 3\n    +-\ttest $cnt = 3\n    ++\tgit format-patch -3 --stdout >patch &&\n    ++\tgrep \"^From \" patch >from &&\n    ++\ttest_line_count = 3 from\n      '\n      \n    -@@ t/t4014-format-patch.sh: test_expect_success \"format-patch result applies\" '\n    + test_expect_success \"format-patch result applies\" '\n      \n      \tgit checkout -b rebuild-0 master &&\n      \tgit am -3 patch0 &&\n    @@ t/t4014-format-patch.sh: test_expect_success 'reroll count (-v)' '\n      \texpect=\"$1\" &&\n      \tshift &&\n     -\t(git format-patch --stdout \"$@\"; echo $? > status.out) |\n    -+\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n    ++\tgit format-patch --stdout \"$@\" >patch &&\n      \t# Prints everything between the Message-ID and In-Reply-To,\n      \t# and replaces all Message-ID-lookalikes by a sequence number\n      \tperl -ne '\n    @@ t/t4014-format-patch.sh: check_threading () {\n      \t\t}\n      \t\tprint \"---\\n\" if /^From /i;\n     -\t' > actual &&\n    -+\t' >actual &&\n    - \ttest 0 = \"$(cat status.out)\" &&\n    +-\ttest 0 = \"$(cat status.out)\" &&\n    ++\t' <patch >actual &&\n      \ttest_cmp \"$expect\" actual\n      }\n      \n    @@ t/t4014-format-patch.sh: test_expect_success 'format-patch with multiple notes r\n     +\ttest_must_fail git format-patch --name-status 2>output &&\n      \ttest_i18ncmp expect.name-status output &&\n     -\ttest_must_fail git format-patch --check 2> output &&\n    +-\ttest_i18ncmp expect.check output'\n     +\ttest_must_fail git format-patch --check 2>output &&\n    - \ttest_i18ncmp expect.check output'\n    ++\ttest_i18ncmp expect.check output\n    ++'\n      \n      test_expect_success 'format-patch --numstat should produce a patch' '\n     -\tgit format-patch --numstat --stdout master..side > output &&\n    +-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)'\n     +\tgit format-patch --numstat --stdout master..side >output &&\n    - \ttest 5 = $(grep \"^diff --git a/\" output | wc -l)'\n    ++\tgrep \"^diff --git a/\" output >diff &&\n    ++\ttest_line_count = 5 diff\n    ++'\n      \n      test_expect_success 'format-patch -- <path>' '\n    + \tgit format-patch master..side -- file 2>error &&\n     @@ t/t4014-format-patch.sh: test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n      \tgit format-patch --ignore-if-in-upstream HEAD\n      '\n      \n     -git_version=\"$(git --version | sed \"s/.* //\")\"\n    -+git_version=\"$(git --version >version && sed \"s/.* //\" version)\"\n    - \n    +-\n      signature() {\n    ++\tgit_version=\"$(git --version >version && sed \"s/.* //\" version)\" &&\n      \tprintf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n      }\n      \n    @@ t/t4014-format-patch.sh: test_expect_success 'format-patch --ignore-if-in-upstre\n      \tsignature \"my sig\" >expect &&\n      \ttest_cmp expect output\n      '\n    +@@ t/t4014-format-patch.sh: test_expect_success 'format-patch --signature --cover-letter' '\n    + \tgit config --unset-all format.signature &&\n    + \tgit format-patch --stdout --signature=\"my sig\" --cover-letter \\\n    + \t\t-1 >output &&\n    +-\tgrep \"my sig\" output &&\n    +-\ttest 2 = $(grep \"my sig\" output | wc -l)\n    ++\tgrep \"my sig\" output >sig &&\n    ++\ttest_line_count = 2 sig\n    + '\n    + \n    + test_expect_success 'format.signature=\"\" suppresses signatures' '\n     @@ t/t4014-format-patch.sh: append_signoff()\n      \n      test_expect_success 'signoff: commit with no body' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -8:\n     -9:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    -+\tcat <<-\\EOF | sed \"s/EOL$//\" >expected &&\n    +-\ttest_cmp expected actual\n    ++\tcat <<-\\EOF | sed \"s/EOL$//\" >expect &&\n     +\t4:Subject: [PATCH] EOL\n     +\t8:\n     +\t9:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: commit with only subject' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -8:\n     -9:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    -+\tcat >expected <<-\\EOF &&\n    +-\ttest_cmp expected actual\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t9:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: commit with only subject that does not end with NL' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -8:\n     -9:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    -+\tcat >expected <<-\\EOF &&\n    +-\ttest_cmp expected actual\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t9:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: no existing signoffs' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -10:\n     -11:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tbody\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t11:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -10:\n     -11:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    -+\tcat >expected <<-\\EOF &&\n    +-\ttest_cmp expected actual\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t11:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: some random signoff' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -11:Signed-off-by: my@house\n     -12:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tSigned-off-by: my@house\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t11:Signed-off-by: my@house\n     +\t12:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: misc conforming footer elements' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -11:Signed-off-by: my@house\n     -15:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tSigned-off-by: my@house\n     +\t(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n     +\tTested-by: Some One <someone@example.com>\n     +\tBug: 1234\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t11:Signed-off-by: my@house\n     +\t15:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: some random signoff-alike' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -11:\n     -12:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tbody\n     +\tFooled-by-me: my@house\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t11:\n     +\t12:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: not really a signoff' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -10:\n     -11:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tI want to mention about Signed-off-by: here.\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t9:I want to mention about Signed-off-by: here.\n     +\t10:\n     +\t11:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: not really a signoff (2)' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -10:Signed-off-by: example happens to be wrapped here.\n     -11:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tMy unfortunate\n     +\tSigned-off-by: example happens to be wrapped here.\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:Signed-off-by: example happens to be wrapped here.\n     +\t11:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -13:\n     -14:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tA lot of houses.\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t9:Signed-off-by: my@house\n    @@ t/t4014-format-patch.sh: append_signoff()\n     +\t13:\n     +\t14:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: the same signoff at the end' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -10:\n     -11:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tSigned-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t11:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -8:\n     -9:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    -+\tcat >expected <<-\\EOF &&\n    +-\ttest_cmp expected actual\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t9:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: the same signoff NOT at the end' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -11:Signed-off-by: C O Mitter <committer@example.com>\n     -12:Signed-off-by: my@house\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tSigned-off-by: C O Mitter <committer@example.com>\n     +\tSigned-off-by: my@house\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t11:Signed-off-by: C O Mitter <committer@example.com>\n     +\t12:Signed-off-by: my@house\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: tolerate garbage in conforming footer' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -10:\n     -13:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tTested-by: my@house\n     +\tSome Trash\n     +\tSigned-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t13:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: respect trailer config' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -11:\n     -12:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual &&\n     +\tMyfooter: x\n     +\tSome Trash\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t11:\n     +\t12:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual &&\n    ++\ttest_cmp expect actual &&\n      \n      \ttest_config trailer.Myfooter.ifexists add &&\n     -\tappend_signoff <<\\EOF >actual &&\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -8:\n     -11:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tMyfooter: x\n     +\tSome Trash\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t11:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n      test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n    @@ t/t4014-format-patch.sh: append_signoff()\n     -10:\n     -14:Signed-off-by: C O Mitter <committer@example.com>\n     -EOF\n    +-\ttest_cmp expected actual\n     +\tReviewed-id: Noone\n     +\tTested-by: my@house\n     +\tChange-id: Ideadbeef\n     +\tSigned-off-by: C O Mitter <committer@example.com>\n     +\tBug: 1234\n     +\tEOF\n    -+\tcat >expected <<-\\EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\t4:Subject: [PATCH] subject\n     +\t8:\n     +\t10:\n     +\t14:Signed-off-by: C O Mitter <committer@example.com>\n     +\tEOF\n    - \ttest_cmp expected actual\n    ++\ttest_cmp expect actual\n      '\n      \n    + test_expect_success 'format patch ignores color.ui' '\n     @@ t/t4014-format-patch.sh: test_expect_success 'cover letter using branch description (1)' '\n      \tgit checkout rebuild-1 &&\n      \ttest_config branch.rebuild-1.description hello &&\n    @@ t/t4014-format-patch.sh: test_expect_success 'format-patch -o overrides format.o\n      \tgit checkout patchid &&\n     -\tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n     -\tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n    +-\techo >expected &&\n    +-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n    +-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n    +-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n    +-\tsignature >> expected &&\n    +-\ttest_cmp expected actual1 &&\n    +-\ttest_cmp expected actual2 &&\n    ++\n     +\tgit format-patch --stdout --base=HEAD~3 -1 >patch &&\n     +\ttail -n 7 patch >actual1 &&\n    ++\n     +\tgit format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&\n     +\ttail -n 7 patch >actual2 &&\n    - \techo >expected &&\n    - \techo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n    --\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n    --\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n    --\tsignature >> expected &&\n    ++\n    ++\techo >expect &&\n    ++\tgit rev-parse HEAD~3 >commit-id-base &&\n    ++\techo \"base-commit: $(cat commit-id-base)\" >>expect &&\n    ++\n     +\tgit show --patch HEAD~2 >patch &&\n     +\tgit patch-id --stable <patch >patch.id.raw &&\n    -+\tawk \"{print \\$1}\" <patch.id.raw >patch.id &&\n    -+\techo \"prerequisite-patch-id: $(cat patch.id)\" >>expected &&\n    ++\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n    ++\n     +\tgit show --patch HEAD~1 >patch &&\n     +\tgit patch-id --stable <patch >patch.id.raw &&\n    -+\tawk \"{print \\$1}\" <patch.id.raw >patch.id &&\n    -+\techo \"prerequisite-patch-id: $(cat patch.id)\" >>expected &&\n    -+\tsignature >>expected &&\n    - \ttest_cmp expected actual1 &&\n    - \ttest_cmp expected actual2 &&\n    ++\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n    ++\n    ++\tsignature >>expect &&\n    ++\ttest_cmp expect actual1 &&\n    ++\ttest_cmp expect actual2 &&\n    ++\n      \techo >fail &&\n    - \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n    +-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n     -\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n     -\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n    -+\techo \"prerequisite-patch-id: $(\n    -+\t\tgit show --patch HEAD~2 >patch &&\n    -+\t\tgit patch-id --unstable <patch >patch.id.raw &&\n    -+\t\tawk \"{print \\$1}\" <patch.id.raw)\" >>fail &&\n    -+\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 >patch &&\n    -+\t\tgit patch-id --unstable <patch >patch.id.raw &&\n    -+\t\tawk \"{print \\$1}\" <pattch.id.raw)\" >>fail &&\n    - \tsignature >> fail &&\n    +-\tsignature >> fail &&\n    ++\techo \"base-commit: $(cat commit-id-base)\" >>fail &&\n    ++\n    ++\tgit show --patch HEAD~2 >patch &&\n    ++\tgit patch-id --unstable <patch >patch.id.raw &&\n    ++\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n    ++\n    ++\tgit show --patch HEAD~1 >patch &&\n    ++\tgit patch-id --unstable <patch >patch.id.raw &&\n    ++\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n    ++\n    ++\tsignature >>fail &&\n      \t! test_cmp fail actual1 &&\n      \t! test_cmp fail actual2\n    + '\n    +@@ t/t4014-format-patch.sh: test_expect_success 'format-patch --base errors out when base commit is in revis\n    + \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n    + \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n    + \tgrep \"^base-commit:\" patch >actual &&\n    +-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expected &&\n    +-\ttest_cmp expected actual\n    ++\tgit rev-parse HEAD~2 >commit-id-base &&\n    ++\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n    ++\ttest_cmp expect actual\n    + '\n    + \n    + test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '\n    +@@ t/t4014-format-patch.sh: test_expect_success 'format-patch --base errors out when base commit is not ance\n    + \ttest_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&\n    + \tgit format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&\n    + \tgrep \"^base-commit:\" patch >actual &&\n    +-\techo \"base-commit: $(cat commit-id-base)\" >expected &&\n    +-\ttest_cmp expected actual\n    ++\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n    ++\ttest_cmp expect actual\n    + '\n    + \n    + test_expect_success 'format-patch --base=auto' '\n    +@@ t/t4014-format-patch.sh: test_expect_success 'format-patch --base=auto' '\n    + \ttest_commit N2 &&\n    + \tgit format-patch --stdout --base=auto -2 >patch &&\n    + \tgrep \"^base-commit:\" patch >actual &&\n    +-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n    +-\ttest_cmp expected actual\n    ++\tgit rev-parse upstream >commit-id-base &&\n    ++\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n    ++\ttest_cmp expect actual\n    + '\n    + \n    + test_expect_success 'format-patch errors out when history involves criss-cross' '\n    +@@ t/t4014-format-patch.sh: test_expect_success 'format-patch format.useAutoBaseoption' '\n    + \tgit config format.useAutoBase true &&\n    + \tgit format-patch --stdout -1 >patch &&\n    + \tgrep \"^base-commit:\" patch >actual &&\n    +-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n    +-\ttest_cmp expected actual\n    ++\tgit rev-parse upstream >commit-id-base &&\n    ++\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n    ++\ttest_cmp expect actual\n    + '\n    + \n    + test_expect_success 'format-patch --base overrides format.useAutoBase' '\n    +@@ t/t4014-format-patch.sh: test_expect_success 'format-patch --base overrides format.useAutoBase' '\n    + \tgit config format.useAutoBase true &&\n    + \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n    + \tgrep \"^base-commit:\" patch >actual &&\n    +-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expected &&\n    +-\ttest_cmp expected actual\n    ++\tgit rev-parse HEAD~1 >commit-id-base &&\n    ++\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n    ++\ttest_cmp expect actual\n    + '\n    + \n    + test_expect_success 'format-patch --base with --attach' '\n2:  7619da962d ! 2:  fd908bcc01 Doc: add more detail for git-format-patch\n    @@ Commit message\n         Next, while we're at it, surround option arguments with <>.\n     \n         Finally, document the `format.outputDirectory` config and change\n    -    `format.coverletter` to use camelcase.\n    +    `format.coverletter` to use camel case.\n     \n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n     \n    @@ Documentation/git-format-patch.txt: Beware that the default for 'git send-email'\n      \tMake the first mail (or all the mails with `--no-thread`) appear as a\n      \treply to the given Message-Id, which avoids breaking threads to\n      \tprovide a new patch series.\n    -@@ Documentation/git-format-patch.txt: will want to ensure that threading is disabled for `git send-email`.\n    - \n    - --to=<email>::\n    - \tAdd a `To:` header to the email headers. This is in addition\n    --\tto any configured headers, and may be used multiple times.\n    -+\tto any configured headers, and may be used multiple times. The\n    -+\temails given will be used along with any emails given by\n    -+\t`format.to` configurations.\n    - \tThe negated form `--no-to` discards all `To:` headers added so\n    - \tfar (from config or command line).\n    - \n    - --cc=<email>::\n    - \tAdd a `Cc:` header to the email headers. This is in addition\n    --\tto any configured headers, and may be used multiple times.\n    -+\tto any configured headers, and may be used multiple times. The\n    -+\temails given will be used along with any emails given by\n    -+\t`format.cc` configurations.\n    - \tThe negated form `--no-cc` discards all `Cc:` headers added so\n    - \tfar (from config or command line).\n    - \n     @@ Documentation/git-format-patch.txt: you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n      --base=<commit>::\n      \tRecord the base tree information to identify the state the\n      \tpatch series applies to.  See the BASE TREE INFORMATION section\n     -\tbelow for details.\n    -+\tbelow for details. If <commit> is equal to \"auto\", a base commit\n    -+\tis automatically chosen.\n    ++\tbelow for details. If <commit> is \"auto\", a base commit is\n    ++\tautomatically chosen.\n      \n      --root::\n      \tTreat the revision argument as a <revision range>, even if it\n-:  ---------- > 3:  94a778c9aa config/format.txt: make clear the default value of format.coverLetter\n3:  5cc5e354b6 ! 4:  e682bd347a format-patch: infer cover letter from branch description\n    @@ Metadata\n     Author: Denton Liu <liu.denton@gmail.com>\n     \n      ## Commit message ##\n    -    format-patch: infer cover letter from branch description\n    +    format-patch: learn --infer-cover-letter option\n     \n         We used to populate the subject of the cover letter generated by\n         git-format-patch with \"*** SUBJECT HERE ***\". However, if a user submits\n    @@ Documentation/config/format.txt: format.subjectPrefix::\n      \tsubject prefix. Use this variable to change that prefix.\n      \n     +format.inferCoverSubject::\n    -+\tA boolean that controls whether or not to infer the subject for\n    -+\tthe cover letter based on the branch's description. See the\n    -+\t--infer-cover-subject option in linkgit:git-format-patch[1].\n    ++\tA boolean value which lets you enable the\n    ++\t`--infer-cover-subject` option of format-patch by default.\n     +\n      format.signature::\n      \tThe default for format-patch is to output a signature containing\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380749","messageId":"76a0a274fde564f709d294acd7d6da17167f05b5.1566258525.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566258525.git.liu.denton@gmail.com","subject":"[PATCH v2 1/4] t4014: clean up style","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T23:52:46Z","receivedAt":"2019-08-19T23:52:52Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In Git's tests, there is typically no space between the redirection\noperator and the filename. Remove these spaces.\n\nSince output is silenced when running without `-v` and debugging\noutput is useful with `-v`, remove redirections to /dev/null.\n\nChange here-docs from `<<\\EOF` to `<<-\\EOF` so that they can be indented\nalong with the rest of the test case.\n\nConvert all instances of `cnt=$(... | wc -l) && test $cnt = N` into\nuses of `test_line_count()`.\n\nFor style, move the ending sq of test cases onto its own line whenever\nthey do not conform.\n\nRename output files from \"expected\" to \"expect\" to conform with the\nusual convention.\n\nFinally, refactor to remove Git commands upstream of pipe as well as Git\ncommands that are in a non-variable-assignment subshell (e.g. `echo\n\"base-commit: $(git rev-parse HEAD)\"`. This way, if an invocation of a\nGit command fails, the return code won't be lost. Keep upstream non-Git\ncommands since we have to assume a base level of sanity.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n\nThis patch is getting a little unwieldy. Perhaps we could split it into\nseveral smaller patches? Unfortunately, I'm not really sure where a\nlogical place to split it would be.\n\n t/t4014-format-patch.sh | 733 +++++++++++++++++++++-------------------\n 1 file changed, 387 insertions(+), 346 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca7debf1d4..0114608b1f 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -34,7 +34,8 @@ test_expect_success setup '\n \tgit commit -m \"Side changes #3 with \\\\n backslash-n in it.\" &&\n \n \tgit checkout master &&\n-\tgit diff-tree -p C2 | git apply --index &&\n+\tgit diff-tree -p C2 >patch &&\n+\tgit apply --index <patch &&\n \ttest_tick &&\n \tgit commit -m \"Master accepts moral equivalent of #2\" &&\n \n@@ -62,26 +63,24 @@ test_expect_success setup '\n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n \n \tgit format-patch --stdout master..side >patch0 &&\n-\tcnt=$(grep \"^From \" patch0 | wc -l) &&\n-\ttest $cnt = 3\n-\n+\tgrep \"^From \" patch0 >from0 &&\n+\ttest_line_count = 3 from0\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n \n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n-\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n \tgit tag -a v1 -m tag side &&\n \tgit tag -a v2 -m tag master &&\n \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success \"format-patch doesn't consider merge commits\" '\n@@ -96,29 +95,31 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \tgit checkout -b merger master &&\n \ttest_tick &&\n \tgit merge --no-ff slave &&\n-\tcnt=$(git format-patch -3 --stdout | grep \"^From \" | wc -l) &&\n-\ttest $cnt = 3\n+\tgit format-patch -3 --stdout >patch &&\n+\tgrep \"^From \" patch >from &&\n+\ttest_line_count = 3 from\n '\n \n test_expect_success \"format-patch result applies\" '\n \n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n \n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'commit did not screw up the log message' '\n \n-\tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit side >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n \n '\n \n@@ -131,7 +132,8 @@ test_expect_success 'format-patch did not screw up the log message' '\n \n test_expect_success 'replay did not screw up the log message' '\n \n-\tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit rebuild-1 >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n \n '\n \n@@ -141,8 +143,8 @@ test_expect_success 'extra headers' '\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n \" &&\n-\tgit format-patch --stdout master..side > patch2 &&\n-\tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n+\tgit format-patch --stdout master..side >patch2 &&\n+\tsed -e \"/^\\$/q\" patch2 >hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n \n@@ -153,7 +155,7 @@ test_expect_success 'extra headers without newlines' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n-\tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n+\tsed -e \"/^\\$/q\" patch3 >hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n \n@@ -163,8 +165,8 @@ test_expect_success 'extra headers with multiple To:s' '\n \n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n-\tgit format-patch --stdout master..side > patch4 &&\n-\tsed -e \"/^\\$/q\" patch4 > hdrs4 &&\n+\tgit format-patch --stdout master..side >patch4 &&\n+\tsed -e \"/^\\$/q\" patch4 >hdrs4 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>,\\$\" hdrs4 &&\n \tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs4\n '\n@@ -172,72 +174,82 @@ test_expect_success 'extra headers with multiple To:s' '\n test_expect_success 'additional command line cc (ascii)' '\n \n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n \n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_success 'command line headers' '\n \n \tgit config --unset-all format.headers &&\n-\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n+\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side >patch6 &&\n+\tsed -e \"/^\\$/q\" patch6 >hdrs6 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" hdrs6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n \n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch7\n+\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side >patch7 &&\n+\tsed -e \"/^\\$/q\" patch7 >hdrs7 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs7 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs7\n '\n \n test_expect_success 'command line To: header (ascii)' '\n \n \tgit config --unset-all format.headers &&\n-\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n \n-\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n \n-\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n \n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n \n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n \n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs9\n '\n \n # check_patch <patch>: Verify that <patch> looks like a half-sane\n@@ -250,52 +262,52 @@ check_patch () {\n \n test_expect_success 'format.from=false' '\n \n-\tgit -c format.from=false format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n+\tgit -c format.from=false format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n \tcheck_patch patch &&\n-\t! grep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\t! grep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from=true' '\n \n-\tgit -c format.from=true format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\tgit -c format.from=true format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from with address' '\n \n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-from overrides format.from' '\n \n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--from overrides format.from' '\n \n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-to overrides config.to' '\n \n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-to --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch10 &&\n-\tcheck_patch patch10 &&\n-\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" patch10\n+\tgit format-patch --no-to --stdout master..side >patch10 &&\n+\tsed -e \"/^\\$/q\" patch10 >hdrs10 &&\n+\tcheck_patch hdrs10 &&\n+\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs10\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n@@ -303,31 +315,31 @@ test_expect_success '--no-to and --to replaces config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n-\t\t--stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch11 &&\n-\tcheck_patch patch11 &&\n-\t! grep \"^To: Someone <someone@out.there>\\$\" patch11 &&\n-\tgrep \"^To: Someone Else <else@out.there>\\$\" patch11\n+\t\t--stdout master..side >patch11 &&\n+\tsed -e \"/^\\$/q\" patch11 >hdrs11 &&\n+\tcheck_patch hdrs11 &&\n+\t! grep \"^To: Someone <someone@out.there>\\$\" hdrs11 &&\n+\tgrep \"^To: Someone Else <else@out.there>\\$\" hdrs11\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n \n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-cc --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch12 &&\n-\tcheck_patch patch12 &&\n-\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" patch12\n+\tgit format-patch --no-cc --stdout master..side >patch12 &&\n+\tsed -e \"/^\\$/q\" patch12 >hdrs12 &&\n+\tcheck_patch hdrs12 &&\n+\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" hdrs12\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n \n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-add-header --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch13 &&\n-\tcheck_patch patch13 &&\n-\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" patch13\n+\tgit format-patch --no-add-header --stdout master..side >patch13 &&\n+\tsed -e \"/^\\$/q\" patch13 >hdrs13 &&\n+\tcheck_patch hdrs13 &&\n+\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" hdrs13\n '\n \n test_expect_success 'multiple files' '\n@@ -357,7 +369,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? > status.out) |\n+\tgit format-patch --stdout \"$@\" >patch &&\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -372,12 +384,11 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' > actual &&\n-\ttest 0 = \"$(cat status.out)\" &&\n+\t' <patch >actual &&\n \ttest_cmp \"$expect\" actual\n }\n \n-cat >> expect.no-threading <<EOF\n+cat >>expect.no-threading <<EOF\n ---\n ---\n ---\n@@ -388,7 +399,7 @@ test_expect_success 'no threading' '\n \tcheck_threading expect.no-threading master\n '\n \n-cat > expect.thread <<EOF\n+cat >expect.thread <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -405,7 +416,7 @@ test_expect_success 'thread' '\n \tcheck_threading expect.thread --thread master\n '\n \n-cat > expect.in-reply-to <<EOF\n+cat >expect.in-reply-to <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -425,7 +436,7 @@ test_expect_success 'thread in-reply-to' '\n \t\t--thread master\n '\n \n-cat > expect.cover-letter <<EOF\n+cat >expect.cover-letter <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -446,7 +457,7 @@ test_expect_success 'thread cover-letter' '\n \tcheck_threading expect.cover-letter --cover-letter --thread master\n '\n \n-cat > expect.cl-irt <<EOF\n+cat >expect.cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -478,7 +489,7 @@ test_expect_success 'thread explicit shallow' '\n \t\t--in-reply-to=\"<test.message>\" --thread=shallow master\n '\n \n-cat > expect.deep <<EOF\n+cat >expect.deep <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -496,7 +507,7 @@ test_expect_success 'thread deep' '\n \tcheck_threading expect.deep --thread=deep master\n '\n \n-cat > expect.deep-irt <<EOF\n+cat >expect.deep-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -519,7 +530,7 @@ test_expect_success 'thread deep in-reply-to' '\n \t\t--in-reply-to=\"<test.message>\" master\n '\n \n-cat > expect.deep-cl <<EOF\n+cat >expect.deep-cl <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -543,7 +554,7 @@ test_expect_success 'thread deep cover-letter' '\n \tcheck_threading expect.deep-cl --cover-letter --thread=deep master\n '\n \n-cat > expect.deep-cl-irt <<EOF\n+cat >expect.deep-cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -625,7 +636,7 @@ test_expect_success 'cover-letter inherits diff options' '\n \n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n   This is an excessively long subject line for a message due to the\n     habit some projects have of not having a short, one-line subject at\n     the start of the commit message, but rather sticking a whole\n@@ -638,12 +649,12 @@ EOF\n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \n \tgit format-patch --cover-letter -2 &&\n-\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" <0000-cover-letter.patch >output &&\n \ttest_cmp expect output\n \n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n index $before..$after 100644\n --- a/file\n +++ b/file\n@@ -665,7 +676,7 @@ test_expect_success 'format-patch respects -U' '\n \n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n \n diff --git a/file b/file\n index $before..$after 100644\n@@ -681,7 +692,7 @@ EOF\n test_expect_success 'format-patch -p suppresses stat' '\n \n \tgit format-patch -p -2 &&\n-\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n+\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n \ttest_cmp expect output\n \n '\n@@ -736,7 +747,7 @@ test_expect_success 'format-patch from a subdirectory (3)' '\n '\n \n test_expect_success 'format-patch --in-reply-to' '\n-\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" > patch8 &&\n+\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" >patch8 &&\n \tgrep \"^In-Reply-To: <baz@foo.bar>\" patch8 &&\n \tgrep \"^References: <baz@foo.bar>\" patch8\n '\n@@ -827,21 +838,24 @@ test_expect_success 'format-patch with multiple notes refs' '\n \t! grep \"this is note 2\" out\n '\n \n-echo \"fatal: --name-only does not make sense\" > expect.name-only\n-echo \"fatal: --name-status does not make sense\" > expect.name-status\n-echo \"fatal: --check does not make sense\" > expect.check\n+echo \"fatal: --name-only does not make sense\" >expect.name-only\n+echo \"fatal: --name-status does not make sense\" >expect.name-status\n+echo \"fatal: --check does not make sense\" >expect.check\n \n test_expect_success 'options no longer allowed for format-patch' '\n-\ttest_must_fail git format-patch --name-only 2> output &&\n+\ttest_must_fail git format-patch --name-only 2>output &&\n \ttest_i18ncmp expect.name-only output &&\n-\ttest_must_fail git format-patch --name-status 2> output &&\n+\ttest_must_fail git format-patch --name-status 2>output &&\n \ttest_i18ncmp expect.name-status output &&\n-\ttest_must_fail git format-patch --check 2> output &&\n-\ttest_i18ncmp expect.check output'\n+\ttest_must_fail git format-patch --check 2>output &&\n+\ttest_i18ncmp expect.check output\n+'\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n-\tgit format-patch --numstat --stdout master..side > output &&\n-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)'\n+\tgit format-patch --numstat --stdout master..side >output &&\n+\tgrep \"^diff --git a/\" output >diff &&\n+\ttest_line_count = 5 diff\n+'\n \n test_expect_success 'format-patch -- <path>' '\n \tgit format-patch master..side -- file 2>error &&\n@@ -852,20 +866,21 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n \tgit format-patch --ignore-if-in-upstream HEAD\n '\n \n-git_version=\"$(git --version | sed \"s/.* //\")\"\n-\n signature() {\n+\tgit_version=\"$(git --version >version && sed \"s/.* //\" version)\" &&\n \tprintf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n }\n \n test_expect_success 'format-patch default signature' '\n-\tgit format-patch --stdout -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature >expect &&\n \ttest_cmp expect output\n '\n \n test_expect_success 'format-patch --signature' '\n-\tgit format-patch --stdout --signature=\"my sig\" -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout --signature=\"my sig\" -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature \"my sig\" >expect &&\n \ttest_cmp expect output\n '\n@@ -897,8 +912,8 @@ test_expect_success 'format-patch --signature --cover-letter' '\n \tgit config --unset-all format.signature &&\n \tgit format-patch --stdout --signature=\"my sig\" --cover-letter \\\n \t\t-1 >output &&\n-\tgrep \"my sig\" output &&\n-\ttest 2 = $(grep \"my sig\" output | wc -l)\n+\tgrep \"my sig\" output >sig &&\n+\ttest_line_count = 2 sig\n '\n \n test_expect_success 'format.signature=\"\" suppresses signatures' '\n@@ -1256,283 +1271,283 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expected &&\n-4:Subject: [PATCH] EOL\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tcat <<-\\EOF | sed \"s/EOL$//\" >expect &&\n+\t4:Subject: [PATCH] EOL\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tbody\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n-Tested-by: Some One <someone@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-15:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tSigned-off-by: my@house\n+\t(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n+\tTested-by: Some One <someone@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t15:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-Fooled-by-me: my@house\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tbody\n+\tFooled-by-me: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-I want to mention about Signed-off-by: here.\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:I want to mention about Signed-off-by: here.\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tI want to mention about Signed-off-by: here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:I want to mention about Signed-off-by: here.\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-My unfortunate\n-Signed-off-by: example happens to be wrapped here.\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:Signed-off-by: example happens to be wrapped here.\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tMy unfortunate\n+\tSigned-off-by: example happens to be wrapped here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:Signed-off-by: example happens to be wrapped here.\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Signed-off-by: my@house\n-Signed-off-by: your@house\n+\tSigned-off-by: my@house\n+\tSigned-off-by: your@house\n \n-A lot of houses.\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: my@house\n-10:Signed-off-by: your@house\n-11:\n-13:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tA lot of houses.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: my@house\n+\t10:Signed-off-by: your@house\n+\t11:\n+\t13:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-Signed-off-by: my@house\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-12:Signed-off-by: my@house\n-EOF\n-\ttest_cmp expected actual\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\t12:Signed-off-by: my@house\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Tested-by: my@house\n-Some Trash\n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-13:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tTested-by: my@house\n+\tSome Trash\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t13:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual &&\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Reviewed-id: Noone\n-Tested-by: my@house\n-Change-id: Ideadbeef\n-Signed-off-by: C O Mitter <committer@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expected <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\ttest_cmp expected actual\n+\tReviewed-id: Noone\n+\tTested-by: my@house\n+\tChange-id: Ideadbeef\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format patch ignores color.ui' '\n@@ -1547,42 +1562,42 @@ test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (2)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (3)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter ^master rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (4)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master.. >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (5)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 HEAD >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (6)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter with nothing' '\n@@ -1636,7 +1651,8 @@ test_expect_success 'format-patch format.outputDirectory option' '\n \ttest_config format.outputDirectory patches &&\n \trm -fr patches &&\n \tgit format-patch master..side &&\n-\ttest $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)\n+\tgit rev-list master..side >list &&\n+\ttest_line_count = $(ls patches | wc -l) list\n '\n \n test_expect_success 'format-patch -o overrides format.outputDirectory' '\n@@ -1649,20 +1665,41 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' '\n \n test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n-\tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n-\tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n-\techo >expected &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\tsignature >> expected &&\n-\ttest_cmp expected actual1 &&\n-\ttest_cmp expected actual2 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 -1 >patch &&\n+\ttail -n 7 patch >actual1 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&\n+\ttail -n 7 patch >actual2 &&\n+\n+\techo >expect &&\n+\tgit rev-parse HEAD~3 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>expect &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n+\tsignature >>expect &&\n+\ttest_cmp expect actual1 &&\n+\ttest_cmp expect actual2 &&\n+\n \techo >fail &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\tsignature >> fail &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>fail &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n+\tsignature >>fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n '\n@@ -1672,8 +1709,9 @@ test_expect_success 'format-patch --base errors out when base commit is in revis\n \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expected &&\n-\ttest_cmp expected actual\n+\tgit rev-parse HEAD~2 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '\n@@ -1699,8 +1737,8 @@ test_expect_success 'format-patch --base errors out when base commit is not ance\n \ttest_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&\n \tgit format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(cat commit-id-base)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base=auto' '\n@@ -1711,8 +1749,9 @@ test_expect_success 'format-patch --base=auto' '\n \ttest_commit N2 &&\n \tgit format-patch --stdout --base=auto -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch errors out when history involves criss-cross' '\n@@ -1748,8 +1787,9 @@ test_expect_success 'format-patch format.useAutoBaseoption' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base overrides format.useAutoBase' '\n@@ -1757,8 +1797,9 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expected &&\n-\ttest_cmp expected actual\n+\tgit rev-parse HEAD~1 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base with --attach' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380751","messageId":"fd908bcc01884469dce966fbc384d6982687b4bd.1566258525.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566258525.git.liu.denton@gmail.com","subject":"[PATCH v2 2/4] Doc: add more detail for git-format-patch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T23:52:48Z","receivedAt":"2019-08-19T23:52:55Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In git-format-patch.txt, we were missing some key user information.\nFirst of all, using the `--to` and `--cc` options don't override\n`format.to` and `format.cc` variables, respectively. They add on to each\nother. Document this.\n\nIn addition, document the special value of `--base=auto`.\n\nNext, while we're at it, surround option arguments with <>.\n\nFinally, document the `format.outputDirectory` config and change\n`format.coverletter` to use camel case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-format-patch.txt | 17 ++++++++++-------\n 1 file changed, 10 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex b9b97e63ae..95bc4d53ca 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n+\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,7 +159,7 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=Message-Id::\n+--in-reply-to=<Message-Id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n \treply to the given Message-Id, which avoids breaking threads to\n \tprovide a new patch series.\n@@ -314,7 +314,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n --base=<commit>::\n \tRecord the base tree information to identify the state the\n \tpatch series applies to.  See the BASE TREE INFORMATION section\n-\tbelow for details.\n+\tbelow for details. If <commit> is \"auto\", a base commit is\n+\tautomatically chosen.\n \n --root::\n \tTreat the revision argument as a <revision range>, even if it\n@@ -330,8 +331,9 @@ CONFIGURATION\n -------------\n You can specify extra mail header lines to be added to each message,\n defaults for the subject prefix and file suffix, number patches when\n-outputting more than one patch, add \"To\" or \"Cc:\" headers, configure\n-attachments, and sign off patches with configuration variables.\n+outputting more than one patch, add \"To:\" or \"Cc:\" headers, configure\n+attachments, change the patch output directory, and sign off patches\n+with configuration variables.\n \n ------------\n [format]\n@@ -343,7 +345,8 @@ attachments, and sign off patches with configuration variables.\n \tcc = <email>\n \tattach [ = mime-boundary-string ]\n \tsignOff = true\n-\tcoverletter = auto\n+\toutputDirectory = <directory>\n+\tcoverLetter = auto\n ------------\n \n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380750","messageId":"94a778c9aa561c8cbe5ef39e21695db3124611b4.1566258525.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566258525.git.liu.denton@gmail.com","subject":"[PATCH v2 3/4] config/format.txt: make clear the default value of format.coverLetter","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T23:52:51Z","receivedAt":"2019-08-19T23:52:56Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex 414a5a8a9d..60e4e92885 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -74,7 +74,8 @@ format.signOff::\n \tPlease see the 'SubmittingPatches' document for further discussion.\n \n format.coverLetter::\n-\tA boolean that controls whether to generate a cover-letter when\n+\tA boolean which lets you enable the `--cover-letter` option by\n+\tdefault when\n \tformat-patch is invoked, but in addition can be set to \"auto\", to\n \tgenerate a cover-letter only when there's more than one patch.\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380752","messageId":"e682bd347a09d0e1293ec6bd495c38dac5006a19.1566258525.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566258525.git.liu.denton@gmail.com","subject":"[PATCH v2 4/4] format-patch: learn --infer-cover-letter option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-19T23:52:53Z","receivedAt":"2019-08-19T23:52:59Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"We used to populate the subject of the cover letter generated by\ngit-format-patch with \"*** SUBJECT HERE ***\". However, if a user submits\nmultiple patchsets, they may want to keep a consistent subject between\nrerolls.\n\nIf git-format-patch is run with `--infer-cover-letter` or\n`format.inferCoverSubject`, infer the subject for the cover letter from\nthe top line(s) of a branch description, similar to how a subject is\nread from a commit message.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt    |  4 +++\n Documentation/git-format-patch.txt | 10 ++++++\n builtin/log.c                      | 56 +++++++++++++++++++-----------\n t/t4014-format-patch.sh            | 33 ++++++++++++++++++\n 4 files changed, 82 insertions(+), 21 deletions(-)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex 60e4e92885..9cd6a64e3e 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -36,6 +36,10 @@ format.subjectPrefix::\n \tThe default for format-patch is to output files with the '[PATCH]'\n \tsubject prefix. Use this variable to change that prefix.\n \n+format.inferCoverSubject::\n+\tA boolean value which lets you enable the\n+\t`--infer-cover-subject` option of format-patch by default.\n+\n format.signature::\n \tThe default for format-patch is to output a signature containing\n \tthe Git version number. Use this variable to change that default.\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 95bc4d53ca..00ccfb51e7 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -19,6 +19,7 @@ SYNOPSIS\n \t\t   [--start-number <n>] [--numbered-files]\n \t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n+\t\t   [--[no-]infer-cover-subject]\n \t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n@@ -171,6 +172,14 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n+--[no-]infer-cover-subject::\n+\tInstead of using the default \"*** SUBJECT HERE ***\" subject for\n+\tthe cover letter, infer the subject from the branch's\n+\tdescription.\n++\n+Similar to a commit message, the subject is inferred as the beginning of\n+the description up to and excluding the first blank line.\n+\n --subject-prefix=<Subject-Prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n \tline, instead use '[<Subject-Prefix>]'. This\n@@ -347,6 +356,7 @@ with configuration variables.\n \tsignOff = true\n \toutputDirectory = <directory>\n \tcoverLetter = auto\n+\tinferCoverSubject = true\n ------------\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 44b10b3415..b15754e282 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -774,6 +774,7 @@ static const char *signature = git_version_string;\n static const char *signature_file;\n static int config_cover_letter;\n static const char *config_output_directory;\n+static int infer_cover_subject;\n \n enum {\n \tCOVER_UNSET,\n@@ -887,6 +888,10 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\t}\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"format.infercoversubject\")) {\n+\t\tinfer_cover_subject = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n \n \treturn git_log_config(var, value, cb);\n }\n@@ -993,20 +998,6 @@ static void print_signature(FILE *file)\n \tputc('\\n', file);\n }\n \n-static void add_branch_description(struct strbuf *buf, const char *branch_name)\n-{\n-\tstruct strbuf desc = STRBUF_INIT;\n-\tif (!branch_name || !*branch_name)\n-\t\treturn;\n-\tread_branch_desc(&desc, branch_name);\n-\tif (desc.len) {\n-\t\tstrbuf_addch(buf, '\\n');\n-\t\tstrbuf_addbuf(buf, &desc);\n-\t\tstrbuf_addch(buf, '\\n');\n-\t}\n-\tstrbuf_release(&desc);\n-}\n-\n static char *find_branch_name(struct rev_info *rev)\n {\n \tint i, positive = -1;\n@@ -1057,13 +1048,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t      struct commit *origin,\n \t\t\t      int nr, struct commit **list,\n \t\t\t      const char *branch_name,\n+\t\t\t      int infer_subject,\n \t\t\t      int quiet)\n {\n \tconst char *committer;\n-\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n-\tconst char *msg;\n+\tconst char *subject = \"*** SUBJECT HERE ***\";\n+\tconst char *body = \"*** BLURB HERE ***\";\n+\tconst char *description = NULL;\n \tstruct shortlog log;\n \tstruct strbuf sb = STRBUF_INIT;\n+\tstruct strbuf description_sb = STRBUF_INIT;\n+\tstruct strbuf subject_sb = STRBUF_INIT;\n \tint i;\n \tconst char *encoding = \"UTF-8\";\n \tint need_8bit_cte = 0;\n@@ -1091,17 +1086,34 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (!branch_name)\n \t\tbranch_name = find_branch_name(rev);\n \n-\tmsg = body;\n+\tif (branch_name && *branch_name)\n+\t\tread_branch_desc(&description_sb, branch_name);\n+\n+\tif (description_sb.len) {\n+\t\tif (infer_subject) {\n+\t\t\tdescription = format_subject(&subject_sb, description_sb.buf, \" \");\n+\t\t\tsubject = subject_sb.buf;\n+\t\t} else {\n+\t\t\tdescription = description_sb.buf;\n+\t\t}\n+\t}\n+\n \tpp.fmt = CMIT_FMT_EMAIL;\n \tpp.date_mode.type = DATE_RFC2822;\n \tpp.rev = rev;\n \tpp.print_email_subject = 1;\n \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n-\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n-\tpp_remainder(&pp, &msg, &sb, 0);\n-\tadd_branch_description(&sb, branch_name);\n+\tpp_title_line(&pp, &subject, &sb, encoding, need_8bit_cte);\n+\tpp_remainder(&pp, &body, &sb, 0);\n+\tif (description) {\n+\t\tstrbuf_addch(&sb, '\\n');\n+\t\tstrbuf_addstr(&sb, description);\n+\t\tstrbuf_addch(&sb, '\\n');\n+\t}\n \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n \n+\tstrbuf_release(&description_sb);\n+\tstrbuf_release(&subject_sb);\n \tstrbuf_release(&sb);\n \n \tshortlog_init(&log);\n@@ -1577,6 +1589,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t{ OPTION_CALLBACK, 0, \"rfc\", &rev, NULL,\n \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n+\t\tOPT_BOOL(0, \"infer-cover-subject\", &infer_cover_subject,\n+\t\t\t    N_(\"infer a cover letter subject from the branch description\")),\n \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n@@ -1916,7 +1930,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tif (thread)\n \t\t\tgen_message_id(&rev, \"cover\");\n \t\tmake_cover_letter(&rev, use_stdout,\n-\t\t\t\t  origin, nr, list, branch_name, quiet);\n+\t\t\t\t  origin, nr, list, branch_name, infer_cover_subject, quiet);\n \t\tprint_bases(&bases, rev.diffopt.file);\n \t\tprint_signature(rev.diffopt.file);\n \t\ttotal++;\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 0114608b1f..ad920bb063 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1558,6 +1558,39 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cover letter with config subject' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.inferCoverSubject true &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line subject' '\n+\ttest_config branch.rebuild-1.description \"command-line subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --infer-cover-subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] command-line subject$\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line --no-infer-cover-subject overrides config' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.inferCoverSubject true &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --no-infer-cover-subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380755","messageId":"CAPig+cSzq7KB4y+wuuVtVS7oi=uK2FY0+UkfOXx1jp-oe=fs4Q@mail.gmail.com","threadId":"51687","inReplyTo":"76a0a274fde564f709d294acd7d6da17167f05b5.1566258525.git.liu.denton@gmail.com","subject":"Re: [PATCH v2 1/4] t4014: clean up style","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-20T02:41:22Z","receivedAt":"2019-08-20T02:41:37Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Aug 19, 2019 at 7:53 PM Denton Liu <liu.denton@gmail.com> wrote:\n> In Git's tests, there is typically no space between the redirection\n> operator and the filename. Remove these spaces.\n>\n> Since output is silenced when running without `-v` and debugging\n> output is useful with `-v`, remove redirections to /dev/null.\n>\n> Change here-docs from `<<\\EOF` to `<<-\\EOF` so that they can be indented\n> along with the rest of the test case.\n>\n> Convert all instances of `cnt=$(... | wc -l) && test $cnt = N` into\n> uses of `test_line_count()`.\n>\n> For style, move the ending sq of test cases onto its own line whenever\n> they do not conform.\n>\n> Rename output files from \"expected\" to \"expect\" to conform with the\n> usual convention.\n>\n> Finally, refactor to remove Git commands upstream of pipe as well as Git\n> commands that are in a non-variable-assignment subshell (e.g. `echo\n> \"base-commit: $(git rev-parse HEAD)\"`. This way, if an invocation of a\n> Git command fails, the return code won't be lost. Keep upstream non-Git\n> commands since we have to assume a base level of sanity.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> This patch is getting a little unwieldy. Perhaps we could split it into\n> several smaller patches? Unfortunately, I'm not really sure where a\n> logical place to split it would be.\n\nThe bullet points in the commit message, each of which is a distinct\nchange, give a strong hint as to how the commit could be split into\nsmaller pieces. It would make repeated review easier (though I'm not\nsure it's worth re-rolling just for that).\n\n> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> @@ -62,26 +63,24 @@ test_expect_success setup '\n>  test_expect_success \"format-patch --ignore-if-in-upstream\" '\n>\n>         git format-patch --stdout \\\n>                 --ignore-if-in-upstream master..side >patch1 &&\n> -       cnt=$(grep \"^From \" patch1 | wc -l) &&\n> -       test $cnt = 2\n> -\n> +       grep \"^From \" patch1 >from1 &&\n> +       test_line_count = 2 from1\n>  '\n\nHere you've removed the blank line following the body before the\nclosing quote, which brings the formatting more in line with current\nstyle, however, you could do the same with the blank line before the\nbody. Ditto for other tests.\n\nAnother style fix would be to change the double quotes in the test\ntitle to single quotes (here and in other tests).\n\n> @@ -357,7 +369,7 @@ test_expect_success 'reroll count (-v)' '\n>  check_threading () {\n>         expect=\"$1\" &&\n>         shift &&\n> -       (git format-patch --stdout \"$@\"; echo $? > status.out) |\n> +       git format-patch --stdout \"$@\" >patch &&\n>         # Prints everything between the Message-ID and In-Reply-To,\n>         # and replaces all Message-ID-lookalikes by a sequence number\n>         perl -ne '\n> @@ -372,12 +384,11 @@ check_threading () {\n>                         print;\n>                 }\n>                 print \"---\\n\" if /^From /i;\n> -       ' > actual &&\n> -       test 0 = \"$(cat status.out)\" &&\n> +       ' <patch >actual &&\n>         test_cmp \"$expect\" actual\n>  }\n\nIf you do break this patch into smaller pieces, this might deserve its\nown patch (or not) because it requires a bit of extra reasoning by the\nreviewer.\n\n> @@ -852,20 +866,21 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n> -git_version=\"$(git --version | sed \"s/.* //\")\"\n> -\n>  signature() {\n> +       git_version=\"$(git --version >version && sed \"s/.* //\" version)\" &&\n>         printf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n>  }\n\nWindows folks are not going to like you for this change since process\ncreation is so expensive on that platform, and the point of setting\nthat variable globally was to avoid repeated invocation (especially\nsince the output of \"git --version\" won't change). This function\nappears to be invoked only three times presently, but that number\ncould increase in the future as new tests are added. Consequently, it\nmight be best to drop this change.\n"},{"id":"380756","messageId":"CAPig+cTL3rtPuMQiFfZPcAX7T=v8fVSOL07ULDbXUuG+GD_jzQ@mail.gmail.com","threadId":"51687","inReplyTo":"fd908bcc01884469dce966fbc384d6982687b4bd.1566258525.git.liu.denton@gmail.com","subject":"Re: [PATCH v2 2/4] Doc: add more detail for git-format-patch","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-20T02:44:03Z","receivedAt":"2019-08-20T02:44:17Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Aug 19, 2019 at 7:53 PM Denton Liu <liu.denton@gmail.com> wrote:\n> In git-format-patch.txt, we were missing some key user information.\n> First of all, using the `--to` and `--cc` options don't override\n> `format.to` and `format.cc` variables, respectively. They add on to each\n> other. Document this.\n\nThis entire paragraph can go away since v2 dropped this change.\n\n> In addition, document the special value of `--base=auto`.\n>\n> Next, while we're at it, surround option arguments with <>.\n>\n> Finally, document the `format.outputDirectory` config and change\n> `format.coverletter` to use camel case.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\n> @@ -314,7 +314,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n>  --base=<commit>::\n>         Record the base tree information to identify the state the\n>         patch series applies to.  See the BASE TREE INFORMATION section\n> -       below for details.\n> +       below for details. If <commit> is \"auto\", a base commit is\n> +       automatically chosen.\n\nShould <commit> be encased in backquotes in the paragraph body?\n"},{"id":"380758","messageId":"CAPig+cTA-YzPkDP+pTpZQkwj0UeCuci8aCuXZW_xrS7-CH7Rng@mail.gmail.com","threadId":"51687","inReplyTo":"94a778c9aa561c8cbe5ef39e21695db3124611b4.1566258525.git.liu.denton@gmail.com","subject":"Re: [PATCH v2 3/4] config/format.txt: make clear the default value of format.coverLetter","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-20T02:47:01Z","receivedAt":"2019-08-20T02:47:15Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Aug 19, 2019 at 7:53 PM Denton Liu <liu.denton@gmail.com> wrote:\n> diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\n> @@ -74,7 +74,8 @@ format.signOff::\n>  format.coverLetter::\n> -       A boolean that controls whether to generate a cover-letter when\n> +       A boolean which lets you enable the `--cover-letter` option by\n> +       default when\n>         format-patch is invoked, but in addition can be set to \"auto\", to\n>         generate a cover-letter only when there's more than one patch.\n\nRather than rewriting like this, I think it's more common in Git\ndocumentation to mention the default as the last sentence in the\nparagraph. For instance:\n\n    ... when there's more than one patch. Default is true.\n"},{"id":"380768","messageId":"CAPig+cRfk7jdhqRX2OiyftW0eaM040u6KgRPLUWin7Z3W1LgDA@mail.gmail.com","threadId":"51687","inReplyTo":"e682bd347a09d0e1293ec6bd495c38dac5006a19.1566258525.git.liu.denton@gmail.com","subject":"Re: [PATCH v2 4/4] format-patch: learn --infer-cover-letter option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-20T03:46:47Z","receivedAt":"2019-08-20T03:47:01Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Aug 19, 2019 at 7:53 PM Denton Liu <liu.denton@gmail.com> wrote:\n> We used to populate the subject of the cover letter generated by\n> git-format-patch with \"*** SUBJECT HERE ***\". However, if a user submits\n> multiple patchsets, they may want to keep a consistent subject between\n> rerolls.\n>\n> If git-format-patch is run with `--infer-cover-letter` or\n\ns/letter/subject/\n\n> `format.inferCoverSubject`, infer the subject for the cover letter from\n> the top line(s) of a branch description, similar to how a subject is\n> read from a commit message.\n\nA possible rewrite of the entire commit message in imperative mood:\n\n    Teach 'format-patch' to use the first line of the branch description\n    as the Subject: of the generated cover letter, rather than\n    \"*** SUBJECT HERE ***\", if --infer-cover-subject is specified (or the\n    corresponding `format.inferCoverSubject` option is enabled). This\n    complements existing inclusion of the branch description in the\n    cover letter body.\n\nA casual reader of this patch might wonder why this new useful\nbehavior isn't default, so it might make sense for the commit message\nto further explain that making it default would potentially break\nexisting tooling.\n\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\n> @@ -36,6 +36,10 @@ format.subjectPrefix::\n> +format.inferCoverSubject::\n> +       A boolean value which lets you enable the\n> +       `--infer-cover-subject` option of format-patch by default.\n\nAs mentioned in my review of 3/4, it is common to mention the default\nvalue at the end of the paragraph. So, perhaps:\n\n    A boolean that controls whether or not to take the first line of\n    the branch description as the subject for the cover letter. See the\n    `--infer-cover-subject` option in linkgit:git-format-patch[1].\n    Default is false.\n\n> diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\n> @@ -171,6 +172,14 @@ will want to ensure that threading is disabled for `git send-email`.\n> +--[no-]infer-cover-subject::\n> +       Instead of using the default \"*** SUBJECT HERE ***\" subject for\n> +       the cover letter, infer the subject from the branch's\n> +       description.\n> ++\n> +Similar to a commit message, the subject is inferred as the beginning of\n> +the description up to and excluding the first blank line.\n\nI think this can all be collapsed to the simpler:\n\n    Use the beginning of the branch description (up to the first\n    blank line) as the cover letter subject instead of the default\n    \"*** SUBJECT HERE ***\".\n\nor something.\n\n> diff --git a/builtin/log.c b/builtin/log.c\n> @@ -1577,6 +1589,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n> +               OPT_BOOL(0, \"infer-cover-subject\", &infer_cover_subject,\n> +                           N_(\"infer a cover letter subject from the branch description\")),\n\nShorter: \"infer cover letter subject from branch description\"\n"},{"id":"380774","messageId":"20190820070740.GA29407@archbookpro.localdomain","threadId":"51687","inReplyTo":"CAPig+cTL3rtPuMQiFfZPcAX7T=v8fVSOL07ULDbXUuG+GD_jzQ@mail.gmail.com","subject":"Re: [PATCH v2 2/4] Doc: add more detail for git-format-patch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:07:40Z","receivedAt":"2019-08-20T07:07:46Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Mon, Aug 19, 2019 at 10:44:03PM -0400, Eric Sunshine wrote:\n> On Mon, Aug 19, 2019 at 7:53 PM Denton Liu <liu.denton@gmail.com> wrote:\n> > In git-format-patch.txt, we were missing some key user information.\n> > First of all, using the `--to` and `--cc` options don't override\n> > `format.to` and `format.cc` variables, respectively. They add on to each\n> > other. Document this.\n> \n> This entire paragraph can go away since v2 dropped this change.\n> \n> > In addition, document the special value of `--base=auto`.\n> >\n> > Next, while we're at it, surround option arguments with <>.\n> >\n> > Finally, document the `format.outputDirectory` config and change\n> > `format.coverletter` to use camel case.\n> >\n> > Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> > ---\n> > diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\n> > @@ -314,7 +314,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n> >  --base=<commit>::\n> >         Record the base tree information to identify the state the\n> >         patch series applies to.  See the BASE TREE INFORMATION section\n> > -       below for details.\n> > +       below for details. If <commit> is \"auto\", a base commit is\n> > +       automatically chosen.\n> \n> Should <commit> be encased in backquotes in the paragraph body?\n\nIn this page, it seems like the other instances of <commit> (or most\nother <text> for that matter) aren't wrapped in backquotes. From\nchecking out the rest of Git's documentation, it seems like it's a mixed\nbag whether to do this or not.\n\nI'm going to leave it as is and hopefully someone who cares enough will\nmake the docs more stylistically uniform.\n"},{"id":"380775","messageId":"cover.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566258525.git.liu.denton@gmail.com","subject":"[PATCH v3 00/13] format-patch: learn --infer-cover-subject option (also t4014 cleanup)","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:18:43Z","receivedAt":"2019-08-20T07:18:48Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Thanks for another round of reviews, Eric. I've incorporated most of\nyour suggestions, including breaking the t4014 cleanup patch into\nmultiple patches. Hopefully it isn't such a doozy to review now.\n\nCurrently, format-patch only puts \"*** SUBJECT HERE ***\" when a cover\nletter is generated. However, it is already smart enough to be able to\npopulate the cover letter with the branch description so there's no\nreason why it cannot populate the subject as well.\n\nTeach format-patch the `--infer-cover-subject` option and corresponding\n`format.inferCoverSubject` configuration option which will read the\nsubject from the branch description using the same rules as for a commit\nmessage (that is, it will expect a subject line followed by a blank\nline).\n\nWhile we're at it, perform some major cleanup of t4014 including some\nstylistic cleanup and also, unmasking of Git return codes.\n\nThis was based on patches 1-3 of an earlier patchset I sent[1].\n\nChanges since v2:\n\n* Break 1/4 into many different patches (one per paragraph of the\n  original patch)\n\n* Incorporate Eric's documentation/commit message suggestions\n\nChanges since v1:\n\n* Incorporate Eric's suggestions for cleanup in all patches\n\n* Add patch 3/4 to make it clear what is the default value for\n  format.coverLetter (since format.inferCoverSubject was borrowed from\n  this config but it also did not state what the default value was)\n\n* In 1/4, rename all instances of \"expected\" to \"expect\"\n\n[1]: https://public-inbox.org/git/cover.1558492582.git.liu.denton@gmail.com/\n\n\nDenton Liu (13):\n  t4014: drop unnecessary blank lines from test cases\n  t4014: s/expected/expect/\n  t4014: move closing sq onto its own line\n  t4014: use sq for test case names\n  t4014: remove spaces after redirect operators\n  t4014: use indentable here-docs\n  t4014: drop redirections to /dev/null\n  t4014: use test_line_count() where possible\n  t4014: remove confusing pipe in check_threading()\n  t4014: stop losing return codes of git commands\n  Doc: add more detail for git-format-patch\n  config/format.txt: specify default value of format.coverLetter\n  format-patch: learn --infer-cover-subject option\n\n Documentation/config/format.txt    |   7 +\n Documentation/git-format-patch.txt |  24 +-\n builtin/log.c                      |  56 +-\n t/t4014-format-patch.sh            | 822 +++++++++++++++--------------\n 4 files changed, 486 insertions(+), 423 deletions(-)\n\nRange-diff against v2:\n 1:  76a0a274fd <  -:  ---------- t4014: clean up style\n -:  ---------- >  1:  fb000bfca2 t4014: drop unnecessary blank lines from test cases\n -:  ---------- >  2:  568b3a03a0 t4014: s/expected/expect/\n -:  ---------- >  3:  a205a920bd t4014: move closing sq onto its own line\n -:  ---------- >  4:  66bf2e3dd4 t4014: use sq for test case names\n -:  ---------- >  5:  6f1371275e t4014: remove spaces after redirect operators\n -:  ---------- >  6:  b4295846f5 t4014: use indentable here-docs\n -:  ---------- >  7:  34315412c8 t4014: drop redirections to /dev/null\n -:  ---------- >  8:  de08dd886d t4014: use test_line_count() where possible\n -:  ---------- >  9:  dec5a62e82 t4014: remove confusing pipe in check_threading()\n -:  ---------- > 10:  64069c0c54 t4014: stop losing return codes of git commands\n 2:  fd908bcc01 ! 11:  c12534ab5d Doc: add more detail for git-format-patch\n    @@ Commit message\n         Doc: add more detail for git-format-patch\n     \n         In git-format-patch.txt, we were missing some key user information.\n    -    First of all, using the `--to` and `--cc` options don't override\n    -    `format.to` and `format.cc` variables, respectively. They add on to each\n    -    other. Document this.\n    -\n    -    In addition, document the special value of `--base=auto`.\n    +    First of all, document the special value of `--base=auto`.\n     \n         Next, while we're at it, surround option arguments with <>.\n     \n 3:  94a778c9aa <  -:  ---------- config/format.txt: make clear the default value of format.coverLetter\n -:  ---------- > 12:  a08273ebcc config/format.txt: specify default value of format.coverLetter\n 4:  e682bd347a ! 13:  de599f7ca9 format-patch: learn --infer-cover-letter option\n    @@ Metadata\n     Author: Denton Liu <liu.denton@gmail.com>\n     \n      ## Commit message ##\n    -    format-patch: learn --infer-cover-letter option\n    +    format-patch: learn --infer-cover-subject option\n     \n    -    We used to populate the subject of the cover letter generated by\n    -    git-format-patch with \"*** SUBJECT HERE ***\". However, if a user submits\n    -    multiple patchsets, they may want to keep a consistent subject between\n    -    rerolls.\n    +    Teach format-patch to use the first line of the branch description as\n    +    the Subject: of the generated cover letter, rather than \"*** SUBJECT\n    +    HERE ***\" if `--infer-cover-subject` is specified or the corresponding\n    +    `format.inferCoverSubject` option is enabled. This complements the\n    +    existing inclusion of the branch description in the cover letter body.\n     \n    -    If git-format-patch is run with `--infer-cover-letter` or\n    -    `format.inferCoverSubject`, infer the subject for the cover letter from\n    -    the top line(s) of a branch description, similar to how a subject is\n    -    read from a commit message.\n    +    The reason why this behaviour is not made default is because this change\n    +    is not backwards compatible and may break existing tooling that may rely\n    +    on the default template subject.\n     \n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n     \n    @@ Documentation/config/format.txt: format.subjectPrefix::\n      \tsubject prefix. Use this variable to change that prefix.\n      \n     +format.inferCoverSubject::\n    -+\tA boolean value which lets you enable the\n    -+\t`--infer-cover-subject` option of format-patch by default.\n    ++\tA boolean that controls whether or not to take the first line of\n    ++\tthe branch description as the subject for the cover letter. See the\n    ++\t`--infer-cover-subject` option in linkgit:git-format-patch[1].\n    ++\tDefault is false.\n     +\n      format.signature::\n      \tThe default for format-patch is to output a signature containing\n    @@ Documentation/git-format-patch.txt: will want to ensure that threading is disabl\n      \tignored.\n      \n     +--[no-]infer-cover-subject::\n    -+\tInstead of using the default \"*** SUBJECT HERE ***\" subject for\n    -+\tthe cover letter, infer the subject from the branch's\n    -+\tdescription.\n    -++\n    -+Similar to a commit message, the subject is inferred as the beginning of\n    -+the description up to and excluding the first blank line.\n    ++\tUse the beginning of the branch description (up to the first\n    ++\tblank line) as the cover letter subject instead of the default\n    ++\t\"*** SUBJECT HERE ***\".\n     +\n      --subject-prefix=<Subject-Prefix>::\n      \tInstead of the standard '[PATCH]' prefix in the subject\n    @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *pre\n      \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n      \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n     +\t\tOPT_BOOL(0, \"infer-cover-subject\", &infer_cover_subject,\n    -+\t\t\t    N_(\"infer a cover letter subject from the branch description\")),\n    ++\t\t\t    N_(\"infer a cover letter subject from branch description\")),\n      \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n      \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n      \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n    @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *pre\n      \t\ttotal++;\n     \n      ## t/t4014-format-patch.sh ##\n    +@@ t/t4014-format-patch.sh: test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n    + '\n    + \n    + test_expect_success 'get git version' '\n    +-\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n    ++\tgit_version=\"$(git --version >version && sed \"s/.* //\" <version)\"\n    + '\n    + \n    + signature() {\n     @@ t/t4014-format-patch.sh: test_expect_success 'format patch ignores color.ui' '\n      \ttest_cmp expect actual\n      '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380776","messageId":"fb000bfca21bde176f1e7ea947f36f3639f822bd.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 01/13] t4014: drop unnecessary blank lines from test cases","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:18:46Z","receivedAt":"2019-08-20T07:18:52Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 47 -----------------------------------------\n 1 file changed, 47 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca7debf1d4..3ed3feabfe 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -9,7 +9,6 @@ test_description='various format-patch tests'\n . \"$TEST_DIRECTORY\"/lib-terminal.sh\n \n test_expect_success setup '\n-\n \tfor i in 1 2 3 4 5 6 7 8 9 10; do echo \"$i\"; done >file &&\n \tcat file >elif &&\n \tgit add file elif &&\n@@ -60,20 +59,16 @@ test_expect_success setup '\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n-\n \tgit format-patch --stdout master..side >patch0 &&\n \tcnt=$(grep \"^From \" patch0 | wc -l) &&\n \ttest $cnt = 3\n-\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n-\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n \tcnt=$(grep \"^From \" patch1 | wc -l) &&\n \ttest $cnt = 2\n-\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n@@ -85,7 +80,6 @@ test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n '\n \n test_expect_success \"format-patch doesn't consider merge commits\" '\n-\n \tgit checkout -b slave master &&\n \techo \"Another line\" >>file &&\n \ttest_tick &&\n@@ -101,7 +95,6 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n '\n \n test_expect_success \"format-patch result applies\" '\n-\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n@@ -109,7 +102,6 @@ test_expect_success \"format-patch result applies\" '\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n-\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n@@ -117,26 +109,19 @@ test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n '\n \n test_expect_success 'commit did not screw up the log message' '\n-\n \tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n-\n '\n \n test_expect_success 'format-patch did not screw up the log message' '\n-\n \tgrep \"^Subject: .*Side changes #3 with .* backslash-n\" patch0 &&\n \tgrep \"^Subject: .*Side changes #3 with .* backslash-n\" patch1\n-\n '\n \n test_expect_success 'replay did not screw up the log message' '\n-\n \tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n-\n '\n \n test_expect_success 'extra headers' '\n-\n \tgit config format.headers \"To: R E Cipient <rcipient@example.com>\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n@@ -145,22 +130,18 @@ test_expect_success 'extra headers' '\n \tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n-\n '\n \n test_expect_success 'extra headers without newlines' '\n-\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n \tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n-\n '\n \n test_expect_success 'extra headers with multiple To:s' '\n-\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side > patch4 &&\n@@ -170,7 +151,6 @@ test_expect_success 'extra headers with multiple To:s' '\n '\n \n test_expect_success 'additional command line cc (ascii)' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n@@ -178,7 +158,6 @@ test_expect_success 'additional command line cc (ascii)' '\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n@@ -186,14 +165,12 @@ test_expect_failure 'additional command line cc (rfc822)' '\n '\n \n test_expect_success 'command line headers' '\n-\n \tgit config --unset-all format.headers &&\n \tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n@@ -201,40 +178,34 @@ test_expect_success 'configuration headers and command line headers' '\n '\n \n test_expect_success 'command line To: header (ascii)' '\n-\n \tgit config --unset-all format.headers &&\n \tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n-\n \tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n-\n \tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n-\n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n-\n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n-\n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n@@ -249,7 +220,6 @@ check_patch () {\n }\n \n test_expect_success 'format.from=false' '\n-\n \tgit -c format.from=false format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -257,7 +227,6 @@ test_expect_success 'format.from=false' '\n '\n \n test_expect_success 'format.from=true' '\n-\n \tgit -c format.from=true format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -265,7 +234,6 @@ test_expect_success 'format.from=true' '\n '\n \n test_expect_success 'format.from with address' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -273,7 +241,6 @@ test_expect_success 'format.from with address' '\n '\n \n test_expect_success '--no-from overrides format.from' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -281,7 +248,6 @@ test_expect_success '--no-from overrides format.from' '\n '\n \n test_expect_success '--from overrides format.from' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -289,7 +255,6 @@ test_expect_success '--from overrides format.from' '\n '\n \n test_expect_success '--no-to overrides config.to' '\n-\n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-to --stdout master..side |\n@@ -299,7 +264,6 @@ test_expect_success '--no-to overrides config.to' '\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n-\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n@@ -311,7 +275,6 @@ test_expect_success '--no-to and --to replaces config.to' '\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n-\n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-cc --stdout master..side |\n@@ -321,7 +284,6 @@ test_expect_success '--no-cc overrides config.cc' '\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n-\n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-add-header --stdout master..side |\n@@ -331,7 +293,6 @@ test_expect_success '--no-add-header overrides config.headers' '\n '\n \n test_expect_success 'multiple files' '\n-\n \trm -rf patches/ &&\n \tgit checkout side &&\n \tgit format-patch -o patches/ master &&\n@@ -594,7 +555,6 @@ test_expect_success 'thread config + --no-thread' '\n '\n \n test_expect_success 'excessive subject' '\n-\n \trm -rf patches/ &&\n \tgit checkout side &&\n \tbefore=$(git hash-object file) &&\n@@ -622,7 +582,6 @@ test_expect_success 'cover-letter inherits diff options' '\n \t! grep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch &&\n \tgit format-patch --cover-letter -1 -M &&\n \tgrep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch\n-\n '\n \n cat > expect << EOF\n@@ -636,11 +595,9 @@ cat > expect << EOF\n EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n-\n \tgit format-patch --cover-letter -2 &&\n \tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n \ttest_cmp expect output\n-\n '\n \n cat > expect << EOF\n@@ -656,13 +613,11 @@ index $before..$after 100644\n EOF\n \n test_expect_success 'format-patch respects -U' '\n-\n \tgit format-patch -U4 -2 &&\n \tsed -e \"1,/^diff/d\" -e \"/^+5/q\" \\\n \t\t<0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \\\n \t\t>output &&\n \ttest_cmp expect output\n-\n '\n \n cat > expect << EOF\n@@ -679,11 +634,9 @@ index $before..$after 100644\n EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n-\n \tgit format-patch -p -2 &&\n \tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n \ttest_cmp expect output\n-\n '\n \n test_expect_success 'format-patch from a subdirectory (1)' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380777","messageId":"568b3a03a08faf109220aff47c1fd3e68fde3bfe.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 02/13] t4014: s/expected/expect/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:18:48Z","receivedAt":"2019-08-20T07:18:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For test cases, the usual convention is to name expected output files\n\"expect\", not \"expected\". Replace all instances with \"expected\" with\n\"expect\" except for one case where the \"expected\" is used as the name\nof a test case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 106 ++++++++++++++++++++--------------------\n 1 file changed, 53 insertions(+), 53 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 3ed3feabfe..62f5680f05 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1209,32 +1209,32 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expected &&\n+\tcat <<\\EOF | sed \"s/EOL$//\" >expect &&\n 4:Subject: [PATCH] EOL\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n@@ -1243,24 +1243,24 @@ subject\n \n body\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n@@ -1271,14 +1271,14 @@ body\n \n Signed-off-by: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: my@house\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n@@ -1292,14 +1292,14 @@ Signed-off-by: my@house\n Tested-by: Some One <someone@example.com>\n Bug: 1234\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: my@house\n 15:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n@@ -1309,13 +1309,13 @@ subject\n body\n Fooled-by-me: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n@@ -1324,14 +1324,14 @@ subject\n \n I want to mention about Signed-off-by: here.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:I want to mention about Signed-off-by: here.\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n@@ -1341,13 +1341,13 @@ subject\n My unfortunate\n Signed-off-by: example happens to be wrapped here.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:Signed-off-by: example happens to be wrapped here.\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n@@ -1359,7 +1359,7 @@ Signed-off-by: your@house\n \n A lot of houses.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: my@house\n@@ -1368,7 +1368,7 @@ EOF\n 13:\n 14:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n@@ -1379,24 +1379,24 @@ body\n \n Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n@@ -1408,14 +1408,14 @@ body\n Signed-off-by: C O Mitter <committer@example.com>\n Signed-off-by: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n 12:Signed-off-by: my@house\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n@@ -1428,13 +1428,13 @@ Tested-by: my@house\n Some Trash\n Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 13:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n@@ -1444,13 +1444,13 @@ subject\n Myfooter: x\n Some Trash\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual &&\n+\ttest_cmp expect actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n \tappend_signoff <<\\EOF >actual &&\n@@ -1459,12 +1459,12 @@ subject\n Myfooter: x\n Some Trash\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n@@ -1479,13 +1479,13 @@ Change-id: Ideadbeef\n Signed-off-by: C O Mitter <committer@example.com>\n Bug: 1234\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 14:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format patch ignores color.ui' '\n@@ -1604,13 +1604,13 @@ test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n \tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n \tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n-\techo >expected &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\tsignature >> expected &&\n-\ttest_cmp expected actual1 &&\n-\ttest_cmp expected actual2 &&\n+\techo >expect &&\n+\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n+\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\tsignature >> expect &&\n+\ttest_cmp expect actual1 &&\n+\ttest_cmp expect actual2 &&\n \techo >fail &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n@@ -1625,8 +1625,8 @@ test_expect_success 'format-patch --base errors out when base commit is in revis\n \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse HEAD~2)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '\n@@ -1652,8 +1652,8 @@ test_expect_success 'format-patch --base errors out when base commit is not ance\n \ttest_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&\n \tgit format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(cat commit-id-base)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base=auto' '\n@@ -1664,8 +1664,8 @@ test_expect_success 'format-patch --base=auto' '\n \ttest_commit N2 &&\n \tgit format-patch --stdout --base=auto -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch errors out when history involves criss-cross' '\n@@ -1701,8 +1701,8 @@ test_expect_success 'format-patch format.useAutoBaseoption' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base overrides format.useAutoBase' '\n@@ -1710,8 +1710,8 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse HEAD~1)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base with --attach' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380778","messageId":"a205a920bdd310df043b49ba74469ffbc88d7573.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 03/13] t4014: move closing sq onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:18:51Z","receivedAt":"2019-08-20T07:18:56Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The usual convention for test cases is for the closing sq to be on its\nown line. Move the sq onto its own line for cases that do not conform to\nthis style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 62f5680f05..5e8eb6fb27 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -790,11 +790,13 @@ test_expect_success 'options no longer allowed for format-patch' '\n \ttest_must_fail git format-patch --name-status 2> output &&\n \ttest_i18ncmp expect.name-status output &&\n \ttest_must_fail git format-patch --check 2> output &&\n-\ttest_i18ncmp expect.check output'\n+\ttest_i18ncmp expect.check output\n+'\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n \tgit format-patch --numstat --stdout master..side > output &&\n-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)'\n+\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n+'\n \n test_expect_success 'format-patch -- <path>' '\n \tgit format-patch master..side -- file 2>error &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380779","messageId":"66bf2e3dd4ecfa2d389d3865929226ad02818b55.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 04/13] t4014: use sq for test case names","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:18:53Z","receivedAt":"2019-08-20T07:18:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The usual convention is for test case names to be written between\nsingle-quotes. Change all double-quoted test case names to single-quotes\nexcept for one test case name that uses a sq for a contraction.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 5e8eb6fb27..a7b440b003 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -58,20 +58,20 @@ test_expect_success setup '\n \tgit checkout master\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout master..side >patch0 &&\n \tcnt=$(grep \"^From \" patch0 | wc -l) &&\n \ttest $cnt = 3\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n \tcnt=$(grep \"^From \" patch1 | wc -l) &&\n \ttest $cnt = 2\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '\n \tgit tag -a v1 -m tag side &&\n \tgit tag -a v2 -m tag master &&\n \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n@@ -94,14 +94,14 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \ttest $cnt = 3\n '\n \n-test_expect_success \"format-patch result applies\" '\n+test_expect_success 'format-patch result applies' '\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n \ttest $cnt = 2\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380780","messageId":"6f1371275e3ce9ea5b1da1b183a4ccb71b103c5b.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 05/13] t4014: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:18:56Z","receivedAt":"2019-08-20T07:19:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 62 ++++++++++++++++++++---------------------\n 1 file changed, 31 insertions(+), 31 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex a7b440b003..075affb1e5 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -126,8 +126,8 @@ test_expect_success 'extra headers' '\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n \" &&\n-\tgit format-patch --stdout master..side > patch2 &&\n-\tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n+\tgit format-patch --stdout master..side >patch2 &&\n+\tsed -e \"/^\\$/q\" patch2 >hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n '\n@@ -136,7 +136,7 @@ test_expect_success 'extra headers without newlines' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n-\tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n+\tsed -e \"/^\\$/q\" patch3 >hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n '\n@@ -144,8 +144,8 @@ test_expect_success 'extra headers without newlines' '\n test_expect_success 'extra headers with multiple To:s' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n-\tgit format-patch --stdout master..side > patch4 &&\n-\tsed -e \"/^\\$/q\" patch4 > hdrs4 &&\n+\tgit format-patch --stdout master..side >patch4 &&\n+\tsed -e \"/^\\$/q\" patch4 >hdrs4 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>,\\$\" hdrs4 &&\n \tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs4\n '\n@@ -318,7 +318,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? > status.out) |\n+\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -333,12 +333,12 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' > actual &&\n+\t' >actual &&\n \ttest 0 = \"$(cat status.out)\" &&\n \ttest_cmp \"$expect\" actual\n }\n \n-cat >> expect.no-threading <<EOF\n+cat >>expect.no-threading <<EOF\n ---\n ---\n ---\n@@ -349,7 +349,7 @@ test_expect_success 'no threading' '\n \tcheck_threading expect.no-threading master\n '\n \n-cat > expect.thread <<EOF\n+cat >expect.thread <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -366,7 +366,7 @@ test_expect_success 'thread' '\n \tcheck_threading expect.thread --thread master\n '\n \n-cat > expect.in-reply-to <<EOF\n+cat >expect.in-reply-to <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -386,7 +386,7 @@ test_expect_success 'thread in-reply-to' '\n \t\t--thread master\n '\n \n-cat > expect.cover-letter <<EOF\n+cat >expect.cover-letter <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -407,7 +407,7 @@ test_expect_success 'thread cover-letter' '\n \tcheck_threading expect.cover-letter --cover-letter --thread master\n '\n \n-cat > expect.cl-irt <<EOF\n+cat >expect.cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -439,7 +439,7 @@ test_expect_success 'thread explicit shallow' '\n \t\t--in-reply-to=\"<test.message>\" --thread=shallow master\n '\n \n-cat > expect.deep <<EOF\n+cat >expect.deep <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -457,7 +457,7 @@ test_expect_success 'thread deep' '\n \tcheck_threading expect.deep --thread=deep master\n '\n \n-cat > expect.deep-irt <<EOF\n+cat >expect.deep-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -480,7 +480,7 @@ test_expect_success 'thread deep in-reply-to' '\n \t\t--in-reply-to=\"<test.message>\" master\n '\n \n-cat > expect.deep-cl <<EOF\n+cat >expect.deep-cl <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -504,7 +504,7 @@ test_expect_success 'thread deep cover-letter' '\n \tcheck_threading expect.deep-cl --cover-letter --thread=deep master\n '\n \n-cat > expect.deep-cl-irt <<EOF\n+cat >expect.deep-cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -584,7 +584,7 @@ test_expect_success 'cover-letter inherits diff options' '\n \tgrep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n   This is an excessively long subject line for a message due to the\n     habit some projects have of not having a short, one-line subject at\n     the start of the commit message, but rather sticking a whole\n@@ -596,11 +596,11 @@ EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \tgit format-patch --cover-letter -2 &&\n-\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" <0000-cover-letter.patch >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n index $before..$after 100644\n --- a/file\n +++ b/file\n@@ -620,7 +620,7 @@ test_expect_success 'format-patch respects -U' '\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n \n diff --git a/file b/file\n index $before..$after 100644\n@@ -635,7 +635,7 @@ EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n \tgit format-patch -p -2 &&\n-\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n+\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n \ttest_cmp expect output\n '\n \n@@ -689,7 +689,7 @@ test_expect_success 'format-patch from a subdirectory (3)' '\n '\n \n test_expect_success 'format-patch --in-reply-to' '\n-\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" > patch8 &&\n+\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" >patch8 &&\n \tgrep \"^In-Reply-To: <baz@foo.bar>\" patch8 &&\n \tgrep \"^References: <baz@foo.bar>\" patch8\n '\n@@ -780,21 +780,21 @@ test_expect_success 'format-patch with multiple notes refs' '\n \t! grep \"this is note 2\" out\n '\n \n-echo \"fatal: --name-only does not make sense\" > expect.name-only\n-echo \"fatal: --name-status does not make sense\" > expect.name-status\n-echo \"fatal: --check does not make sense\" > expect.check\n+echo \"fatal: --name-only does not make sense\" >expect.name-only\n+echo \"fatal: --name-status does not make sense\" >expect.name-status\n+echo \"fatal: --check does not make sense\" >expect.check\n \n test_expect_success 'options no longer allowed for format-patch' '\n-\ttest_must_fail git format-patch --name-only 2> output &&\n+\ttest_must_fail git format-patch --name-only 2>output &&\n \ttest_i18ncmp expect.name-only output &&\n-\ttest_must_fail git format-patch --name-status 2> output &&\n+\ttest_must_fail git format-patch --name-status 2>output &&\n \ttest_i18ncmp expect.name-status output &&\n-\ttest_must_fail git format-patch --check 2> output &&\n+\ttest_must_fail git format-patch --check 2>output &&\n \ttest_i18ncmp expect.check output\n '\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n-\tgit format-patch --numstat --stdout master..side > output &&\n+\tgit format-patch --numstat --stdout master..side >output &&\n \ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n '\n \n@@ -1610,14 +1610,14 @@ test_expect_success 'format-patch --base' '\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n-\tsignature >> expect &&\n+\tsignature >>expect &&\n \ttest_cmp expect actual1 &&\n \ttest_cmp expect actual2 &&\n \techo >fail &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\tsignature >> fail &&\n+\tsignature >>fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380781","messageId":"b4295846f5416f706e7f962d511eb77c9b59b7af.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 06/13] t4014: use indentable here-docs","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:18:58Z","receivedAt":"2019-08-20T07:19:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The convention is to use indentable here-docs within test cases so that\nthe here-docs line up with the rest of the code within the test case.\nChange here-docs from `<<\\EOF` to `<<-\\EOF` so that they can be indented\nalong with the rest of the test case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 368 ++++++++++++++++++++--------------------\n 1 file changed, 184 insertions(+), 184 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 075affb1e5..c07d868491 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1211,282 +1211,282 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expect &&\n-4:Subject: [PATCH] EOL\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat <<-\\EOF | sed \"s/EOL$//\" >expect &&\n+\t4:Subject: [PATCH] EOL\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n-Tested-by: Some One <someone@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-15:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\t(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n+\tTested-by: Some One <someone@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t15:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-Fooled-by-me: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tFooled-by-me: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-I want to mention about Signed-off-by: here.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:I want to mention about Signed-off-by: here.\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tI want to mention about Signed-off-by: here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:I want to mention about Signed-off-by: here.\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-My unfortunate\n-Signed-off-by: example happens to be wrapped here.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:Signed-off-by: example happens to be wrapped here.\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMy unfortunate\n+\tSigned-off-by: example happens to be wrapped here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:Signed-off-by: example happens to be wrapped here.\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Signed-off-by: my@house\n-Signed-off-by: your@house\n+\tSigned-off-by: my@house\n+\tSigned-off-by: your@house\n \n-A lot of houses.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: my@house\n-10:Signed-off-by: your@house\n-11:\n-13:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tA lot of houses.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: my@house\n+\t10:Signed-off-by: your@house\n+\t11:\n+\t13:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-Signed-off-by: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-12:Signed-off-by: my@house\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\t12:Signed-off-by: my@house\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Tested-by: my@house\n-Some Trash\n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-13:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tTested-by: my@house\n+\tSome Trash\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t13:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Reviewed-id: Noone\n-Tested-by: my@house\n-Change-id: Ideadbeef\n-Signed-off-by: C O Mitter <committer@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tReviewed-id: Noone\n+\tTested-by: my@house\n+\tChange-id: Ideadbeef\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380782","messageId":"34315412c85e36271bcfe773001a7aa541c6faf0.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 07/13] t4014: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:19:01Z","receivedAt":"2019-08-20T07:19:05Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex c07d868491..2048fb2008 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1502,42 +1502,42 @@ test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (2)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (3)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter ^master rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (4)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master.. >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (5)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 HEAD >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (6)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter with nothing' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380784","messageId":"de08dd886d70425e7b89a6fcd97d2472ecb97454.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 08/13] t4014: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:19:03Z","receivedAt":"2019-08-20T07:19:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Convert all instances of `cnt=$(... | wc -l) && test $cnt = N` into uses\nof `test_line_count()`.\n\nWhile we're at it, convert one instance of a Git command upstream of a\npipe into two commands. This prevents a failure of a Git command from\nbeing masked since only the return code of the last member of the pipe\nis shown.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 35 +++++++++++++++++++----------------\n 1 file changed, 19 insertions(+), 16 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 2048fb2008..176af4b902 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -60,23 +60,23 @@ test_expect_success setup '\n \n test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout master..side >patch0 &&\n-\tcnt=$(grep \"^From \" patch0 | wc -l) &&\n-\ttest $cnt = 3\n+\tgrep \"^From \" patch0 >from0 &&\n+\ttest_line_count = 3 from0\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '\n \tgit tag -a v1 -m tag side &&\n \tgit tag -a v2 -m tag master &&\n \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success \"format-patch doesn't consider merge commits\" '\n@@ -90,22 +90,23 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \tgit checkout -b merger master &&\n \ttest_tick &&\n \tgit merge --no-ff slave &&\n-\tcnt=$(git format-patch -3 --stdout | grep \"^From \" | wc -l) &&\n-\ttest $cnt = 3\n+\tgit format-patch -3 --stdout >patch &&\n+\tgrep \"^From \" patch >from &&\n+\ttest_line_count = 3 from\n '\n \n test_expect_success 'format-patch result applies' '\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'commit did not screw up the log message' '\n@@ -795,7 +796,8 @@ test_expect_success 'options no longer allowed for format-patch' '\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n \tgit format-patch --numstat --stdout master..side >output &&\n-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n+\tgrep \"^diff --git a/\" output >diff &&\n+\ttest_line_count = 5 diff\n '\n \n test_expect_success 'format-patch -- <path>' '\n@@ -852,8 +854,8 @@ test_expect_success 'format-patch --signature --cover-letter' '\n \tgit config --unset-all format.signature &&\n \tgit format-patch --stdout --signature=\"my sig\" --cover-letter \\\n \t\t-1 >output &&\n-\tgrep \"my sig\" output &&\n-\ttest 2 = $(grep \"my sig\" output | wc -l)\n+\tgrep \"my sig\" output >sig &&\n+\ttest_line_count = 2 sig\n '\n \n test_expect_success 'format.signature=\"\" suppresses signatures' '\n@@ -1591,7 +1593,8 @@ test_expect_success 'format-patch format.outputDirectory option' '\n \ttest_config format.outputDirectory patches &&\n \trm -fr patches &&\n \tgit format-patch master..side &&\n-\ttest $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)\n+\tgit rev-list master..side >list &&\n+\ttest_line_count = $(ls patches | wc -l) list\n '\n \n test_expect_success 'format-patch -o overrides format.outputDirectory' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380785","messageId":"dec5a62e82a70e52e46b946bb98332d14d80a76c.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 09/13] t4014: remove confusing pipe in check_threading()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:19:06Z","receivedAt":"2019-08-20T07:19:10Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In check_threading(), there was a Git command in the upstream of a pipe.\nIn order to not lose its status code, it was saved into a file. However,\nthis may be confusing so rewrite to redirect IO to file. This allows us\nto directly use the conventional &&-chain.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 5 ++---\n 1 file changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 176af4b902..7f74948e2c 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -319,7 +319,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n+\tgit format-patch --stdout \"$@\" >patch &&\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -334,8 +334,7 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' >actual &&\n-\ttest 0 = \"$(cat status.out)\" &&\n+\t' <patch >actual &&\n \ttest_cmp \"$expect\" actual\n }\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380783","messageId":"64069c0c540b109b46b2cc6c90e3b5c912aa18c5.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 10/13] t4014: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:19:08Z","receivedAt":"2019-08-20T07:19:13Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of Git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no Git commands upstream.\n\nThe other way is when a command is in a non-assignment subshell. The\nreturn code will be lost in favour of the surrounding command's. Rewrite\ninstances of this such that Git commands output to a file and\nsurrounding commands only call subshells with non-Git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 196 ++++++++++++++++++++++++----------------\n 1 file changed, 119 insertions(+), 77 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7f74948e2c..7b8c8fe136 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -33,7 +33,8 @@ test_expect_success setup '\n \tgit commit -m \"Side changes #3 with \\\\n backslash-n in it.\" &&\n \n \tgit checkout master &&\n-\tgit diff-tree -p C2 | git apply --index &&\n+\tgit diff-tree -p C2 >patch &&\n+\tgit apply --index <patch &&\n \ttest_tick &&\n \tgit commit -m \"Master accepts moral equivalent of #2\" &&\n \n@@ -110,7 +111,8 @@ test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n '\n \n test_expect_success 'commit did not screw up the log message' '\n-\tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit side >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n '\n \n test_expect_success 'format-patch did not screw up the log message' '\n@@ -119,7 +121,8 @@ test_expect_success 'format-patch did not screw up the log message' '\n '\n \n test_expect_success 'replay did not screw up the log message' '\n-\tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit rebuild-1 >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n '\n \n test_expect_success 'extra headers' '\n@@ -153,63 +156,73 @@ test_expect_success 'extra headers with multiple To:s' '\n \n test_expect_success 'additional command line cc (ascii)' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_success 'command line headers' '\n \tgit config --unset-all format.headers &&\n-\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n+\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side >patch6 &&\n+\tsed -e \"/^\\$/q\" patch6 >hdrs6 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" hdrs6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch7\n+\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side >patch7 &&\n+\tsed -e \"/^\\$/q\" patch7 >hdrs7 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs7 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs7\n '\n \n test_expect_success 'command line To: header (ascii)' '\n \tgit config --unset-all format.headers &&\n-\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n-\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n-\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs9\n '\n \n # check_patch <patch>: Verify that <patch> looks like a half-sane\n@@ -221,76 +234,76 @@ check_patch () {\n }\n \n test_expect_success 'format.from=false' '\n-\tgit -c format.from=false format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n+\tgit -c format.from=false format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n \tcheck_patch patch &&\n-\t! grep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\t! grep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from=true' '\n-\tgit -c format.from=true format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\tgit -c format.from=true format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from with address' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-from overrides format.from' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--from overrides format.from' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-to overrides config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-to --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch10 &&\n-\tcheck_patch patch10 &&\n-\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" patch10\n+\tgit format-patch --no-to --stdout master..side >patch10 &&\n+\tsed -e \"/^\\$/q\" patch10 >hdrs10 &&\n+\tcheck_patch hdrs10 &&\n+\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs10\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n-\t\t--stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch11 &&\n-\tcheck_patch patch11 &&\n-\t! grep \"^To: Someone <someone@out.there>\\$\" patch11 &&\n-\tgrep \"^To: Someone Else <else@out.there>\\$\" patch11\n+\t\t--stdout master..side >patch11 &&\n+\tsed -e \"/^\\$/q\" patch11 >hdrs11 &&\n+\tcheck_patch hdrs11 &&\n+\t! grep \"^To: Someone <someone@out.there>\\$\" hdrs11 &&\n+\tgrep \"^To: Someone Else <else@out.there>\\$\" hdrs11\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-cc --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch12 &&\n-\tcheck_patch patch12 &&\n-\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" patch12\n+\tgit format-patch --no-cc --stdout master..side >patch12 &&\n+\tsed -e \"/^\\$/q\" patch12 >hdrs12 &&\n+\tcheck_patch hdrs12 &&\n+\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" hdrs12\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-add-header --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch13 &&\n-\tcheck_patch patch13 &&\n-\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" patch13\n+\tgit format-patch --no-add-header --stdout master..side >patch13 &&\n+\tsed -e \"/^\\$/q\" patch13 >hdrs13 &&\n+\tcheck_patch hdrs13 &&\n+\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" hdrs13\n '\n \n test_expect_success 'multiple files' '\n@@ -808,20 +821,24 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n \tgit format-patch --ignore-if-in-upstream HEAD\n '\n \n-git_version=\"$(git --version | sed \"s/.* //\")\"\n+test_expect_success 'get git version' '\n+\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n+'\n \n signature() {\n \tprintf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n }\n \n test_expect_success 'format-patch default signature' '\n-\tgit format-patch --stdout -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature >expect &&\n \ttest_cmp expect output\n '\n \n test_expect_success 'format-patch --signature' '\n-\tgit format-patch --stdout --signature=\"my sig\" -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout --signature=\"my sig\" -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature \"my sig\" >expect &&\n \ttest_cmp expect output\n '\n@@ -1606,19 +1623,40 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' '\n \n test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n-\tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n-\tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 -1 >patch &&\n+\ttail -n 7 patch >actual1 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&\n+\ttail -n 7 patch >actual2 &&\n+\n \techo >expect &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\tgit rev-parse HEAD~3 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>expect &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n \tsignature >>expect &&\n \ttest_cmp expect actual1 &&\n \ttest_cmp expect actual2 &&\n+\n \techo >fail &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>fail &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n \tsignature >>fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n@@ -1629,7 +1667,8 @@ test_expect_success 'format-patch --base errors out when base commit is in revis\n \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expect &&\n+\tgit rev-parse HEAD~2 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1668,7 +1707,8 @@ test_expect_success 'format-patch --base=auto' '\n \ttest_commit N2 &&\n \tgit format-patch --stdout --base=auto -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1705,7 +1745,8 @@ test_expect_success 'format-patch format.useAutoBaseoption' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1714,7 +1755,8 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expect &&\n+\tgit rev-parse HEAD~1 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380786","messageId":"c12534ab5dc67bdecad45e10d45d428bc783cb09.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 11/13] Doc: add more detail for git-format-patch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:19:11Z","receivedAt":"2019-08-20T07:19:15Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In git-format-patch.txt, we were missing some key user information.\nFirst of all, document the special value of `--base=auto`.\n\nNext, while we're at it, surround option arguments with <>.\n\nFinally, document the `format.outputDirectory` config and change\n`format.coverletter` to use camel case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-format-patch.txt | 17 ++++++++++-------\n 1 file changed, 10 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex b9b97e63ae..95bc4d53ca 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n+\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,7 +159,7 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=Message-Id::\n+--in-reply-to=<Message-Id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n \treply to the given Message-Id, which avoids breaking threads to\n \tprovide a new patch series.\n@@ -314,7 +314,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n --base=<commit>::\n \tRecord the base tree information to identify the state the\n \tpatch series applies to.  See the BASE TREE INFORMATION section\n-\tbelow for details.\n+\tbelow for details. If <commit> is \"auto\", a base commit is\n+\tautomatically chosen.\n \n --root::\n \tTreat the revision argument as a <revision range>, even if it\n@@ -330,8 +331,9 @@ CONFIGURATION\n -------------\n You can specify extra mail header lines to be added to each message,\n defaults for the subject prefix and file suffix, number patches when\n-outputting more than one patch, add \"To\" or \"Cc:\" headers, configure\n-attachments, and sign off patches with configuration variables.\n+outputting more than one patch, add \"To:\" or \"Cc:\" headers, configure\n+attachments, change the patch output directory, and sign off patches\n+with configuration variables.\n \n ------------\n [format]\n@@ -343,7 +345,8 @@ attachments, and sign off patches with configuration variables.\n \tcc = <email>\n \tattach [ = mime-boundary-string ]\n \tsignOff = true\n-\tcoverletter = auto\n+\toutputDirectory = <directory>\n+\tcoverLetter = auto\n ------------\n \n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380787","messageId":"a08273ebccb3cc0b6cbe8a4391ff12f011bfa0b8.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 12/13] config/format.txt: specify default value of format.coverLetter","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:19:13Z","receivedAt":"2019-08-20T07:19:18Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex 414a5a8a9d..cb629fa769 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -77,6 +77,7 @@ format.coverLetter::\n \tA boolean that controls whether to generate a cover-letter when\n \tformat-patch is invoked, but in addition can be set to \"auto\", to\n \tgenerate a cover-letter only when there's more than one patch.\n+\tDefault is false.\n \n format.outputDirectory::\n \tSet a custom directory to store the resulting files instead of the\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380788","messageId":"de599f7ca9b5fe7e298bba0bb8c5d05f2f5cf34f.1566285151.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:19:16Z","receivedAt":"2019-08-20T07:19:21Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Teach format-patch to use the first line of the branch description as\nthe Subject: of the generated cover letter, rather than \"*** SUBJECT\nHERE ***\" if `--infer-cover-subject` is specified or the corresponding\n`format.inferCoverSubject` option is enabled. This complements the\nexisting inclusion of the branch description in the cover letter body.\n\nThe reason why this behaviour is not made default is because this change\nis not backwards compatible and may break existing tooling that may rely\non the default template subject.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt    |  6 ++++\n Documentation/git-format-patch.txt |  7 ++++\n builtin/log.c                      | 56 +++++++++++++++++++-----------\n t/t4014-format-patch.sh            | 35 ++++++++++++++++++-\n 4 files changed, 82 insertions(+), 22 deletions(-)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex cb629fa769..2723566289 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -36,6 +36,12 @@ format.subjectPrefix::\n \tThe default for format-patch is to output files with the '[PATCH]'\n \tsubject prefix. Use this variable to change that prefix.\n \n+format.inferCoverSubject::\n+\tA boolean that controls whether or not to take the first line of\n+\tthe branch description as the subject for the cover letter. See the\n+\t`--infer-cover-subject` option in linkgit:git-format-patch[1].\n+\tDefault is false.\n+\n format.signature::\n \tThe default for format-patch is to output a signature containing\n \tthe Git version number. Use this variable to change that default.\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 95bc4d53ca..c5bc0bf5c6 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -19,6 +19,7 @@ SYNOPSIS\n \t\t   [--start-number <n>] [--numbered-files]\n \t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n+\t\t   [--[no-]infer-cover-subject]\n \t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n@@ -171,6 +172,11 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n+--[no-]infer-cover-subject::\n+\tUse the beginning of the branch description (up to the first\n+\tblank line) as the cover letter subject instead of the default\n+\t\"*** SUBJECT HERE ***\".\n+\n --subject-prefix=<Subject-Prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n \tline, instead use '[<Subject-Prefix>]'. This\n@@ -347,6 +353,7 @@ with configuration variables.\n \tsignOff = true\n \toutputDirectory = <directory>\n \tcoverLetter = auto\n+\tinferCoverSubject = true\n ------------\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 44b10b3415..a19b746495 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -774,6 +774,7 @@ static const char *signature = git_version_string;\n static const char *signature_file;\n static int config_cover_letter;\n static const char *config_output_directory;\n+static int infer_cover_subject;\n \n enum {\n \tCOVER_UNSET,\n@@ -887,6 +888,10 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\t}\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"format.infercoversubject\")) {\n+\t\tinfer_cover_subject = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n \n \treturn git_log_config(var, value, cb);\n }\n@@ -993,20 +998,6 @@ static void print_signature(FILE *file)\n \tputc('\\n', file);\n }\n \n-static void add_branch_description(struct strbuf *buf, const char *branch_name)\n-{\n-\tstruct strbuf desc = STRBUF_INIT;\n-\tif (!branch_name || !*branch_name)\n-\t\treturn;\n-\tread_branch_desc(&desc, branch_name);\n-\tif (desc.len) {\n-\t\tstrbuf_addch(buf, '\\n');\n-\t\tstrbuf_addbuf(buf, &desc);\n-\t\tstrbuf_addch(buf, '\\n');\n-\t}\n-\tstrbuf_release(&desc);\n-}\n-\n static char *find_branch_name(struct rev_info *rev)\n {\n \tint i, positive = -1;\n@@ -1057,13 +1048,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t      struct commit *origin,\n \t\t\t      int nr, struct commit **list,\n \t\t\t      const char *branch_name,\n+\t\t\t      int infer_subject,\n \t\t\t      int quiet)\n {\n \tconst char *committer;\n-\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n-\tconst char *msg;\n+\tconst char *subject = \"*** SUBJECT HERE ***\";\n+\tconst char *body = \"*** BLURB HERE ***\";\n+\tconst char *description = NULL;\n \tstruct shortlog log;\n \tstruct strbuf sb = STRBUF_INIT;\n+\tstruct strbuf description_sb = STRBUF_INIT;\n+\tstruct strbuf subject_sb = STRBUF_INIT;\n \tint i;\n \tconst char *encoding = \"UTF-8\";\n \tint need_8bit_cte = 0;\n@@ -1091,17 +1086,34 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (!branch_name)\n \t\tbranch_name = find_branch_name(rev);\n \n-\tmsg = body;\n+\tif (branch_name && *branch_name)\n+\t\tread_branch_desc(&description_sb, branch_name);\n+\n+\tif (description_sb.len) {\n+\t\tif (infer_subject) {\n+\t\t\tdescription = format_subject(&subject_sb, description_sb.buf, \" \");\n+\t\t\tsubject = subject_sb.buf;\n+\t\t} else {\n+\t\t\tdescription = description_sb.buf;\n+\t\t}\n+\t}\n+\n \tpp.fmt = CMIT_FMT_EMAIL;\n \tpp.date_mode.type = DATE_RFC2822;\n \tpp.rev = rev;\n \tpp.print_email_subject = 1;\n \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n-\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n-\tpp_remainder(&pp, &msg, &sb, 0);\n-\tadd_branch_description(&sb, branch_name);\n+\tpp_title_line(&pp, &subject, &sb, encoding, need_8bit_cte);\n+\tpp_remainder(&pp, &body, &sb, 0);\n+\tif (description) {\n+\t\tstrbuf_addch(&sb, '\\n');\n+\t\tstrbuf_addstr(&sb, description);\n+\t\tstrbuf_addch(&sb, '\\n');\n+\t}\n \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n \n+\tstrbuf_release(&description_sb);\n+\tstrbuf_release(&subject_sb);\n \tstrbuf_release(&sb);\n \n \tshortlog_init(&log);\n@@ -1577,6 +1589,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t{ OPTION_CALLBACK, 0, \"rfc\", &rev, NULL,\n \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n+\t\tOPT_BOOL(0, \"infer-cover-subject\", &infer_cover_subject,\n+\t\t\t    N_(\"infer a cover letter subject from branch description\")),\n \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n@@ -1916,7 +1930,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tif (thread)\n \t\t\tgen_message_id(&rev, \"cover\");\n \t\tmake_cover_letter(&rev, use_stdout,\n-\t\t\t\t  origin, nr, list, branch_name, quiet);\n+\t\t\t\t  origin, nr, list, branch_name, infer_cover_subject, quiet);\n \t\tprint_bases(&bases, rev.diffopt.file);\n \t\tprint_signature(rev.diffopt.file);\n \t\ttotal++;\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 7b8c8fe136..94a3191aca 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -822,7 +822,7 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n '\n \n test_expect_success 'get git version' '\n-\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n+\tgit_version=\"$(git --version >version && sed \"s/.* //\" <version)\"\n '\n \n signature() {\n@@ -1516,6 +1516,39 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cover letter with config subject' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.inferCoverSubject true &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line subject' '\n+\ttest_config branch.rebuild-1.description \"command-line subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --infer-cover-subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] command-line subject$\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line --no-infer-cover-subject overrides config' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.inferCoverSubject true &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --no-infer-cover-subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject\" actual &&\n+\tgrep \"^body\" actual\n+'\n+\n test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"380789","messageId":"20190820073130.GA32049@archbookpro.localdomain","threadId":"51687","inReplyTo":"64069c0c540b109b46b2cc6c90e3b5c912aa18c5.1566285151.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 10/13] t4014: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-20T07:31:30Z","receivedAt":"2019-08-20T07:31:35Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Tue, Aug 20, 2019 at 03:19:08AM -0400, Denton Liu wrote:\n> @@ -808,20 +821,24 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n>  \tgit format-patch --ignore-if-in-upstream HEAD\n>  '\n>  \n> -git_version=\"$(git --version | sed \"s/.* //\")\"\n> +test_expect_success 'get git version' '\n> +\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n> +'\n\nOops, this should read\n\n\tgit_version=\"$(git --version >version && sed \"s/.* //\" <version)\"\n\nAnyway, I was considering keeping the upstream pipe but it feels very\nweird having an unchecked Git command (especially since, from what I can\ntell, `git --version` isn't tested anywhere else). Thoughts?\n\n>  \n>  signature() {\n>  \tprintf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n>  }\n>  \n>  test_expect_success 'format-patch default signature' '\n> -\tgit format-patch --stdout -1 | tail -n 3 >output &&\n> +\tgit format-patch --stdout -1 >patch &&\n> +\ttail -n 3 patch >output &&\n>  \tsignature >expect &&\n>  \ttest_cmp expect output\n>  '\n>  \n>  test_expect_success 'format-patch --signature' '\n> -\tgit format-patch --stdout --signature=\"my sig\" -1 | tail -n 3 >output &&\n> +\tgit format-patch --stdout --signature=\"my sig\" -1 >patch &&\n> +\ttail -n 3 patch >output &&\n>  \tsignature \"my sig\" >expect &&\n>  \ttest_cmp expect output\n>  '\n"},{"id":"380841","messageId":"34a613d0-2ac0-b642-b14d-59ca4ef2738e@kdbg.org","threadId":"51687","inReplyTo":"20190820073130.GA32049@archbookpro.localdomain","subject":"Re: [PATCH v3 10/13] t4014: stop losing return codes of git commands","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2019-08-20T19:04:22Z","receivedAt":"2019-08-20T19:04:27Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 20.08.19 um 09:31 schrieb Denton Liu:\n> Oops, this should read\n> \n> \tgit_version=\"$(git --version >version && sed \"s/.* //\" <version)\"\n\nsed is not necessary. Make that\n\n\tgit_version=$(git --version) &&\n\tgit_version=${git_version##* }\n\n-- Hannes\n"},{"id":"380864","messageId":"CAPig+cTAQEdqHHfFzW=khX95qNL8xvyoiN=mjfaLpwJH4axDAw@mail.gmail.com","threadId":"51687","inReplyTo":"568b3a03a08faf109220aff47c1fd3e68fde3bfe.1566285151.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 02/13] t4014: s/expected/expect/","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-20T21:31:38Z","receivedAt":"2019-08-20T21:31:52Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Aug 20, 2019 at 3:19 AM Denton Liu <liu.denton@gmail.com> wrote:\n> For test cases, the usual convention is to name expected output files\n> \"expect\", not \"expected\". Replace all instances with \"expected\" with\n\ns/with \"expected\"/of \"expected\"/\n\n> \"expect\" except for one case where the \"expected\" is used as the name\n> of a test case.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n"},{"id":"380899","messageId":"xmqqimqqs7cm.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"c12534ab5dc67bdecad45e10d45d428bc783cb09.1566285151.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 11/13] Doc: add more detail for git-format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-21T18:26:17Z","receivedAt":"2019-08-21T18:26:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Next, while we're at it, surround option arguments with <>.\n\nI'd suggest squashing this in to complete the above.\n\ncf. <xmqq1rxfveym.fsf@gitster-ct.c.googlers.com>\n---\n Documentation/git-format-patch.txt | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 95bc4d53ca..0ac56f4b70 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n+\t\t   [--rfc] [--subject-prefix=<subject prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,9 +159,9 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=<Message-Id>::\n+--in-reply-to=<message id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n-\treply to the given Message-Id, which avoids breaking threads to\n+\treply to the given <message id>, which avoids breaking threads to\n \tprovide a new patch series.\n \n --ignore-if-in-upstream::\n@@ -171,9 +171,9 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n---subject-prefix=<Subject-Prefix>::\n+--subject-prefix=<subject prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n-\tline, instead use '[<Subject-Prefix>]'. This\n+\tline, instead use '[<subject prefix>]'. This\n \tallows for useful naming of a patch series, and can be\n \tcombined with the `--numbered` option.\n \n-- \n2.23.0-266-g1e4abb0e04\n\n"},{"id":"380905","messageId":"xmqq8srms4ak.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"de599f7ca9b5fe7e298bba0bb8c5d05f2f5cf34f.1566285151.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-21T19:32:19Z","receivedAt":"2019-08-21T19:32:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Teach format-patch to use the first line of the branch description as\n> the Subject: of the generated cover letter, rather than \"*** SUBJECT\n\nI would not say \"the first line\", as I do not think that is what\nhappens by calling pretty.c::format_subject().  The function is\ndesigned to take the first paragraph, and the behaviour is in line\nwith how the subject is formed from the log message in a commit\nobject.  I'd say \"the first paragraph\" instead.\n\n> HERE ***\" if `--infer-cover-subject` is specified or the corresponding\n> `format.inferCoverSubject` option is enabled. This complements the\n> existing inclusion of the branch description in the cover letter body.\n>\n> The reason why this behaviour is not made default is because this change\n> is not backwards compatible and may break existing tooling that may rely\n> on the default template subject.\n\nI'd suggest writing it more assertively, rather than appearing to be\nmaking lame excuses.  Perhaps like\n\n\tThe new behaviour is not made default; doing so would\n\tsurprise existing users, which is not a good idea.\n\nOr just drop the excuse of not changing the default altogether.  It\nis pretty much the standard practice for us to keep the existing\nbehaviour the same and to make the new behaviour opt-in.\n\nHaving said that, I suspect that in the longer term, people would\nwant to see this new behaviour with a bit of tweak become the new\ndefault.\n\nThe \"tweak\" I suspect is needed is to behave sensibly when \"the\nfirst line\" ends up to be too long a subject.  Whether we make this\nthe new default or keep this optional, the issue exists either way.\n\nOne way to make it behave sensibly with overly long first paragraph\nis to fall back to the current behaviour.  We can think about the way\nan ideally \"tweaked\" version of this patch uses the branch description\nlike this:\n\n 1. Preprocess and prepare the branch description string for use in\n    the next step.\n\n    - If there is no branch description, then pretend as if \"***\n      Subject Here ***\" followed by a blank line and \"*** Blurb here\n      ***\" were given as the branch description in the step 2.\n\n    - If the first paragraph of the description is overly long, then\n      prepend \"*** Subject Here ***\" followed by a blank line before\n      the branch description, and use that the branch description\n      string in the step 2 (this is the \"tweak to make it behave\n      sensibly\" change I suggested above).\n\n    - Otherwise, use the given branch description in the step 2.\n      Optionally, when a backward-compatibility knob is in effect,\n      always prepend the \"Subject Here\" paragraph.  That way, step\n      2. would end up keeping the traditional behaviour.\n\n 2. Split the first pragraph out of the branch description.  Use it\n    as the subject, and use the remainder in the body.\n\nAnd if we view the behaviour that way, it becomes clear that the\n\"--infer-cover-subject\" is a fairly meaningless name for the option.\nWe unconditionally use the branch description to fill in the subject\nand the body, but the traditional way and the updated one when the\nfirst paragraph is overly long use placeholder string for the\nsubject instead.  I.e. a better name for the option may be something\nlike --placeholder-subject-in-cover (as opposed to taking the\nsubject in cover from the branch description), and it can be negated\ni.e. --no-placeholder-subject-in-cover, to force keeping the old\nbehaviour.\n\nAnd I suspect that the approach would allow the implementation to\nbecome simple and straight-forward.  The \"branch description\" needs\nto be prepared in a few different ways (i.e. if there is no\nbranch.*.description, you'd fill a fixed string; after reading\nbranch.*.description and measuring the first paragraph, you may\nprepend another fixed string), but after that is done, the actual\ngeneration of the cover letter will need NO conditional logic. It\njust needs to split that into the first paragraph to be used as the\nsubject, and the remainder used in the body.\n\nHmm?\n\n> @@ -887,6 +888,10 @@ static int git_format_config(const char *var, const char *value, void *cb)\n>  \t\t}\n>  \t\treturn 0;\n>  \t}\n> +\tif (!strcmp(var, \"format.infercoversubject\")) {\n> +\t\tinfer_cover_subject = git_config_bool(var, value);\n> +\t\treturn 0;\n> +\t}\n>  \n>  \treturn git_log_config(var, value, cb);\n>  }\n> @@ -993,20 +998,6 @@ static void print_signature(FILE *file)\n>  \tputc('\\n', file);\n>  }\n>  \n> -static void add_branch_description(struct strbuf *buf, const char *branch_name)\n> -{\n> -\tstruct strbuf desc = STRBUF_INIT;\n> -\tif (!branch_name || !*branch_name)\n> -\t\treturn;\n> -\tread_branch_desc(&desc, branch_name);\n> -\tif (desc.len) {\n> -\t\tstrbuf_addch(buf, '\\n');\n> -\t\tstrbuf_addbuf(buf, &desc);\n> -\t\tstrbuf_addch(buf, '\\n');\n> -\t}\n> -\tstrbuf_release(&desc);\n> -}\n> -\n>  static char *find_branch_name(struct rev_info *rev)\n>  {\n>  \tint i, positive = -1;\n> @@ -1057,13 +1048,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \t\t\t      struct commit *origin,\n>  \t\t\t      int nr, struct commit **list,\n>  \t\t\t      const char *branch_name,\n> +\t\t\t      int infer_subject,\n>  \t\t\t      int quiet)\n>  {\n>  \tconst char *committer;\n> -\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n> -\tconst char *msg;\n> +\tconst char *subject = \"*** SUBJECT HERE ***\";\n> +\tconst char *body = \"*** BLURB HERE ***\";\n> +\tconst char *description = NULL;\n>  \tstruct shortlog log;\n>  \tstruct strbuf sb = STRBUF_INIT;\n> +\tstruct strbuf description_sb = STRBUF_INIT;\n> +\tstruct strbuf subject_sb = STRBUF_INIT;\n>  \tint i;\n>  \tconst char *encoding = \"UTF-8\";\n>  \tint need_8bit_cte = 0;\n> @@ -1091,17 +1086,34 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \tif (!branch_name)\n>  \t\tbranch_name = find_branch_name(rev);\n>  \n> -\tmsg = body;\n> +\tif (branch_name && *branch_name)\n> +\t\tread_branch_desc(&description_sb, branch_name);\n> +\n> +\tif (description_sb.len) {\n> +\t\tif (infer_subject) {\n> +\t\t\tdescription = format_subject(&subject_sb, description_sb.buf, \" \");\n> +\t\t\tsubject = subject_sb.buf;\n> +\t\t} else {\n> +\t\t\tdescription = description_sb.buf;\n> +\t\t}\n> +\t}\n> +\n>  \tpp.fmt = CMIT_FMT_EMAIL;\n>  \tpp.date_mode.type = DATE_RFC2822;\n>  \tpp.rev = rev;\n>  \tpp.print_email_subject = 1;\n>  \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n> -\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n> -\tpp_remainder(&pp, &msg, &sb, 0);\n> -\tadd_branch_description(&sb, branch_name);\n> +\tpp_title_line(&pp, &subject, &sb, encoding, need_8bit_cte);\n> +\tpp_remainder(&pp, &body, &sb, 0);\n> +\tif (description) {\n> +\t\tstrbuf_addch(&sb, '\\n');\n> +\t\tstrbuf_addstr(&sb, description);\n> +\t\tstrbuf_addch(&sb, '\\n');\n> +\t}\n>  \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n>  \n> +\tstrbuf_release(&description_sb);\n> +\tstrbuf_release(&subject_sb);\n>  \tstrbuf_release(&sb);\n>  \n>  \tshortlog_init(&log);\n> @@ -1577,6 +1589,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n>  \t\t{ OPTION_CALLBACK, 0, \"rfc\", &rev, NULL,\n>  \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n>  \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n> +\t\tOPT_BOOL(0, \"infer-cover-subject\", &infer_cover_subject,\n> +\t\t\t    N_(\"infer a cover letter subject from branch description\")),\n>  \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n>  \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n>  \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n> @@ -1916,7 +1930,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n>  \t\tif (thread)\n>  \t\t\tgen_message_id(&rev, \"cover\");\n>  \t\tmake_cover_letter(&rev, use_stdout,\n> -\t\t\t\t  origin, nr, list, branch_name, quiet);\n> +\t\t\t\t  origin, nr, list, branch_name, infer_cover_subject, quiet);\n>  \t\tprint_bases(&bases, rev.diffopt.file);\n>  \t\tprint_signature(rev.diffopt.file);\n>  \t\ttotal++;\n> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> index 7b8c8fe136..94a3191aca 100755\n> --- a/t/t4014-format-patch.sh\n> +++ b/t/t4014-format-patch.sh\n> @@ -822,7 +822,7 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n>  '\n>  \n>  test_expect_success 'get git version' '\n> -\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n> +\tgit_version=\"$(git --version >version && sed \"s/.* //\" <version)\"\n>  '\n>  \n>  signature() {\n> @@ -1516,6 +1516,39 @@ test_expect_success 'format patch ignores color.ui' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'cover letter with config subject' '\n> +\ttest_config branch.rebuild-1.description \"config subject\n> +\n> +body\" &&\n> +\ttest_config format.inferCoverSubject true &&\n> +\tgit checkout rebuild-1 &&\n> +\tgit format-patch --stdout --cover-letter master >actual &&\n> +\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n> +\tgrep \"^body\" actual\n> +'\n> +\n> +test_expect_success 'cover letter with command-line subject' '\n> +\ttest_config branch.rebuild-1.description \"command-line subject\n> +\n> +body\" &&\n> +\tgit checkout rebuild-1 &&\n> +\tgit format-patch --stdout --cover-letter --infer-cover-subject master >actual &&\n> +\tgrep \"^Subject: \\[PATCH 0/2\\] command-line subject$\" actual &&\n> +\tgrep \"^body\" actual\n> +'\n> +\n> +test_expect_success 'cover letter with command-line --no-infer-cover-subject overrides config' '\n> +\ttest_config branch.rebuild-1.description \"config subject\n> +\n> +body\" &&\n> +\ttest_config format.inferCoverSubject true &&\n> +\tgit checkout rebuild-1 &&\n> +\tgit format-patch --stdout --cover-letter --no-infer-cover-subject master >actual &&\n> +\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n> +\tgrep \"^config subject\" actual &&\n> +\tgrep \"^body\" actual\n> +'\n> +\n>  test_expect_success 'cover letter using branch description (1)' '\n>  \tgit checkout rebuild-1 &&\n>  \ttest_config branch.rebuild-1.description hello &&\n"},{"id":"380973","messageId":"xmqqsgptnedb.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 00/13] format-patch: learn --infer-cover-subject option (also t4014 cleanup)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-22T20:18:08Z","receivedAt":"2019-08-22T20:18:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> While we're at it, perform some major cleanup of t4014 including some\n> stylistic cleanup and also, unmasking of Git return codes.\n\nWow.  It seems that \"while we're at it\" grew quite large and (from\npurely patch count's point of view) ends up appearing as if it were\nthe primary focus of the series ;-)\n\nThanks for tackling the age-old mess.  Admittedly, this particular\nscript is from the older parts of Git's history and a clean-up was\nlong overdue.\n\nWith the \"split pipes\" approach taken in patches 09 and 10, we'd end\nup leaving more untracked and unignored cruft in the working tree. I\ndo not think they would cause problems with the existing tests after\nreading the patches over.\n\n\n"},{"id":"381023","messageId":"20190823181545.GA14048@archbookpro.localdomain","threadId":"51687","inReplyTo":"xmqq8srms4ak.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-23T18:15:45Z","receivedAt":"2019-08-23T18:15:52Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Wed, Aug 21, 2019 at 12:32:19PM -0700, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> > Teach format-patch to use the first line of the branch description as\n> > the Subject: of the generated cover letter, rather than \"*** SUBJECT\n> \n> I would not say \"the first line\", as I do not think that is what\n> happens by calling pretty.c::format_subject().  The function is\n> designed to take the first paragraph, and the behaviour is in line\n> with how the subject is formed from the log message in a commit\n> object.  I'd say \"the first paragraph\" instead.\n> \n> > HERE ***\" if `--infer-cover-subject` is specified or the corresponding\n> > `format.inferCoverSubject` option is enabled. This complements the\n> > existing inclusion of the branch description in the cover letter body.\n> >\n> > The reason why this behaviour is not made default is because this change\n> > is not backwards compatible and may break existing tooling that may rely\n> > on the default template subject.\n> \n> I'd suggest writing it more assertively, rather than appearing to be\n> making lame excuses.  Perhaps like\n> \n> \tThe new behaviour is not made default; doing so would\n> \tsurprise existing users, which is not a good idea.\n> \n> Or just drop the excuse of not changing the default altogether.  It\n> is pretty much the standard practice for us to keep the existing\n> behaviour the same and to make the new behaviour opt-in.\n> \n> Having said that, I suspect that in the longer term, people would\n> want to see this new behaviour with a bit of tweak become the new\n> default.\n> \n> The \"tweak\" I suspect is needed is to behave sensibly when \"the\n> first line\" ends up to be too long a subject.  Whether we make this\n> the new default or keep this optional, the issue exists either way.\n\nThe reason why I chose to make this an \"opt-in\" option was because there\ncurrently doesn't exist a standard on how to write branch descriptions\nlike there does for commit messages (i.e. subject then body, subject\nless than x characters). However, against best practices, some\ndevelopers like to have really long subjects. As a result, there's no\n\"real\" way of telling whether the first paragraph is a long subject or a\nshort paragraph.\n\nAs a result, we should allow the cover subject to be read from the\nbranch description only if the developer explicitly chooses this (either\nwith `--infer-cover-subject` the config option). This way, we won't have\nto deal with the ambiguity of deciding whether or not the first\nparagraph is truly a subject and stepping on users' toes if we end up\ndeciding wrong.\n\nThoughts?\n\n> \n> One way to make it behave sensibly with overly long first paragraph\n> is to fall back to the current behaviour.  We can think about the way\n> an ideally \"tweaked\" version of this patch uses the branch description\n> like this:\n> \n>  1. Preprocess and prepare the branch description string for use in\n>     the next step.\n> \n>     - If there is no branch description, then pretend as if \"***\n>       Subject Here ***\" followed by a blank line and \"*** Blurb here\n>       ***\" were given as the branch description in the step 2.\n> \n>     - If the first paragraph of the description is overly long, then\n>       prepend \"*** Subject Here ***\" followed by a blank line before\n>       the branch description, and use that the branch description\n>       string in the step 2 (this is the \"tweak to make it behave\n>       sensibly\" change I suggested above).\n> \n>     - Otherwise, use the given branch description in the step 2.\n>       Optionally, when a backward-compatibility knob is in effect,\n>       always prepend the \"Subject Here\" paragraph.  That way, step\n>       2. would end up keeping the traditional behaviour.\n> \n>  2. Split the first pragraph out of the branch description.  Use it\n>     as the subject, and use the remainder in the body.\n> \n> And if we view the behaviour that way, it becomes clear that the\n> \"--infer-cover-subject\" is a fairly meaningless name for the option.\n> We unconditionally use the branch description to fill in the subject\n> and the body, but the traditional way and the updated one when the\n> first paragraph is overly long use placeholder string for the\n> subject instead.  I.e. a better name for the option may be something\n> like --placeholder-subject-in-cover (as opposed to taking the\n> subject in cover from the branch description), and it can be negated\n> i.e. --no-placeholder-subject-in-cover, to force keeping the old\n> behaviour.\n> \n> And I suspect that the approach would allow the implementation to\n> become simple and straight-forward.  The \"branch description\" needs\n> to be prepared in a few different ways (i.e. if there is no\n> branch.*.description, you'd fill a fixed string; after reading\n> branch.*.description and measuring the first paragraph, you may\n> prepend another fixed string), but after that is done, the actual\n> generation of the cover letter will need NO conditional logic. It\n> just needs to split that into the first paragraph to be used as the\n> subject, and the remainder used in the body.\n> \n> Hmm?\n> \n> > @@ -887,6 +888,10 @@ static int git_format_config(const char *var, const char *value, void *cb)\n> >  \t\t}\n> >  \t\treturn 0;\n> >  \t}\n> > +\tif (!strcmp(var, \"format.infercoversubject\")) {\n> > +\t\tinfer_cover_subject = git_config_bool(var, value);\n> > +\t\treturn 0;\n> > +\t}\n> >  \n> >  \treturn git_log_config(var, value, cb);\n> >  }\n> > @@ -993,20 +998,6 @@ static void print_signature(FILE *file)\n> >  \tputc('\\n', file);\n> >  }\n> >  \n> > -static void add_branch_description(struct strbuf *buf, const char *branch_name)\n> > -{\n> > -\tstruct strbuf desc = STRBUF_INIT;\n> > -\tif (!branch_name || !*branch_name)\n> > -\t\treturn;\n> > -\tread_branch_desc(&desc, branch_name);\n> > -\tif (desc.len) {\n> > -\t\tstrbuf_addch(buf, '\\n');\n> > -\t\tstrbuf_addbuf(buf, &desc);\n> > -\t\tstrbuf_addch(buf, '\\n');\n> > -\t}\n> > -\tstrbuf_release(&desc);\n> > -}\n> > -\n> >  static char *find_branch_name(struct rev_info *rev)\n> >  {\n> >  \tint i, positive = -1;\n> > @@ -1057,13 +1048,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n> >  \t\t\t      struct commit *origin,\n> >  \t\t\t      int nr, struct commit **list,\n> >  \t\t\t      const char *branch_name,\n> > +\t\t\t      int infer_subject,\n> >  \t\t\t      int quiet)\n> >  {\n> >  \tconst char *committer;\n> > -\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n> > -\tconst char *msg;\n> > +\tconst char *subject = \"*** SUBJECT HERE ***\";\n> > +\tconst char *body = \"*** BLURB HERE ***\";\n> > +\tconst char *description = NULL;\n> >  \tstruct shortlog log;\n> >  \tstruct strbuf sb = STRBUF_INIT;\n> > +\tstruct strbuf description_sb = STRBUF_INIT;\n> > +\tstruct strbuf subject_sb = STRBUF_INIT;\n> >  \tint i;\n> >  \tconst char *encoding = \"UTF-8\";\n> >  \tint need_8bit_cte = 0;\n> > @@ -1091,17 +1086,34 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n> >  \tif (!branch_name)\n> >  \t\tbranch_name = find_branch_name(rev);\n> >  \n> > -\tmsg = body;\n> > +\tif (branch_name && *branch_name)\n> > +\t\tread_branch_desc(&description_sb, branch_name);\n> > +\n> > +\tif (description_sb.len) {\n> > +\t\tif (infer_subject) {\n> > +\t\t\tdescription = format_subject(&subject_sb, description_sb.buf, \" \");\n> > +\t\t\tsubject = subject_sb.buf;\n> > +\t\t} else {\n> > +\t\t\tdescription = description_sb.buf;\n> > +\t\t}\n> > +\t}\n> > +\n> >  \tpp.fmt = CMIT_FMT_EMAIL;\n> >  \tpp.date_mode.type = DATE_RFC2822;\n> >  \tpp.rev = rev;\n> >  \tpp.print_email_subject = 1;\n> >  \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n> > -\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n> > -\tpp_remainder(&pp, &msg, &sb, 0);\n> > -\tadd_branch_description(&sb, branch_name);\n> > +\tpp_title_line(&pp, &subject, &sb, encoding, need_8bit_cte);\n> > +\tpp_remainder(&pp, &body, &sb, 0);\n> > +\tif (description) {\n> > +\t\tstrbuf_addch(&sb, '\\n');\n> > +\t\tstrbuf_addstr(&sb, description);\n> > +\t\tstrbuf_addch(&sb, '\\n');\n> > +\t}\n> >  \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n> >  \n> > +\tstrbuf_release(&description_sb);\n> > +\tstrbuf_release(&subject_sb);\n> >  \tstrbuf_release(&sb);\n> >  \n> >  \tshortlog_init(&log);\n> > @@ -1577,6 +1589,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n> >  \t\t{ OPTION_CALLBACK, 0, \"rfc\", &rev, NULL,\n> >  \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n> >  \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n> > +\t\tOPT_BOOL(0, \"infer-cover-subject\", &infer_cover_subject,\n> > +\t\t\t    N_(\"infer a cover letter subject from branch description\")),\n> >  \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n> >  \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n> >  \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n> > @@ -1916,7 +1930,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n> >  \t\tif (thread)\n> >  \t\t\tgen_message_id(&rev, \"cover\");\n> >  \t\tmake_cover_letter(&rev, use_stdout,\n> > -\t\t\t\t  origin, nr, list, branch_name, quiet);\n> > +\t\t\t\t  origin, nr, list, branch_name, infer_cover_subject, quiet);\n> >  \t\tprint_bases(&bases, rev.diffopt.file);\n> >  \t\tprint_signature(rev.diffopt.file);\n> >  \t\ttotal++;\n> > diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> > index 7b8c8fe136..94a3191aca 100755\n> > --- a/t/t4014-format-patch.sh\n> > +++ b/t/t4014-format-patch.sh\n> > @@ -822,7 +822,7 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n> >  '\n> >  \n> >  test_expect_success 'get git version' '\n> > -\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n> > +\tgit_version=\"$(git --version >version && sed \"s/.* //\" <version)\"\n> >  '\n> >  \n> >  signature() {\n> > @@ -1516,6 +1516,39 @@ test_expect_success 'format patch ignores color.ui' '\n> >  \ttest_cmp expect actual\n> >  '\n> >  \n> > +test_expect_success 'cover letter with config subject' '\n> > +\ttest_config branch.rebuild-1.description \"config subject\n> > +\n> > +body\" &&\n> > +\ttest_config format.inferCoverSubject true &&\n> > +\tgit checkout rebuild-1 &&\n> > +\tgit format-patch --stdout --cover-letter master >actual &&\n> > +\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n> > +\tgrep \"^body\" actual\n> > +'\n> > +\n> > +test_expect_success 'cover letter with command-line subject' '\n> > +\ttest_config branch.rebuild-1.description \"command-line subject\n> > +\n> > +body\" &&\n> > +\tgit checkout rebuild-1 &&\n> > +\tgit format-patch --stdout --cover-letter --infer-cover-subject master >actual &&\n> > +\tgrep \"^Subject: \\[PATCH 0/2\\] command-line subject$\" actual &&\n> > +\tgrep \"^body\" actual\n> > +'\n> > +\n> > +test_expect_success 'cover letter with command-line --no-infer-cover-subject overrides config' '\n> > +\ttest_config branch.rebuild-1.description \"config subject\n> > +\n> > +body\" &&\n> > +\ttest_config format.inferCoverSubject true &&\n> > +\tgit checkout rebuild-1 &&\n> > +\tgit format-patch --stdout --cover-letter --no-infer-cover-subject master >actual &&\n> > +\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n> > +\tgrep \"^config subject\" actual &&\n> > +\tgrep \"^body\" actual\n> > +'\n> > +\n> >  test_expect_success 'cover letter using branch description (1)' '\n> >  \tgit checkout rebuild-1 &&\n> >  \ttest_config branch.rebuild-1.description hello &&\n"},{"id":"381024","messageId":"20190823181956.GB14048@archbookpro.localdomain","threadId":"51687","inReplyTo":"xmqqsgptnedb.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 00/13] format-patch: learn --infer-cover-subject option (also t4014 cleanup)","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-23T18:19:56Z","receivedAt":"2019-08-23T18:20:02Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Thu, Aug 22, 2019 at 01:18:08PM -0700, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> > While we're at it, perform some major cleanup of t4014 including some\n> > stylistic cleanup and also, unmasking of Git return codes.\n> \n> Wow.  It seems that \"while we're at it\" grew quite large and (from\n> purely patch count's point of view) ends up appearing as if it were\n> the primary focus of the series ;-)\n\nFor housekeeping, since this patchset now exists as two branches\n(dl/format-patch-cover-letter-subject and\ndl/format-patch-doc-test-cleanup), would you prefer any new revisions\nexist as one big patchset or two separate patchsets targeting each\nindividual branch?\n\n> \n> Thanks for tackling the age-old mess.  Admittedly, this particular\n> script is from the older parts of Git's history and a clean-up was\n> long overdue.\n> \n> With the \"split pipes\" approach taken in patches 09 and 10, we'd end\n> up leaving more untracked and unignored cruft in the working tree. I\n> do not think they would cause problems with the existing tests after\n> reading the patches over.\n> \n> \n"},{"id":"381026","messageId":"d8a02cfd-2250-44ce-b559-dbec742b7cdf@iee.email","threadId":"51687","inReplyTo":"20190823181545.GA14048@archbookpro.localdomain","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.email","sentAt":"2019-08-23T18:46:30Z","receivedAt":"2019-08-23T18:46:34Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"\n\nOn 23/08/2019 19:15, Denton Liu wrote:\n>> Having said that, I suspect that in the longer term, people would\n>> want to see this new behaviour with a bit of tweak become the new\n>> default.\n>>\n>> The \"tweak\" I suspect is needed is to behave sensibly when \"the\n>> first line\" ends up to be too long a subject.  Whether we make this\n>> the new default or keep this optional, the issue exists either way.\n> The reason why I chose to make this an \"opt-in\" option was because there\n> currently doesn't exist a standard on how to write branch descriptions\n> like there does for commit messages (i.e. subject then body, subject\n> less than x characters). However, against best practices, some\n> developers like to have really long subjects. As a result, there's no\n> \"real\" way of telling whether the first paragraph is a long subject or a\n> short paragraph.\n>\n> As a result, we should allow the cover subject to be read from the\n> branch description only if the developer explicitly chooses this (either\n> with `--infer-cover-subject` the config option). This way, we won't have\n> to deal with the ambiguity of deciding whether or not the first\n> paragraph is truly a subject and stepping on users' toes if we end up\n> deciding wrong.\n>\n> Thoughts?\nPerhaps the `--infer-cover-subject` the config option needs to be \nmulti-valued to include:\n      \"subject\" (always expect short first lines) or\n      \"message\" (always the long paragraph description, still use \n***Subject Here***),\n      with the \"true\" being used when expecting both as previously \ndescribed.\n\n-- \nPhilip\n\nAs an aside, for format-patch to learn a --branch-version option that \ncreates a branch with the '-vN' suffix to the current branch when the \n-vN option is used would be a useful addition (as long as the formatted \nrefs are first parent to the current branch). #todo list #leftoverbits\n\n"},{"id":"381028","messageId":"xmqq1rxbmy8r.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"d8a02cfd-2250-44ce-b559-dbec742b7cdf@iee.email","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-23T20:18:44Z","receivedAt":"2019-08-23T20:18:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Philip Oakley <philipoakley@iee.email> writes:\n\n> Perhaps the `--infer-cover-subject` the config option needs to be\n> multi-valued to include:\n>      \"subject\" (always expect short first lines) or\n>      \"message\" (always the long paragraph description, still use\n> ***Subject Here***),\n>      with the \"true\" being used when expecting both as previously\n> described.\n\nThe idea to have three choices feels that this is getting better,\nbut I notice that the choice is no longer about \"subject\".\n\nI've always felt that the name of this option is way suboptimal.\nOne reason is because the option only says it is about the subject\nof the cover (letter), and the verb \"infer\" conveys almost no\ninformation---especially it does not say anything about what affects\nthe inference (hint: the branch description value gets used, in a\nsingle hardcoded ways right now, but now with the patch we have a\nchoice to control how it gets used).\n\n\n\n"},{"id":"381029","messageId":"xmqqwof3ljcz.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"20190823181956.GB14048@archbookpro.localdomain","subject":"Re: [PATCH v3 00/13] format-patch: learn --infer-cover-subject option (also t4014 cleanup)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-23T20:25:32Z","receivedAt":"2019-08-23T20:28:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> For housekeeping, since this patchset now exists as two branches\n> (dl/format-patch-cover-letter-subject and\n> dl/format-patch-doc-test-cleanup), would you prefer any new revisions\n> exist as one big patchset or two separate patchsets targeting each\n> individual branch?\n\nI think any updates to the last step would need to build on top of\nthe clean-up series.  You might be able to add new tests and update\ndocs in such a way that is independent from the clean-up and then\nworry about possible merge conflicts later, but with the clean-up\nseries being in reasonably good shape already, I'd expect that the\nbigger clean-up series can be polished enough before we work on\npolishing the last step.  So perhaps we just focus first on the\nclean-up series, have them graduate to 'master', and then build the\nnew feature on top, perhaps?\n\n"},{"id":"381047","messageId":"20190824080328.GA9726@archbookpro.localdomain","threadId":"51687","inReplyTo":"xmqq1rxbmy8r.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:03:28Z","receivedAt":"2019-08-24T08:03:33Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Fri, Aug 23, 2019 at 01:18:44PM -0700, Junio C Hamano wrote:\n> Philip Oakley <philipoakley@iee.email> writes:\n> \n> > Perhaps the `--infer-cover-subject` the config option needs to be\n> > multi-valued to include:\n> >      \"subject\" (always expect short first lines) or\n> >      \"message\" (always the long paragraph description, still use\n> > ***Subject Here***),\n> >      with the \"true\" being used when expecting both as previously\n> > described.\n\nGood idea, I like this a lot!\n\n> \n> The idea to have three choices feels that this is getting better,\n> but I notice that the choice is no longer about \"subject\".\n> \n> I've always felt that the name of this option is way suboptimal.\n> One reason is because the option only says it is about the subject\n> of the cover (letter), and the verb \"infer\" conveys almost no\n> information---especially it does not say anything about what affects\n> the inference (hint: the branch description value gets used, in a\n> single hardcoded ways right now, but now with the patch we have a\n> choice to control how it gets used).\n\nPerhaps something like\n--cover-subject-from-description={true,auto,false}?\n"},{"id":"381049","messageId":"cover.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH 00/13] format-patch: clean up tests and documentation","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:25:17Z","receivedAt":"2019-08-24T08:25:26Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"*** BLURB HERE ***\n\nAs one of the older parts of the Git, the tests and documentation for\nformat-patch have been needing cleanup for a while. Let's do that in\nthis patchset!\n\nThis patchset is based on v3 of \"format-patch: learn\n--infer-cover-subject option (also t4014 cleanup)\"[1].\n\nChanges since v3 of \"format-patch: learn --infer-cover-subject option (also\nt4014 cleanup)\":\n\n* Squash in Junio's and Hannes' suggestions\n\n* Add 't4014: let sed open its own files'\n\n[1]: https://public-inbox.org/git/xmqqwof3ljcz.fsf@gitster-ct.c.googlers.com/T/#m19570aff4828dfbd65d57cacf231c2938af1dc9f\n\n\nDenton Liu (13):\n  t4014: drop unnecessary blank lines from test cases\n  t4014: s/expected/expect/\n  t4014: move closing sq onto its own line\n  t4014: use sq for test case names\n  t4014: remove spaces after redirect operators\n  t4014: use indentable here-docs\n  t4014: drop redirections to /dev/null\n  t4014: let sed open its own files\n  t4014: use test_line_count() where possible\n  t4014: remove confusing pipe in check_threading()\n  t4014: stop losing return codes of git commands\n  Doc: add more detail for git-format-patch\n  config/format.txt: specify default value of format.coverLetter\n\n Documentation/config/format.txt    |   1 +\n Documentation/git-format-patch.txt |  23 +-\n t/t4014-format-patch.sh            | 814 ++++++++++++++---------------\n 3 files changed, 421 insertions(+), 417 deletions(-)\n\nRange-diff:\n 1:  fb000bfca2 =  1:  fb000bfca2 t4014: drop unnecessary blank lines from test cases\n 2:  568b3a03a0 !  2:  0a5ce9b95f t4014: s/expected/expect/\n    @@ Commit message\n         t4014: s/expected/expect/\n     \n         For test cases, the usual convention is to name expected output files\n    -    \"expect\", not \"expected\". Replace all instances with \"expected\" with\n    +    \"expect\", not \"expected\". Replace all instances of \"expected\" with\n         \"expect\" except for one case where the \"expected\" is used as the name\n         of a test case.\n     \n 3:  a205a920bd =  3:  5c49703aa4 t4014: move closing sq onto its own line\n 4:  66bf2e3dd4 =  4:  02a11147fd t4014: use sq for test case names\n 5:  6f1371275e =  5:  8d9791c061 t4014: remove spaces after redirect operators\n 6:  b4295846f5 =  6:  90ad0fcf70 t4014: use indentable here-docs\n 7:  34315412c8 =  7:  804b3163f8 t4014: drop redirections to /dev/null\n -:  ---------- >  8:  7d9a24a979 t4014: let sed open its own files\n 8:  de08dd886d =  9:  d068d42098 t4014: use test_line_count() where possible\n 9:  dec5a62e82 = 10:  6a9409cee0 t4014: remove confusing pipe in check_threading()\n10:  64069c0c54 ! 11:  c580ce447b t4014: stop losing return codes of git commands\n    @@ t/t4014-format-patch.sh: test_expect_success 'format-patch --ignore-if-in-upstre\n      \n     -git_version=\"$(git --version | sed \"s/.* //\")\"\n     +test_expect_success 'get git version' '\n    -+\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n    ++\tgit_version=$(git --version) &&\n    ++\tgit_version=${git_version##* }\n     +'\n      \n      signature() {\n11:  c12534ab5d = 12:  a97f861e6a Doc: add more detail for git-format-patch\n12:  a08273ebcc <  -:  ---------- config/format.txt: specify default value of format.coverLetter\n13:  de599f7ca9 <  -:  ---------- format-patch: learn --infer-cover-subject option\n -:  ---------- > 13:  7c8522abf2 config/format.txt: specify default value of format.coverLetter\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381050","messageId":"fb000bfca21bde176f1e7ea947f36f3639f822bd.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 01/13] t4014: drop unnecessary blank lines from test cases","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:26:49Z","receivedAt":"2019-08-24T08:26:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 47 -----------------------------------------\n 1 file changed, 47 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca7debf1d4..3ed3feabfe 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -9,7 +9,6 @@ test_description='various format-patch tests'\n . \"$TEST_DIRECTORY\"/lib-terminal.sh\n \n test_expect_success setup '\n-\n \tfor i in 1 2 3 4 5 6 7 8 9 10; do echo \"$i\"; done >file &&\n \tcat file >elif &&\n \tgit add file elif &&\n@@ -60,20 +59,16 @@ test_expect_success setup '\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n-\n \tgit format-patch --stdout master..side >patch0 &&\n \tcnt=$(grep \"^From \" patch0 | wc -l) &&\n \ttest $cnt = 3\n-\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n-\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n \tcnt=$(grep \"^From \" patch1 | wc -l) &&\n \ttest $cnt = 2\n-\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n@@ -85,7 +80,6 @@ test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n '\n \n test_expect_success \"format-patch doesn't consider merge commits\" '\n-\n \tgit checkout -b slave master &&\n \techo \"Another line\" >>file &&\n \ttest_tick &&\n@@ -101,7 +95,6 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n '\n \n test_expect_success \"format-patch result applies\" '\n-\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n@@ -109,7 +102,6 @@ test_expect_success \"format-patch result applies\" '\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n-\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n@@ -117,26 +109,19 @@ test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n '\n \n test_expect_success 'commit did not screw up the log message' '\n-\n \tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n-\n '\n \n test_expect_success 'format-patch did not screw up the log message' '\n-\n \tgrep \"^Subject: .*Side changes #3 with .* backslash-n\" patch0 &&\n \tgrep \"^Subject: .*Side changes #3 with .* backslash-n\" patch1\n-\n '\n \n test_expect_success 'replay did not screw up the log message' '\n-\n \tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n-\n '\n \n test_expect_success 'extra headers' '\n-\n \tgit config format.headers \"To: R E Cipient <rcipient@example.com>\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n@@ -145,22 +130,18 @@ test_expect_success 'extra headers' '\n \tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n-\n '\n \n test_expect_success 'extra headers without newlines' '\n-\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n \tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n-\n '\n \n test_expect_success 'extra headers with multiple To:s' '\n-\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side > patch4 &&\n@@ -170,7 +151,6 @@ test_expect_success 'extra headers with multiple To:s' '\n '\n \n test_expect_success 'additional command line cc (ascii)' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n@@ -178,7 +158,6 @@ test_expect_success 'additional command line cc (ascii)' '\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n@@ -186,14 +165,12 @@ test_expect_failure 'additional command line cc (rfc822)' '\n '\n \n test_expect_success 'command line headers' '\n-\n \tgit config --unset-all format.headers &&\n \tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n@@ -201,40 +178,34 @@ test_expect_success 'configuration headers and command line headers' '\n '\n \n test_expect_success 'command line To: header (ascii)' '\n-\n \tgit config --unset-all format.headers &&\n \tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n-\n \tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n-\n \tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n-\n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n-\n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n-\n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n@@ -249,7 +220,6 @@ check_patch () {\n }\n \n test_expect_success 'format.from=false' '\n-\n \tgit -c format.from=false format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -257,7 +227,6 @@ test_expect_success 'format.from=false' '\n '\n \n test_expect_success 'format.from=true' '\n-\n \tgit -c format.from=true format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -265,7 +234,6 @@ test_expect_success 'format.from=true' '\n '\n \n test_expect_success 'format.from with address' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -273,7 +241,6 @@ test_expect_success 'format.from with address' '\n '\n \n test_expect_success '--no-from overrides format.from' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -281,7 +248,6 @@ test_expect_success '--no-from overrides format.from' '\n '\n \n test_expect_success '--from overrides format.from' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -289,7 +255,6 @@ test_expect_success '--from overrides format.from' '\n '\n \n test_expect_success '--no-to overrides config.to' '\n-\n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-to --stdout master..side |\n@@ -299,7 +264,6 @@ test_expect_success '--no-to overrides config.to' '\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n-\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n@@ -311,7 +275,6 @@ test_expect_success '--no-to and --to replaces config.to' '\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n-\n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-cc --stdout master..side |\n@@ -321,7 +284,6 @@ test_expect_success '--no-cc overrides config.cc' '\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n-\n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-add-header --stdout master..side |\n@@ -331,7 +293,6 @@ test_expect_success '--no-add-header overrides config.headers' '\n '\n \n test_expect_success 'multiple files' '\n-\n \trm -rf patches/ &&\n \tgit checkout side &&\n \tgit format-patch -o patches/ master &&\n@@ -594,7 +555,6 @@ test_expect_success 'thread config + --no-thread' '\n '\n \n test_expect_success 'excessive subject' '\n-\n \trm -rf patches/ &&\n \tgit checkout side &&\n \tbefore=$(git hash-object file) &&\n@@ -622,7 +582,6 @@ test_expect_success 'cover-letter inherits diff options' '\n \t! grep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch &&\n \tgit format-patch --cover-letter -1 -M &&\n \tgrep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch\n-\n '\n \n cat > expect << EOF\n@@ -636,11 +595,9 @@ cat > expect << EOF\n EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n-\n \tgit format-patch --cover-letter -2 &&\n \tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n \ttest_cmp expect output\n-\n '\n \n cat > expect << EOF\n@@ -656,13 +613,11 @@ index $before..$after 100644\n EOF\n \n test_expect_success 'format-patch respects -U' '\n-\n \tgit format-patch -U4 -2 &&\n \tsed -e \"1,/^diff/d\" -e \"/^+5/q\" \\\n \t\t<0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \\\n \t\t>output &&\n \ttest_cmp expect output\n-\n '\n \n cat > expect << EOF\n@@ -679,11 +634,9 @@ index $before..$after 100644\n EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n-\n \tgit format-patch -p -2 &&\n \tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n \ttest_cmp expect output\n-\n '\n \n test_expect_success 'format-patch from a subdirectory (1)' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381051","messageId":"0a5ce9b95f837fb7c6b526201fa619da15fb2625.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 02/13] t4014: s/expected/expect/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:26:51Z","receivedAt":"2019-08-24T08:26:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For test cases, the usual convention is to name expected output files\n\"expect\", not \"expected\". Replace all instances of \"expected\" with\n\"expect\" except for one case where the \"expected\" is used as the name\nof a test case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 106 ++++++++++++++++++++--------------------\n 1 file changed, 53 insertions(+), 53 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 3ed3feabfe..62f5680f05 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1209,32 +1209,32 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expected &&\n+\tcat <<\\EOF | sed \"s/EOL$//\" >expect &&\n 4:Subject: [PATCH] EOL\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n@@ -1243,24 +1243,24 @@ subject\n \n body\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n@@ -1271,14 +1271,14 @@ body\n \n Signed-off-by: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: my@house\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n@@ -1292,14 +1292,14 @@ Signed-off-by: my@house\n Tested-by: Some One <someone@example.com>\n Bug: 1234\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: my@house\n 15:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n@@ -1309,13 +1309,13 @@ subject\n body\n Fooled-by-me: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n@@ -1324,14 +1324,14 @@ subject\n \n I want to mention about Signed-off-by: here.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:I want to mention about Signed-off-by: here.\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n@@ -1341,13 +1341,13 @@ subject\n My unfortunate\n Signed-off-by: example happens to be wrapped here.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:Signed-off-by: example happens to be wrapped here.\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n@@ -1359,7 +1359,7 @@ Signed-off-by: your@house\n \n A lot of houses.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: my@house\n@@ -1368,7 +1368,7 @@ EOF\n 13:\n 14:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n@@ -1379,24 +1379,24 @@ body\n \n Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n@@ -1408,14 +1408,14 @@ body\n Signed-off-by: C O Mitter <committer@example.com>\n Signed-off-by: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n 12:Signed-off-by: my@house\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n@@ -1428,13 +1428,13 @@ Tested-by: my@house\n Some Trash\n Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 13:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n@@ -1444,13 +1444,13 @@ subject\n Myfooter: x\n Some Trash\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual &&\n+\ttest_cmp expect actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n \tappend_signoff <<\\EOF >actual &&\n@@ -1459,12 +1459,12 @@ subject\n Myfooter: x\n Some Trash\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n@@ -1479,13 +1479,13 @@ Change-id: Ideadbeef\n Signed-off-by: C O Mitter <committer@example.com>\n Bug: 1234\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 14:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format patch ignores color.ui' '\n@@ -1604,13 +1604,13 @@ test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n \tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n \tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n-\techo >expected &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\tsignature >> expected &&\n-\ttest_cmp expected actual1 &&\n-\ttest_cmp expected actual2 &&\n+\techo >expect &&\n+\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n+\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\tsignature >> expect &&\n+\ttest_cmp expect actual1 &&\n+\ttest_cmp expect actual2 &&\n \techo >fail &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n@@ -1625,8 +1625,8 @@ test_expect_success 'format-patch --base errors out when base commit is in revis\n \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse HEAD~2)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '\n@@ -1652,8 +1652,8 @@ test_expect_success 'format-patch --base errors out when base commit is not ance\n \ttest_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&\n \tgit format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(cat commit-id-base)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base=auto' '\n@@ -1664,8 +1664,8 @@ test_expect_success 'format-patch --base=auto' '\n \ttest_commit N2 &&\n \tgit format-patch --stdout --base=auto -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch errors out when history involves criss-cross' '\n@@ -1701,8 +1701,8 @@ test_expect_success 'format-patch format.useAutoBaseoption' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base overrides format.useAutoBase' '\n@@ -1710,8 +1710,8 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse HEAD~1)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base with --attach' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381052","messageId":"5c49703aa4fd3741d1685d25b647d775003f9962.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 03/13] t4014: move closing sq onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:26:54Z","receivedAt":"2019-08-24T08:26:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The usual convention for test cases is for the closing sq to be on its\nown line. Move the sq onto its own line for cases that do not conform to\nthis style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 62f5680f05..5e8eb6fb27 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -790,11 +790,13 @@ test_expect_success 'options no longer allowed for format-patch' '\n \ttest_must_fail git format-patch --name-status 2> output &&\n \ttest_i18ncmp expect.name-status output &&\n \ttest_must_fail git format-patch --check 2> output &&\n-\ttest_i18ncmp expect.check output'\n+\ttest_i18ncmp expect.check output\n+'\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n \tgit format-patch --numstat --stdout master..side > output &&\n-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)'\n+\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n+'\n \n test_expect_success 'format-patch -- <path>' '\n \tgit format-patch master..side -- file 2>error &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381053","messageId":"02a11147fd016be4f0933cc30a759cb688506f4f.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 04/13] t4014: use sq for test case names","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:26:56Z","receivedAt":"2019-08-24T08:27:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The usual convention is for test case names to be written between\nsingle-quotes. Change all double-quoted test case names to single-quotes\nexcept for one test case name that uses a sq for a contraction.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 5e8eb6fb27..a7b440b003 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -58,20 +58,20 @@ test_expect_success setup '\n \tgit checkout master\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout master..side >patch0 &&\n \tcnt=$(grep \"^From \" patch0 | wc -l) &&\n \ttest $cnt = 3\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n \tcnt=$(grep \"^From \" patch1 | wc -l) &&\n \ttest $cnt = 2\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '\n \tgit tag -a v1 -m tag side &&\n \tgit tag -a v2 -m tag master &&\n \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n@@ -94,14 +94,14 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \ttest $cnt = 3\n '\n \n-test_expect_success \"format-patch result applies\" '\n+test_expect_success 'format-patch result applies' '\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n \ttest $cnt = 2\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381054","messageId":"8d9791c0611897f3bd3cbeaf5df65db8925a3e65.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 05/13] t4014: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:26:58Z","receivedAt":"2019-08-24T08:27:04Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 62 ++++++++++++++++++++---------------------\n 1 file changed, 31 insertions(+), 31 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex a7b440b003..075affb1e5 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -126,8 +126,8 @@ test_expect_success 'extra headers' '\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n \" &&\n-\tgit format-patch --stdout master..side > patch2 &&\n-\tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n+\tgit format-patch --stdout master..side >patch2 &&\n+\tsed -e \"/^\\$/q\" patch2 >hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n '\n@@ -136,7 +136,7 @@ test_expect_success 'extra headers without newlines' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n-\tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n+\tsed -e \"/^\\$/q\" patch3 >hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n '\n@@ -144,8 +144,8 @@ test_expect_success 'extra headers without newlines' '\n test_expect_success 'extra headers with multiple To:s' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n-\tgit format-patch --stdout master..side > patch4 &&\n-\tsed -e \"/^\\$/q\" patch4 > hdrs4 &&\n+\tgit format-patch --stdout master..side >patch4 &&\n+\tsed -e \"/^\\$/q\" patch4 >hdrs4 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>,\\$\" hdrs4 &&\n \tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs4\n '\n@@ -318,7 +318,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? > status.out) |\n+\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -333,12 +333,12 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' > actual &&\n+\t' >actual &&\n \ttest 0 = \"$(cat status.out)\" &&\n \ttest_cmp \"$expect\" actual\n }\n \n-cat >> expect.no-threading <<EOF\n+cat >>expect.no-threading <<EOF\n ---\n ---\n ---\n@@ -349,7 +349,7 @@ test_expect_success 'no threading' '\n \tcheck_threading expect.no-threading master\n '\n \n-cat > expect.thread <<EOF\n+cat >expect.thread <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -366,7 +366,7 @@ test_expect_success 'thread' '\n \tcheck_threading expect.thread --thread master\n '\n \n-cat > expect.in-reply-to <<EOF\n+cat >expect.in-reply-to <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -386,7 +386,7 @@ test_expect_success 'thread in-reply-to' '\n \t\t--thread master\n '\n \n-cat > expect.cover-letter <<EOF\n+cat >expect.cover-letter <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -407,7 +407,7 @@ test_expect_success 'thread cover-letter' '\n \tcheck_threading expect.cover-letter --cover-letter --thread master\n '\n \n-cat > expect.cl-irt <<EOF\n+cat >expect.cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -439,7 +439,7 @@ test_expect_success 'thread explicit shallow' '\n \t\t--in-reply-to=\"<test.message>\" --thread=shallow master\n '\n \n-cat > expect.deep <<EOF\n+cat >expect.deep <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -457,7 +457,7 @@ test_expect_success 'thread deep' '\n \tcheck_threading expect.deep --thread=deep master\n '\n \n-cat > expect.deep-irt <<EOF\n+cat >expect.deep-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -480,7 +480,7 @@ test_expect_success 'thread deep in-reply-to' '\n \t\t--in-reply-to=\"<test.message>\" master\n '\n \n-cat > expect.deep-cl <<EOF\n+cat >expect.deep-cl <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -504,7 +504,7 @@ test_expect_success 'thread deep cover-letter' '\n \tcheck_threading expect.deep-cl --cover-letter --thread=deep master\n '\n \n-cat > expect.deep-cl-irt <<EOF\n+cat >expect.deep-cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -584,7 +584,7 @@ test_expect_success 'cover-letter inherits diff options' '\n \tgrep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n   This is an excessively long subject line for a message due to the\n     habit some projects have of not having a short, one-line subject at\n     the start of the commit message, but rather sticking a whole\n@@ -596,11 +596,11 @@ EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \tgit format-patch --cover-letter -2 &&\n-\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" <0000-cover-letter.patch >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n index $before..$after 100644\n --- a/file\n +++ b/file\n@@ -620,7 +620,7 @@ test_expect_success 'format-patch respects -U' '\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n \n diff --git a/file b/file\n index $before..$after 100644\n@@ -635,7 +635,7 @@ EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n \tgit format-patch -p -2 &&\n-\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n+\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n \ttest_cmp expect output\n '\n \n@@ -689,7 +689,7 @@ test_expect_success 'format-patch from a subdirectory (3)' '\n '\n \n test_expect_success 'format-patch --in-reply-to' '\n-\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" > patch8 &&\n+\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" >patch8 &&\n \tgrep \"^In-Reply-To: <baz@foo.bar>\" patch8 &&\n \tgrep \"^References: <baz@foo.bar>\" patch8\n '\n@@ -780,21 +780,21 @@ test_expect_success 'format-patch with multiple notes refs' '\n \t! grep \"this is note 2\" out\n '\n \n-echo \"fatal: --name-only does not make sense\" > expect.name-only\n-echo \"fatal: --name-status does not make sense\" > expect.name-status\n-echo \"fatal: --check does not make sense\" > expect.check\n+echo \"fatal: --name-only does not make sense\" >expect.name-only\n+echo \"fatal: --name-status does not make sense\" >expect.name-status\n+echo \"fatal: --check does not make sense\" >expect.check\n \n test_expect_success 'options no longer allowed for format-patch' '\n-\ttest_must_fail git format-patch --name-only 2> output &&\n+\ttest_must_fail git format-patch --name-only 2>output &&\n \ttest_i18ncmp expect.name-only output &&\n-\ttest_must_fail git format-patch --name-status 2> output &&\n+\ttest_must_fail git format-patch --name-status 2>output &&\n \ttest_i18ncmp expect.name-status output &&\n-\ttest_must_fail git format-patch --check 2> output &&\n+\ttest_must_fail git format-patch --check 2>output &&\n \ttest_i18ncmp expect.check output\n '\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n-\tgit format-patch --numstat --stdout master..side > output &&\n+\tgit format-patch --numstat --stdout master..side >output &&\n \ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n '\n \n@@ -1610,14 +1610,14 @@ test_expect_success 'format-patch --base' '\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n-\tsignature >> expect &&\n+\tsignature >>expect &&\n \ttest_cmp expect actual1 &&\n \ttest_cmp expect actual2 &&\n \techo >fail &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\tsignature >> fail &&\n+\tsignature >>fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381055","messageId":"90ad0fcf703e8b932789194b0a86ce061ffd48e0.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 06/13] t4014: use indentable here-docs","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:00Z","receivedAt":"2019-08-24T08:27:06Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The convention is to use indentable here-docs within test cases so that\nthe here-docs line up with the rest of the code within the test case.\nChange here-docs from `<<\\EOF` to `<<-\\EOF` so that they can be indented\nalong with the rest of the test case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 368 ++++++++++++++++++++--------------------\n 1 file changed, 184 insertions(+), 184 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 075affb1e5..c07d868491 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1211,282 +1211,282 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expect &&\n-4:Subject: [PATCH] EOL\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat <<-\\EOF | sed \"s/EOL$//\" >expect &&\n+\t4:Subject: [PATCH] EOL\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n-Tested-by: Some One <someone@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-15:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\t(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n+\tTested-by: Some One <someone@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t15:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-Fooled-by-me: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tFooled-by-me: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-I want to mention about Signed-off-by: here.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:I want to mention about Signed-off-by: here.\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tI want to mention about Signed-off-by: here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:I want to mention about Signed-off-by: here.\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-My unfortunate\n-Signed-off-by: example happens to be wrapped here.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:Signed-off-by: example happens to be wrapped here.\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMy unfortunate\n+\tSigned-off-by: example happens to be wrapped here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:Signed-off-by: example happens to be wrapped here.\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Signed-off-by: my@house\n-Signed-off-by: your@house\n+\tSigned-off-by: my@house\n+\tSigned-off-by: your@house\n \n-A lot of houses.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: my@house\n-10:Signed-off-by: your@house\n-11:\n-13:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tA lot of houses.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: my@house\n+\t10:Signed-off-by: your@house\n+\t11:\n+\t13:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-Signed-off-by: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-12:Signed-off-by: my@house\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\t12:Signed-off-by: my@house\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Tested-by: my@house\n-Some Trash\n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-13:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tTested-by: my@house\n+\tSome Trash\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t13:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Reviewed-id: Noone\n-Tested-by: my@house\n-Change-id: Ideadbeef\n-Signed-off-by: C O Mitter <committer@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tReviewed-id: Noone\n+\tTested-by: my@house\n+\tChange-id: Ideadbeef\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381056","messageId":"804b3163f866cce0b8a928256b5009fc42dbc709.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 07/13] t4014: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:03Z","receivedAt":"2019-08-24T08:27:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex c07d868491..2048fb2008 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1502,42 +1502,42 @@ test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (2)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (3)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter ^master rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (4)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master.. >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (5)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 HEAD >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (6)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter with nothing' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381057","messageId":"7d9a24a97972ab8a8a1cfe1f2605630e154886be.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 08/13] t4014: let sed open its own files","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:06Z","receivedAt":"2019-08-24T08:27:11Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In some cases, we were using a redirection operator to feed input into\nsed. However, since sed is capable of opening its own files and provides\nbetter error messages on IO failure, make sed open its own files instead\nof redirecting input into it.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 28 ++++++++++++++--------------\n 1 file changed, 14 insertions(+), 14 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 2048fb2008..35cf798847 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -596,7 +596,7 @@ EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \tgit format-patch --cover-letter -2 &&\n-\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" <0000-cover-letter.patch >output &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" 0000-cover-letter.patch >output &&\n \ttest_cmp expect output\n '\n \n@@ -635,7 +635,7 @@ EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n \tgit format-patch -p -2 &&\n-\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n+\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n \ttest_cmp expect output\n '\n \n@@ -890,7 +890,7 @@ test_expect_success 'prepare mail-signature input' '\n test_expect_success '--signature-file=file works' '\n \tgit format-patch --stdout --signature-file=mail-signature -1 >output &&\n \tcheck_patch output &&\n-\tsed -e \"1,/^-- \\$/d\" <output >actual &&\n+\tsed -e \"1,/^-- \\$/d\" output >actual &&\n \t{\n \t\tcat mail-signature && echo\n \t} >expect &&\n@@ -901,7 +901,7 @@ test_expect_success 'format.signaturefile works' '\n \ttest_config format.signaturefile mail-signature &&\n \tgit format-patch --stdout -1 >output &&\n \tcheck_patch output &&\n-\tsed -e \"1,/^-- \\$/d\" <output >actual &&\n+\tsed -e \"1,/^-- \\$/d\" output >actual &&\n \t{\n \t\tcat mail-signature && echo\n \t} >expect &&\n@@ -923,7 +923,7 @@ test_expect_success '--signature-file overrides format.signaturefile' '\n \tgit format-patch --stdout \\\n \t\t\t--signature-file=other-mail-signature -1 >output &&\n \tcheck_patch output &&\n-\tsed -e \"1,/^-- \\$/d\" <output >actual &&\n+\tsed -e \"1,/^-- \\$/d\" output >actual &&\n \t{\n \t\tcat other-mail-signature && echo\n \t} >expect &&\n@@ -992,7 +992,7 @@ test_expect_success 'format-patch wraps extremely long subject (ascii)' '\n \tgit add file &&\n \tgit commit -m \"$M512\" &&\n \tgit format-patch --stdout -1 >patch &&\n-\tsed -n \"/^Subject/p; /^ /p; /^$/q\" <patch >subject &&\n+\tsed -n \"/^Subject/p; /^ /p; /^$/q\" patch >subject &&\n \ttest_cmp expect subject\n '\n \n@@ -1031,7 +1031,7 @@ test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '\n \tgit add file &&\n \tgit commit -m \"$M512\" &&\n \tgit format-patch --stdout -1 >patch &&\n-\tsed -n \"/^Subject/p; /^ /p; /^$/q\" <patch >subject &&\n+\tsed -n \"/^Subject/p; /^ /p; /^$/q\" patch >subject &&\n \ttest_cmp expect subject\n '\n \n@@ -1040,7 +1040,7 @@ check_author() {\n \tgit add file &&\n \tGIT_AUTHOR_NAME=$1 git commit -m author-check &&\n \tgit format-patch --stdout -1 >patch &&\n-\tsed -n \"/^From: /p; /^ /p; /^$/q\" <patch >actual &&\n+\tsed -n \"/^From: /p; /^ /p; /^$/q\" patch >actual &&\n \ttest_cmp expect actual\n }\n \n@@ -1160,7 +1160,7 @@ test_expect_success '--from=ident replaces author' '\n \tFrom: A U Thor <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1172,7 +1172,7 @@ test_expect_success '--from uses committer ident' '\n \tFrom: A U Thor <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1182,7 +1182,7 @@ test_expect_success '--from omits redundant in-body header' '\n \tFrom: A U Thor <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1197,7 +1197,7 @@ test_expect_success 'in-body headers trigger content encoding' '\n \tFrom: éxötìc <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^Content-Type/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^Content-Type/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1788,7 +1788,7 @@ test_expect_success 'interdiff: cover-letter' '\n \tgit format-patch --cover-letter --interdiff=boop~2 -1 boop &&\n \ttest_i18ngrep \"^Interdiff:$\" 0000-cover-letter.patch &&\n \ttest_i18ngrep ! \"^Interdiff:$\" 0001-fleep.patch &&\n-\tsed \"1,/^@@ /d; /^-- $/q\" <0000-cover-letter.patch >actual &&\n+\tsed \"1,/^@@ /d; /^-- $/q\" 0000-cover-letter.patch >actual &&\n \ttest_cmp expect actual\n '\n \n@@ -1804,7 +1804,7 @@ test_expect_success 'interdiff: solo-patch' '\n \tEOF\n \tgit format-patch --interdiff=boop~2 -1 boop &&\n \ttest_i18ngrep \"^Interdiff:$\" 0001-fleep.patch &&\n-\tsed \"1,/^  @@ /d; /^$/q\" <0001-fleep.patch >actual &&\n+\tsed \"1,/^  @@ /d; /^$/q\" 0001-fleep.patch >actual &&\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381058","messageId":"d068d42098f3e9079f1b3173bfae743264f60f44.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 09/13] t4014: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:08Z","receivedAt":"2019-08-24T08:27:14Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Convert all instances of `cnt=$(... | wc -l) && test $cnt = N` into uses\nof `test_line_count()`.\n\nWhile we're at it, convert one instance of a Git command upstream of a\npipe into two commands. This prevents a failure of a Git command from\nbeing masked since only the return code of the last member of the pipe\nis shown.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 35 +++++++++++++++++++----------------\n 1 file changed, 19 insertions(+), 16 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 35cf798847..18142ee5fa 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -60,23 +60,23 @@ test_expect_success setup '\n \n test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout master..side >patch0 &&\n-\tcnt=$(grep \"^From \" patch0 | wc -l) &&\n-\ttest $cnt = 3\n+\tgrep \"^From \" patch0 >from0 &&\n+\ttest_line_count = 3 from0\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '\n \tgit tag -a v1 -m tag side &&\n \tgit tag -a v2 -m tag master &&\n \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success \"format-patch doesn't consider merge commits\" '\n@@ -90,22 +90,23 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \tgit checkout -b merger master &&\n \ttest_tick &&\n \tgit merge --no-ff slave &&\n-\tcnt=$(git format-patch -3 --stdout | grep \"^From \" | wc -l) &&\n-\ttest $cnt = 3\n+\tgit format-patch -3 --stdout >patch &&\n+\tgrep \"^From \" patch >from &&\n+\ttest_line_count = 3 from\n '\n \n test_expect_success 'format-patch result applies' '\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'commit did not screw up the log message' '\n@@ -795,7 +796,8 @@ test_expect_success 'options no longer allowed for format-patch' '\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n \tgit format-patch --numstat --stdout master..side >output &&\n-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n+\tgrep \"^diff --git a/\" output >diff &&\n+\ttest_line_count = 5 diff\n '\n \n test_expect_success 'format-patch -- <path>' '\n@@ -852,8 +854,8 @@ test_expect_success 'format-patch --signature --cover-letter' '\n \tgit config --unset-all format.signature &&\n \tgit format-patch --stdout --signature=\"my sig\" --cover-letter \\\n \t\t-1 >output &&\n-\tgrep \"my sig\" output &&\n-\ttest 2 = $(grep \"my sig\" output | wc -l)\n+\tgrep \"my sig\" output >sig &&\n+\ttest_line_count = 2 sig\n '\n \n test_expect_success 'format.signature=\"\" suppresses signatures' '\n@@ -1591,7 +1593,8 @@ test_expect_success 'format-patch format.outputDirectory option' '\n \ttest_config format.outputDirectory patches &&\n \trm -fr patches &&\n \tgit format-patch master..side &&\n-\ttest $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)\n+\tgit rev-list master..side >list &&\n+\ttest_line_count = $(ls patches | wc -l) list\n '\n \n test_expect_success 'format-patch -o overrides format.outputDirectory' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381059","messageId":"6a9409cee036f3ded3b88540959dc4d05a3ced12.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 10/13] t4014: remove confusing pipe in check_threading()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:11Z","receivedAt":"2019-08-24T08:27:16Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In check_threading(), there was a Git command in the upstream of a pipe.\nIn order to not lose its status code, it was saved into a file. However,\nthis may be confusing so rewrite to redirect IO to file. This allows us\nto directly use the conventional &&-chain.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 5 ++---\n 1 file changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 18142ee5fa..67f4c62ed6 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -319,7 +319,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n+\tgit format-patch --stdout \"$@\" >patch &&\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -334,8 +334,7 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' >actual &&\n-\ttest 0 = \"$(cat status.out)\" &&\n+\t' <patch >actual &&\n \ttest_cmp \"$expect\" actual\n }\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381060","messageId":"c580ce447b6344e9dead40f269d5730070ff43a1.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 11/13] t4014: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:13Z","receivedAt":"2019-08-24T08:27:18Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of Git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no Git commands upstream.\n\nThe other way is when a command is in a non-assignment subshell. The\nreturn code will be lost in favour of the surrounding command's. Rewrite\ninstances of this such that Git commands output to a file and\nsurrounding commands only call subshells with non-Git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 197 ++++++++++++++++++++++++----------------\n 1 file changed, 120 insertions(+), 77 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 67f4c62ed6..83f52614d3 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -33,7 +33,8 @@ test_expect_success setup '\n \tgit commit -m \"Side changes #3 with \\\\n backslash-n in it.\" &&\n \n \tgit checkout master &&\n-\tgit diff-tree -p C2 | git apply --index &&\n+\tgit diff-tree -p C2 >patch &&\n+\tgit apply --index <patch &&\n \ttest_tick &&\n \tgit commit -m \"Master accepts moral equivalent of #2\" &&\n \n@@ -110,7 +111,8 @@ test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n '\n \n test_expect_success 'commit did not screw up the log message' '\n-\tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit side >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n '\n \n test_expect_success 'format-patch did not screw up the log message' '\n@@ -119,7 +121,8 @@ test_expect_success 'format-patch did not screw up the log message' '\n '\n \n test_expect_success 'replay did not screw up the log message' '\n-\tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit rebuild-1 >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n '\n \n test_expect_success 'extra headers' '\n@@ -153,63 +156,73 @@ test_expect_success 'extra headers with multiple To:s' '\n \n test_expect_success 'additional command line cc (ascii)' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_success 'command line headers' '\n \tgit config --unset-all format.headers &&\n-\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n+\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side >patch6 &&\n+\tsed -e \"/^\\$/q\" patch6 >hdrs6 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" hdrs6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch7\n+\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side >patch7 &&\n+\tsed -e \"/^\\$/q\" patch7 >hdrs7 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs7 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs7\n '\n \n test_expect_success 'command line To: header (ascii)' '\n \tgit config --unset-all format.headers &&\n-\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n-\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n-\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs9\n '\n \n # check_patch <patch>: Verify that <patch> looks like a half-sane\n@@ -221,76 +234,76 @@ check_patch () {\n }\n \n test_expect_success 'format.from=false' '\n-\tgit -c format.from=false format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n+\tgit -c format.from=false format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n \tcheck_patch patch &&\n-\t! grep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\t! grep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from=true' '\n-\tgit -c format.from=true format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\tgit -c format.from=true format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from with address' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-from overrides format.from' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--from overrides format.from' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-to overrides config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-to --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch10 &&\n-\tcheck_patch patch10 &&\n-\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" patch10\n+\tgit format-patch --no-to --stdout master..side >patch10 &&\n+\tsed -e \"/^\\$/q\" patch10 >hdrs10 &&\n+\tcheck_patch hdrs10 &&\n+\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs10\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n-\t\t--stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch11 &&\n-\tcheck_patch patch11 &&\n-\t! grep \"^To: Someone <someone@out.there>\\$\" patch11 &&\n-\tgrep \"^To: Someone Else <else@out.there>\\$\" patch11\n+\t\t--stdout master..side >patch11 &&\n+\tsed -e \"/^\\$/q\" patch11 >hdrs11 &&\n+\tcheck_patch hdrs11 &&\n+\t! grep \"^To: Someone <someone@out.there>\\$\" hdrs11 &&\n+\tgrep \"^To: Someone Else <else@out.there>\\$\" hdrs11\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-cc --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch12 &&\n-\tcheck_patch patch12 &&\n-\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" patch12\n+\tgit format-patch --no-cc --stdout master..side >patch12 &&\n+\tsed -e \"/^\\$/q\" patch12 >hdrs12 &&\n+\tcheck_patch hdrs12 &&\n+\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" hdrs12\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-add-header --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch13 &&\n-\tcheck_patch patch13 &&\n-\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" patch13\n+\tgit format-patch --no-add-header --stdout master..side >patch13 &&\n+\tsed -e \"/^\\$/q\" patch13 >hdrs13 &&\n+\tcheck_patch hdrs13 &&\n+\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" hdrs13\n '\n \n test_expect_success 'multiple files' '\n@@ -808,20 +821,25 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n \tgit format-patch --ignore-if-in-upstream HEAD\n '\n \n-git_version=\"$(git --version | sed \"s/.* //\")\"\n+test_expect_success 'get git version' '\n+\tgit_version=$(git --version) &&\n+\tgit_version=${git_version##* }\n+'\n \n signature() {\n \tprintf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n }\n \n test_expect_success 'format-patch default signature' '\n-\tgit format-patch --stdout -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature >expect &&\n \ttest_cmp expect output\n '\n \n test_expect_success 'format-patch --signature' '\n-\tgit format-patch --stdout --signature=\"my sig\" -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout --signature=\"my sig\" -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature \"my sig\" >expect &&\n \ttest_cmp expect output\n '\n@@ -1606,19 +1624,40 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' '\n \n test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n-\tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n-\tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 -1 >patch &&\n+\ttail -n 7 patch >actual1 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&\n+\ttail -n 7 patch >actual2 &&\n+\n \techo >expect &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\tgit rev-parse HEAD~3 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>expect &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n \tsignature >>expect &&\n \ttest_cmp expect actual1 &&\n \ttest_cmp expect actual2 &&\n+\n \techo >fail &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>fail &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n \tsignature >>fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n@@ -1629,7 +1668,8 @@ test_expect_success 'format-patch --base errors out when base commit is in revis\n \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expect &&\n+\tgit rev-parse HEAD~2 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1668,7 +1708,8 @@ test_expect_success 'format-patch --base=auto' '\n \ttest_commit N2 &&\n \tgit format-patch --stdout --base=auto -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1705,7 +1746,8 @@ test_expect_success 'format-patch format.useAutoBaseoption' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1714,7 +1756,8 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expect &&\n+\tgit rev-parse HEAD~1 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381061","messageId":"a97f861e6a9889545a61a750791257757fc5b8df.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 12/13] Doc: add more detail for git-format-patch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:15Z","receivedAt":"2019-08-24T08:27:21Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In git-format-patch.txt, we were missing some key user information.\nFirst of all, document the special value of `--base=auto`.\n\nNext, while we're at it, surround option arguments with <>.\n\nFinally, document the `format.outputDirectory` config and change\n`format.coverletter` to use camel case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-format-patch.txt | 17 ++++++++++-------\n 1 file changed, 10 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex b9b97e63ae..95bc4d53ca 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n+\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,7 +159,7 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=Message-Id::\n+--in-reply-to=<Message-Id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n \treply to the given Message-Id, which avoids breaking threads to\n \tprovide a new patch series.\n@@ -314,7 +314,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n --base=<commit>::\n \tRecord the base tree information to identify the state the\n \tpatch series applies to.  See the BASE TREE INFORMATION section\n-\tbelow for details.\n+\tbelow for details. If <commit> is \"auto\", a base commit is\n+\tautomatically chosen.\n \n --root::\n \tTreat the revision argument as a <revision range>, even if it\n@@ -330,8 +331,9 @@ CONFIGURATION\n -------------\n You can specify extra mail header lines to be added to each message,\n defaults for the subject prefix and file suffix, number patches when\n-outputting more than one patch, add \"To\" or \"Cc:\" headers, configure\n-attachments, and sign off patches with configuration variables.\n+outputting more than one patch, add \"To:\" or \"Cc:\" headers, configure\n+attachments, change the patch output directory, and sign off patches\n+with configuration variables.\n \n ------------\n [format]\n@@ -343,7 +345,8 @@ attachments, and sign off patches with configuration variables.\n \tcc = <email>\n \tattach [ = mime-boundary-string ]\n \tsignOff = true\n-\tcoverletter = auto\n+\toutputDirectory = <directory>\n+\tcoverLetter = auto\n ------------\n \n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381062","messageId":"7c8522abf2aca59615e68993345c61e255f3a0c2.1566635008.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH 13/13] config/format.txt: specify default value of format.coverLetter","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:27:18Z","receivedAt":"2019-08-24T08:27:22Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt    |  1 +\n Documentation/git-format-patch.txt | 12 ++++++------\n 2 files changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex 414a5a8a9d..cb629fa769 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -77,6 +77,7 @@ format.coverLetter::\n \tA boolean that controls whether to generate a cover-letter when\n \tformat-patch is invoked, but in addition can be set to \"auto\", to\n \tgenerate a cover-letter only when there's more than one patch.\n+\tDefault is false.\n \n format.outputDirectory::\n \tSet a custom directory to store the resulting files instead of the\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 95bc4d53ca..0ac56f4b70 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n+\t\t   [--rfc] [--subject-prefix=<subject prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,9 +159,9 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=<Message-Id>::\n+--in-reply-to=<message id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n-\treply to the given Message-Id, which avoids breaking threads to\n+\treply to the given <message id>, which avoids breaking threads to\n \tprovide a new patch series.\n \n --ignore-if-in-upstream::\n@@ -171,9 +171,9 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n---subject-prefix=<Subject-Prefix>::\n+--subject-prefix=<subject prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n-\tline, instead use '[<Subject-Prefix>]'. This\n+\tline, instead use '[<subject prefix>]'. This\n \tallows for useful naming of a patch series, and can be\n \tcombined with the `--numbered` option.\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381063","messageId":"20190824082815.GA13369@archbookpro.localdomain","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"Re: [PATCH 00/13] format-patch: clean up tests and documentation","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-24T08:28:15Z","receivedAt":"2019-08-24T08:28:20Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Sat, Aug 24, 2019 at 04:25:17AM -0400, Denton Liu wrote:\n> *** BLURB HERE ***\n\nWhoops, perhaps we also need a configuration option for turning this off\nas well ;)\n\n> \n> As one of the older parts of the Git, the tests and documentation for\n> format-patch have been needing cleanup for a while. Let's do that in\n> this patchset!\n> \n> This patchset is based on v3 of \"format-patch: learn\n> --infer-cover-subject option (also t4014 cleanup)\"[1].\n> \n> Changes since v3 of \"format-patch: learn --infer-cover-subject option (also\n> t4014 cleanup)\":\n> \n> * Squash in Junio's and Hannes' suggestions\n> \n> * Add 't4014: let sed open its own files'\n> \n> [1]: https://public-inbox.org/git/xmqqwof3ljcz.fsf@gitster-ct.c.googlers.com/T/#m19570aff4828dfbd65d57cacf231c2938af1dc9f\n> \n> \n> Denton Liu (13):\n>   t4014: drop unnecessary blank lines from test cases\n>   t4014: s/expected/expect/\n>   t4014: move closing sq onto its own line\n>   t4014: use sq for test case names\n>   t4014: remove spaces after redirect operators\n>   t4014: use indentable here-docs\n>   t4014: drop redirections to /dev/null\n>   t4014: let sed open its own files\n>   t4014: use test_line_count() where possible\n>   t4014: remove confusing pipe in check_threading()\n>   t4014: stop losing return codes of git commands\n>   Doc: add more detail for git-format-patch\n>   config/format.txt: specify default value of format.coverLetter\n> \n>  Documentation/config/format.txt    |   1 +\n>  Documentation/git-format-patch.txt |  23 +-\n>  t/t4014-format-patch.sh            | 814 ++++++++++++++---------------\n>  3 files changed, 421 insertions(+), 417 deletions(-)\n> \n> Range-diff:\n>  1:  fb000bfca2 =  1:  fb000bfca2 t4014: drop unnecessary blank lines from test cases\n>  2:  568b3a03a0 !  2:  0a5ce9b95f t4014: s/expected/expect/\n>     @@ Commit message\n>          t4014: s/expected/expect/\n>      \n>          For test cases, the usual convention is to name expected output files\n>     -    \"expect\", not \"expected\". Replace all instances with \"expected\" with\n>     +    \"expect\", not \"expected\". Replace all instances of \"expected\" with\n>          \"expect\" except for one case where the \"expected\" is used as the name\n>          of a test case.\n>      \n>  3:  a205a920bd =  3:  5c49703aa4 t4014: move closing sq onto its own line\n>  4:  66bf2e3dd4 =  4:  02a11147fd t4014: use sq for test case names\n>  5:  6f1371275e =  5:  8d9791c061 t4014: remove spaces after redirect operators\n>  6:  b4295846f5 =  6:  90ad0fcf70 t4014: use indentable here-docs\n>  7:  34315412c8 =  7:  804b3163f8 t4014: drop redirections to /dev/null\n>  -:  ---------- >  8:  7d9a24a979 t4014: let sed open its own files\n>  8:  de08dd886d =  9:  d068d42098 t4014: use test_line_count() where possible\n>  9:  dec5a62e82 = 10:  6a9409cee0 t4014: remove confusing pipe in check_threading()\n> 10:  64069c0c54 ! 11:  c580ce447b t4014: stop losing return codes of git commands\n>     @@ t/t4014-format-patch.sh: test_expect_success 'format-patch --ignore-if-in-upstre\n>       \n>      -git_version=\"$(git --version | sed \"s/.* //\")\"\n>      +test_expect_success 'get git version' '\n>     -+\tgit_version=\"$(git --version | sed \"s/.* //\")\"\n>     ++\tgit_version=$(git --version) &&\n>     ++\tgit_version=${git_version##* }\n>      +'\n>       \n>       signature() {\n> 11:  c12534ab5d = 12:  a97f861e6a Doc: add more detail for git-format-patch\n> 12:  a08273ebcc <  -:  ---------- config/format.txt: specify default value of format.coverLetter\n> 13:  de599f7ca9 <  -:  ---------- format-patch: learn --infer-cover-subject option\n>  -:  ---------- > 13:  7c8522abf2 config/format.txt: specify default value of format.coverLetter\n> -- \n> 2.23.0.248.g3a9dd8fb08\n> \n"},{"id":"381069","messageId":"1eccefe4-8002-4664-3bc2-8332fb7bd697@iee.email","threadId":"51687","inReplyTo":"20190824080328.GA9726@archbookpro.localdomain","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.email","sentAt":"2019-08-24T13:59:01Z","receivedAt":"2019-08-24T13:59:06Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"On 24/08/2019 09:03, Denton Liu wrote:\n> On Fri, Aug 23, 2019 at 01:18:44PM -0700, Junio C Hamano wrote:\n>> Philip Oakley <philipoakley@iee.email> writes:\n>>\n>>> Perhaps the `--infer-cover-subject` the config option needs to be\n>>> multi-valued to include:\n>>>       \"subject\" (always expect short first lines) or\n>>>       \"message\" (always the long paragraph description, still use\n>>> ***Subject Here***),\n>>>       with the \"true\" being used when expecting both as previously\n>>> described.\n> Good idea, I like this a lot!\n>\n>> The idea to have three choices feels that this is getting better,\n>> but I notice that the choice is no longer about \"subject\".\n>>\n>> I've always felt that the name of this option is way suboptimal.\n>> One reason is because the option only says it is about the subject\n>> of the cover (letter), and the verb \"infer\" conveys almost no\n>> information---especially it does not say anything about what affects\n>> the inference (hint: the branch description value gets used, in a\n>> single hardcoded ways right now, but now with the patch we have a\n>> choice to control how it gets used).\n> Perhaps something like\n> --cover-subject-from-description={true,auto,false}?\n\nmaybe --cover-letter-from-description={true,auto,subject,message,false}? \nto cover most eventualities (i.e. letter rather than subject).\n\nI haven't looked at what happens on Windows (CRLF usage?) for multi-line \ndescriptions. The common assumption is LF in repo, with attributes etc, \nbut the branch description is a bit free format in terms of guidance ;-)\n\nPhilip\n\n"},{"id":"381135","messageId":"CAPig+cTBzxbEOo2tBOeTiYM8njDuAVTdBzATtPUmA6uMni4L-Q@mail.gmail.com","threadId":"51687","inReplyTo":"7d9a24a97972ab8a8a1cfe1f2605630e154886be.1566635008.git.liu.denton@gmail.com","subject":"Re: [PATCH 08/13] t4014: let sed open its own files","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-08-26T00:42:22Z","receivedAt":"2019-08-26T00:42:39Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Aug 24, 2019 at 4:27 AM Denton Liu <liu.denton@gmail.com> wrote:\n> In some cases, we were using a redirection operator to feed input into\n> sed. However, since sed is capable of opening its own files and provides\n> better error messages on IO failure, make sed open its own files instead\n> of redirecting input into it.\n\nI don't care strongly one way or the other, but the justification of\n\"better error message\" is rather weak:\n\n    % sed '/^$/d' <foo\n    sh: foo: No such file or directory\n    % sed '/^$/d' foo\n    sed: foo: No such file or directory\n    %\n\nI doubt it's worth a re-roll, though.\n\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n"},{"id":"381176","messageId":"xmqqef18knoj.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"20190824080328.GA9726@archbookpro.localdomain","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-26T14:26:36Z","receivedAt":"2019-08-26T14:26:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Perhaps something like\n> --cover-subject-from-description={true,auto,false}?\n\nIs it still only about \"subject\"?  I thought one of the improved\nbehaviour was to populate the subject header with the title\n(i.e. the first, often single-line, paragraph) and use the remainder\nin the body?  --use-description-in-cover={both,auto,body} meaning\n\"both subject and body gets filled\" (among the three this name is I\nam least happy with), \"automatically decide---if the first paragraph\nis overly big, it is unwise to use it on the subject\", \"use it only\nin body\" (implying \"use the *** SUBJECT HERE *** placeholder on the\nsubject header), perhaps?\n"},{"id":"381179","messageId":"xmqqa7bwkni4.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"1eccefe4-8002-4664-3bc2-8332fb7bd697@iee.email","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-26T14:30:27Z","receivedAt":"2019-08-26T14:30:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Philip Oakley <philipoakley@iee.email> writes:\n\n> I haven't looked at what happens on Windows (CRLF usage?) for\n> multi-line descriptions. The common assumption is LF in repo, with\n> attributes etc, but the branch description is a bit free format in\n> terms of guidance ;-)\n\nThe same approach taken by the format-patch to use a commit-log\nmessage to form the subject and the body should be applicable; as\nlong as the resulting cover letters are made the same way as the\nnormal patch e-mails, it is OK.  If both are broken wrt CRLF usage\nor whatever, as long as they are broken in the same way, we can\ncorrect both at the same time ;-)\n\n"},{"id":"381189","messageId":"xmqq1rx8kl76.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"a97f861e6a9889545a61a750791257757fc5b8df.1566635008.git.liu.denton@gmail.com","subject":"Re: [PATCH 12/13] Doc: add more detail for git-format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-26T15:20:13Z","receivedAt":"2019-08-26T15:20:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> In git-format-patch.txt, we were missing some key user information.\n> First of all, document the special value of `--base=auto`.\n>\n> Next, while we're at it, surround option arguments with <>.\n\nI'd suggest squashing this in to complete the above.\n\ncf. <xmqq1rxfveym.fsf@gitster-ct.c.googlers.com>\ncf. <xmqqimqqs7cm.fsf@gitster-ct.c.googlers.com>\n---\n Documentation/git-format-patch.txt | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 95bc4d53ca..0ac56f4b70 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n+\t\t   [--rfc] [--subject-prefix=<subject prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,9 +159,9 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=<Message-Id>::\n+--in-reply-to=<message id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n-\treply to the given Message-Id, which avoids breaking threads to\n+\treply to the given <message id>, which avoids breaking threads to\n \tprovide a new patch series.\n \n --ignore-if-in-upstream::\n@@ -171,9 +171,9 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n---subject-prefix=<Subject-Prefix>::\n+--subject-prefix=<subject prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n-\tline, instead use '[<Subject-Prefix>]'. This\n+\tline, instead use '[<subject prefix>]'. This\n \tallows for useful naming of a patch series, and can be\n \tcombined with the `--numbered` option.\n \n-- \n2.23.0-266-g1e4abb0e04\n"},{"id":"381190","messageId":"xmqqwof0j6k6.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"20190824082815.GA13369@archbookpro.localdomain","subject":"Re: [PATCH 00/13] format-patch: clean up tests and documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-26T15:21:45Z","receivedAt":"2019-08-26T15:21:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> On Sat, Aug 24, 2019 at 04:25:17AM -0400, Denton Liu wrote:\n>> *** BLURB HERE ***\n>\n> Whoops, perhaps we also need a configuration option for turning this off\n> as well ;)\n\nYes.\n\nI think it is OK to just remove it when we are taking anything from\nthe branch.*.description (and any other stuff that leaves human\nreadable text in the future) to add to the body.\n\n"},{"id":"381199","messageId":"xmqqblwbkj3a.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"xmqqef18knoj.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 13/13] format-patch: learn --infer-cover-subject option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-26T16:05:45Z","receivedAt":"2019-08-26T16:05:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Denton Liu <liu.denton@gmail.com> writes:\n>\n>> Perhaps something like\n>> --cover-subject-from-description={true,auto,false}?\n>\n> Is it still only about \"subject\"?  I thought one of the improved\n> behaviour was to populate the subject header with the title\n> (i.e. the first, often single-line, paragraph) and use the remainder\n> in the body?  --use-description-in-cover={both,auto,body} meaning\n> \"both subject and body gets filled\" (among the three this name is I\n> am least happy with), \"automatically decide---if the first paragraph\n> is overly big, it is unwise to use it on the subject\", \"use it only\n> in body\" (implying \"use the *** SUBJECT HERE *** placeholder on the\n> subject header), perhaps?\n\nAh, I see Philip has suggested \"--cover-letter-from-description\",\nwhich also sounds better by not focusing too much on the 'subject',\nand I have no strong preference between the two.\n"},{"id":"381200","messageId":"xmqq7e6zkj0y.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"xmqq1rx8kl76.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 12/13] Doc: add more detail for git-format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-26T16:07:09Z","receivedAt":"2019-08-26T16:07:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Denton Liu <liu.denton@gmail.com> writes:\n>\n>> In git-format-patch.txt, we were missing some key user information.\n>> First of all, document the special value of `--base=auto`.\n>>\n>> Next, while we're at it, surround option arguments with <>.\n>\n> I'd suggest squashing this in to complete the above.\n>\n> cf. <xmqq1rxfveym.fsf@gitster-ct.c.googlers.com>\n> cf. <xmqqimqqs7cm.fsf@gitster-ct.c.googlers.com>\n> ---\n>  Documentation/git-format-patch.txt | 12 ++++++------\n>  1 file changed, 6 insertions(+), 6 deletions(-)\n\nAh, I see that you have squashed this into the next step.  I do not\nthink it belongs there, though.\n"},{"id":"381288","messageId":"cover.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566635008.git.liu.denton@gmail.com","subject":"[PATCH v2 00/13] format-patch: clean up tests and documentation","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:04:47Z","receivedAt":"2019-08-27T04:04:53Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In this reroll, I squashed Junio's suggestion into the correct patch.\nAlso, I took Eric's suggestion and removed the weak justification (i.e.\nbetter error messages) from the sed patch since it doesn't really\ncontribute.\n\n\nAs one of the older parts of the Git, the tests and documentation for\nformat-patch have been needing cleanup for a while. Let's do that in\nthis patchset!\n\nThis patchset is based on v3 of \"format-patch: learn\n--infer-cover-subject option (also t4014 cleanup)\"[1].\n\nChanges since v1:\n\n* Squash Junio's patch into the correct patch ;)\n\n* Remove weak justification (better error messages) in 8/13\n\nChanges since v3 of \"format-patch: learn --infer-cover-subject option (also\nt4014 cleanup)\":\n\n* Squash in Junio's and Hannes' suggestions\n\n* Add 't4014: let sed open its own files'\n\n[1]: https://public-inbox.org/git/xmqqwof3ljcz.fsf@gitster-ct.c.googlers.com/T/#m19570aff4828dfbd65d57cacf231c2938af1dc9f\n\n\nDenton Liu (13):\n  t4014: drop unnecessary blank lines from test cases\n  t4014: s/expected/expect/\n  t4014: move closing sq onto its own line\n  t4014: use sq for test case names\n  t4014: remove spaces after redirect operators\n  t4014: use indentable here-docs\n  t4014: drop redirections to /dev/null\n  t4014: let sed open its own files\n  t4014: use test_line_count() where possible\n  t4014: remove confusing pipe in check_threading()\n  t4014: stop losing return codes of git commands\n  Doc: add more detail for git-format-patch\n  config/format.txt: specify default value of format.coverLetter\n\n Documentation/config/format.txt    |   1 +\n Documentation/git-format-patch.txt |  23 +-\n t/t4014-format-patch.sh            | 814 ++++++++++++++---------------\n 3 files changed, 421 insertions(+), 417 deletions(-)\n\nRange-diff against v1:\n 1:  fb000bfca2 =  1:  fb000bfca2 t4014: drop unnecessary blank lines from test cases\n 2:  0a5ce9b95f =  2:  0a5ce9b95f t4014: s/expected/expect/\n 3:  5c49703aa4 =  3:  5c49703aa4 t4014: move closing sq onto its own line\n 4:  02a11147fd =  4:  02a11147fd t4014: use sq for test case names\n 5:  8d9791c061 =  5:  8d9791c061 t4014: remove spaces after redirect operators\n 6:  90ad0fcf70 =  6:  90ad0fcf70 t4014: use indentable here-docs\n 7:  804b3163f8 =  7:  804b3163f8 t4014: drop redirections to /dev/null\n 8:  7d9a24a979 !  8:  967e624bb4 t4014: let sed open its own files\n    @@ Commit message\n         t4014: let sed open its own files\n     \n         In some cases, we were using a redirection operator to feed input into\n    -    sed. However, since sed is capable of opening its own files and provides\n    -    better error messages on IO failure, make sed open its own files instead\n    -    of redirecting input into it.\n    +    sed. However, since sed is capable of opening its own files, make sed\n    +    open its own files instead of redirecting input into it.\n     \n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n     \n 9:  d068d42098 =  9:  9a42ec2b7e t4014: use test_line_count() where possible\n10:  6a9409cee0 = 10:  8acc90f74d t4014: remove confusing pipe in check_threading()\n11:  c580ce447b = 11:  bc7355485f t4014: stop losing return codes of git commands\n12:  a97f861e6a ! 12:  fd343b99c5 Doc: add more detail for git-format-patch\n    @@ Commit message\n         In git-format-patch.txt, we were missing some key user information.\n         First of all, document the special value of `--base=auto`.\n     \n    -    Next, while we're at it, surround option arguments with <>.\n    +    Next, while we're at it, surround option arguments with <> and change\n    +    existing names such as \"Message-Id\" to \"message id\", which conforms with\n    +    how existing documentation is written.\n     \n         Finally, document the `format.outputDirectory` config and change\n         `format.coverletter` to use camel case.\n    @@ Documentation/git-format-patch.txt: SYNOPSIS\n      \t\t   [-n | --numbered | -N | --no-numbered]\n      \t\t   [--start-number <n>] [--numbered-files]\n     -\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n    -+\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n    ++\t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n      \t\t   [--ignore-if-in-upstream]\n     -\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n    -+\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n    ++\t\t   [--rfc] [--subject-prefix=<subject prefix>]\n      \t\t   [(--reroll-count|-v) <n>]\n      \t\t   [--to=<email>] [--cc=<email>]\n      \t\t   [--[no-]cover-letter] [--quiet]\n    @@ Documentation/git-format-patch.txt: Beware that the default for 'git send-email'\n      will want to ensure that threading is disabled for `git send-email`.\n      \n     ---in-reply-to=Message-Id::\n    -+--in-reply-to=<Message-Id>::\n    ++--in-reply-to=<message id>::\n      \tMake the first mail (or all the mails with `--no-thread`) appear as a\n    - \treply to the given Message-Id, which avoids breaking threads to\n    +-\treply to the given Message-Id, which avoids breaking threads to\n    ++\treply to the given <message id>, which avoids breaking threads to\n      \tprovide a new patch series.\n    + \n    + --ignore-if-in-upstream::\n    +@@ Documentation/git-format-patch.txt: will want to ensure that threading is disabled for `git send-email`.\n    + \tpatches being generated, and any patch that matches is\n    + \tignored.\n    + \n    +---subject-prefix=<Subject-Prefix>::\n    ++--subject-prefix=<subject prefix>::\n    + \tInstead of the standard '[PATCH]' prefix in the subject\n    +-\tline, instead use '[<Subject-Prefix>]'. This\n    ++\tline, instead use '[<subject prefix>]'. This\n    + \tallows for useful naming of a patch series, and can be\n    + \tcombined with the `--numbered` option.\n    + \n     @@ Documentation/git-format-patch.txt: you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n      --base=<commit>::\n      \tRecord the base tree information to identify the state the\n13:  7c8522abf2 <  -:  ---------- config/format.txt: specify default value of format.coverLetter\n -:  ---------- > 13:  4e429e1989 config/format.txt: specify default value of format.coverLetter\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381289","messageId":"fb000bfca21bde176f1e7ea947f36f3639f822bd.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 01/13] t4014: drop unnecessary blank lines from test cases","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:04:50Z","receivedAt":"2019-08-27T04:04:55Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 47 -----------------------------------------\n 1 file changed, 47 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex ca7debf1d4..3ed3feabfe 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -9,7 +9,6 @@ test_description='various format-patch tests'\n . \"$TEST_DIRECTORY\"/lib-terminal.sh\n \n test_expect_success setup '\n-\n \tfor i in 1 2 3 4 5 6 7 8 9 10; do echo \"$i\"; done >file &&\n \tcat file >elif &&\n \tgit add file elif &&\n@@ -60,20 +59,16 @@ test_expect_success setup '\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n-\n \tgit format-patch --stdout master..side >patch0 &&\n \tcnt=$(grep \"^From \" patch0 | wc -l) &&\n \ttest $cnt = 3\n-\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream\" '\n-\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n \tcnt=$(grep \"^From \" patch1 | wc -l) &&\n \ttest $cnt = 2\n-\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n@@ -85,7 +80,6 @@ test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n '\n \n test_expect_success \"format-patch doesn't consider merge commits\" '\n-\n \tgit checkout -b slave master &&\n \techo \"Another line\" >>file &&\n \ttest_tick &&\n@@ -101,7 +95,6 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n '\n \n test_expect_success \"format-patch result applies\" '\n-\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n@@ -109,7 +102,6 @@ test_expect_success \"format-patch result applies\" '\n '\n \n test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n-\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n@@ -117,26 +109,19 @@ test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n '\n \n test_expect_success 'commit did not screw up the log message' '\n-\n \tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n-\n '\n \n test_expect_success 'format-patch did not screw up the log message' '\n-\n \tgrep \"^Subject: .*Side changes #3 with .* backslash-n\" patch0 &&\n \tgrep \"^Subject: .*Side changes #3 with .* backslash-n\" patch1\n-\n '\n \n test_expect_success 'replay did not screw up the log message' '\n-\n \tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n-\n '\n \n test_expect_success 'extra headers' '\n-\n \tgit config format.headers \"To: R E Cipient <rcipient@example.com>\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n@@ -145,22 +130,18 @@ test_expect_success 'extra headers' '\n \tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n-\n '\n \n test_expect_success 'extra headers without newlines' '\n-\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n \tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n-\n '\n \n test_expect_success 'extra headers with multiple To:s' '\n-\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side > patch4 &&\n@@ -170,7 +151,6 @@ test_expect_success 'extra headers with multiple To:s' '\n '\n \n test_expect_success 'additional command line cc (ascii)' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n@@ -178,7 +158,6 @@ test_expect_success 'additional command line cc (ascii)' '\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n@@ -186,14 +165,12 @@ test_expect_failure 'additional command line cc (rfc822)' '\n '\n \n test_expect_success 'command line headers' '\n-\n \tgit config --unset-all format.headers &&\n \tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n-\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n \tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n@@ -201,40 +178,34 @@ test_expect_success 'configuration headers and command line headers' '\n '\n \n test_expect_success 'command line To: header (ascii)' '\n-\n \tgit config --unset-all format.headers &&\n \tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n-\n \tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n-\n \tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n \tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n-\n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n-\n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n-\n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n \tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n \tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n@@ -249,7 +220,6 @@ check_patch () {\n }\n \n test_expect_success 'format.from=false' '\n-\n \tgit -c format.from=false format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -257,7 +227,6 @@ test_expect_success 'format.from=false' '\n '\n \n test_expect_success 'format.from=true' '\n-\n \tgit -c format.from=true format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -265,7 +234,6 @@ test_expect_success 'format.from=true' '\n '\n \n test_expect_success 'format.from with address' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -273,7 +241,6 @@ test_expect_success 'format.from with address' '\n '\n \n test_expect_success '--no-from overrides format.from' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -281,7 +248,6 @@ test_expect_success '--no-from overrides format.from' '\n '\n \n test_expect_success '--from overrides format.from' '\n-\n \tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n \tsed -e \"/^\\$/q\" >patch &&\n \tcheck_patch patch &&\n@@ -289,7 +255,6 @@ test_expect_success '--from overrides format.from' '\n '\n \n test_expect_success '--no-to overrides config.to' '\n-\n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-to --stdout master..side |\n@@ -299,7 +264,6 @@ test_expect_success '--no-to overrides config.to' '\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n-\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n@@ -311,7 +275,6 @@ test_expect_success '--no-to and --to replaces config.to' '\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n-\n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-cc --stdout master..side |\n@@ -321,7 +284,6 @@ test_expect_success '--no-cc overrides config.cc' '\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n-\n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n \tgit format-patch --no-add-header --stdout master..side |\n@@ -331,7 +293,6 @@ test_expect_success '--no-add-header overrides config.headers' '\n '\n \n test_expect_success 'multiple files' '\n-\n \trm -rf patches/ &&\n \tgit checkout side &&\n \tgit format-patch -o patches/ master &&\n@@ -594,7 +555,6 @@ test_expect_success 'thread config + --no-thread' '\n '\n \n test_expect_success 'excessive subject' '\n-\n \trm -rf patches/ &&\n \tgit checkout side &&\n \tbefore=$(git hash-object file) &&\n@@ -622,7 +582,6 @@ test_expect_success 'cover-letter inherits diff options' '\n \t! grep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch &&\n \tgit format-patch --cover-letter -1 -M &&\n \tgrep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch\n-\n '\n \n cat > expect << EOF\n@@ -636,11 +595,9 @@ cat > expect << EOF\n EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n-\n \tgit format-patch --cover-letter -2 &&\n \tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n \ttest_cmp expect output\n-\n '\n \n cat > expect << EOF\n@@ -656,13 +613,11 @@ index $before..$after 100644\n EOF\n \n test_expect_success 'format-patch respects -U' '\n-\n \tgit format-patch -U4 -2 &&\n \tsed -e \"1,/^diff/d\" -e \"/^+5/q\" \\\n \t\t<0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \\\n \t\t>output &&\n \ttest_cmp expect output\n-\n '\n \n cat > expect << EOF\n@@ -679,11 +634,9 @@ index $before..$after 100644\n EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n-\n \tgit format-patch -p -2 &&\n \tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n \ttest_cmp expect output\n-\n '\n \n test_expect_success 'format-patch from a subdirectory (1)' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381290","messageId":"0a5ce9b95f837fb7c6b526201fa619da15fb2625.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 02/13] t4014: s/expected/expect/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:04:52Z","receivedAt":"2019-08-27T04:04:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For test cases, the usual convention is to name expected output files\n\"expect\", not \"expected\". Replace all instances of \"expected\" with\n\"expect\" except for one case where the \"expected\" is used as the name\nof a test case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 106 ++++++++++++++++++++--------------------\n 1 file changed, 53 insertions(+), 53 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 3ed3feabfe..62f5680f05 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1209,32 +1209,32 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expected &&\n+\tcat <<\\EOF | sed \"s/EOL$//\" >expect &&\n 4:Subject: [PATCH] EOL\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n@@ -1243,24 +1243,24 @@ subject\n \n body\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n@@ -1271,14 +1271,14 @@ body\n \n Signed-off-by: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: my@house\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n@@ -1292,14 +1292,14 @@ Signed-off-by: my@house\n Tested-by: Some One <someone@example.com>\n Bug: 1234\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: my@house\n 15:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n@@ -1309,13 +1309,13 @@ subject\n body\n Fooled-by-me: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n@@ -1324,14 +1324,14 @@ subject\n \n I want to mention about Signed-off-by: here.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:I want to mention about Signed-off-by: here.\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n@@ -1341,13 +1341,13 @@ subject\n My unfortunate\n Signed-off-by: example happens to be wrapped here.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:Signed-off-by: example happens to be wrapped here.\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n@@ -1359,7 +1359,7 @@ Signed-off-by: your@house\n \n A lot of houses.\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: my@house\n@@ -1368,7 +1368,7 @@ EOF\n 13:\n 14:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n@@ -1379,24 +1379,24 @@ body\n \n Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 9:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n@@ -1408,14 +1408,14 @@ body\n Signed-off-by: C O Mitter <committer@example.com>\n Signed-off-by: my@house\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n 12:Signed-off-by: my@house\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n@@ -1428,13 +1428,13 @@ Tested-by: my@house\n Some Trash\n Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 13:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n@@ -1444,13 +1444,13 @@ subject\n Myfooter: x\n Some Trash\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:\n 12:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual &&\n+\ttest_cmp expect actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n \tappend_signoff <<\\EOF >actual &&\n@@ -1459,12 +1459,12 @@ subject\n Myfooter: x\n Some Trash\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 11:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n@@ -1479,13 +1479,13 @@ Change-id: Ideadbeef\n Signed-off-by: C O Mitter <committer@example.com>\n Bug: 1234\n EOF\n-\tcat >expected <<\\EOF &&\n+\tcat >expect <<\\EOF &&\n 4:Subject: [PATCH] subject\n 8:\n 10:\n 14:Signed-off-by: C O Mitter <committer@example.com>\n EOF\n-\ttest_cmp expected actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format patch ignores color.ui' '\n@@ -1604,13 +1604,13 @@ test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n \tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n \tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n-\techo >expected &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expected &&\n-\tsignature >> expected &&\n-\ttest_cmp expected actual1 &&\n-\ttest_cmp expected actual2 &&\n+\techo >expect &&\n+\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n+\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\tsignature >> expect &&\n+\ttest_cmp expect actual1 &&\n+\ttest_cmp expect actual2 &&\n \techo >fail &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n@@ -1625,8 +1625,8 @@ test_expect_success 'format-patch --base errors out when base commit is in revis\n \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse HEAD~2)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '\n@@ -1652,8 +1652,8 @@ test_expect_success 'format-patch --base errors out when base commit is not ance\n \ttest_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&\n \tgit format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(cat commit-id-base)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base=auto' '\n@@ -1664,8 +1664,8 @@ test_expect_success 'format-patch --base=auto' '\n \ttest_commit N2 &&\n \tgit format-patch --stdout --base=auto -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch errors out when history involves criss-cross' '\n@@ -1701,8 +1701,8 @@ test_expect_success 'format-patch format.useAutoBaseoption' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base overrides format.useAutoBase' '\n@@ -1710,8 +1710,8 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expected &&\n-\ttest_cmp expected actual\n+\techo \"base-commit: $(git rev-parse HEAD~1)\" >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'format-patch --base with --attach' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381291","messageId":"5c49703aa4fd3741d1685d25b647d775003f9962.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 03/13] t4014: move closing sq onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:04:55Z","receivedAt":"2019-08-27T04:05:00Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The usual convention for test cases is for the closing sq to be on its\nown line. Move the sq onto its own line for cases that do not conform to\nthis style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 62f5680f05..5e8eb6fb27 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -790,11 +790,13 @@ test_expect_success 'options no longer allowed for format-patch' '\n \ttest_must_fail git format-patch --name-status 2> output &&\n \ttest_i18ncmp expect.name-status output &&\n \ttest_must_fail git format-patch --check 2> output &&\n-\ttest_i18ncmp expect.check output'\n+\ttest_i18ncmp expect.check output\n+'\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n \tgit format-patch --numstat --stdout master..side > output &&\n-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)'\n+\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n+'\n \n test_expect_success 'format-patch -- <path>' '\n \tgit format-patch master..side -- file 2>error &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381292","messageId":"02a11147fd016be4f0933cc30a759cb688506f4f.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 04/13] t4014: use sq for test case names","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:04:58Z","receivedAt":"2019-08-27T04:05:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The usual convention is for test case names to be written between\nsingle-quotes. Change all double-quoted test case names to single-quotes\nexcept for one test case name that uses a sq for a contraction.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 5e8eb6fb27..a7b440b003 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -58,20 +58,20 @@ test_expect_success setup '\n \tgit checkout master\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout master..side >patch0 &&\n \tcnt=$(grep \"^From \" patch0 | wc -l) &&\n \ttest $cnt = 3\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n \tcnt=$(grep \"^From \" patch1 | wc -l) &&\n \ttest $cnt = 2\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream handles tags\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '\n \tgit tag -a v1 -m tag side &&\n \tgit tag -a v2 -m tag master &&\n \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n@@ -94,14 +94,14 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \ttest $cnt = 3\n '\n \n-test_expect_success \"format-patch result applies\" '\n+test_expect_success 'format-patch result applies' '\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n \ttest $cnt = 2\n '\n \n-test_expect_success \"format-patch --ignore-if-in-upstream result applies\" '\n+test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n \tcnt=$(git rev-list master.. | wc -l) &&\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381293","messageId":"8d9791c0611897f3bd3cbeaf5df65db8925a3e65.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 05/13] t4014: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:00Z","receivedAt":"2019-08-27T04:05:05Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 62 ++++++++++++++++++++---------------------\n 1 file changed, 31 insertions(+), 31 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex a7b440b003..075affb1e5 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -126,8 +126,8 @@ test_expect_success 'extra headers' '\n \" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\n \" &&\n-\tgit format-patch --stdout master..side > patch2 &&\n-\tsed -e \"/^\\$/q\" patch2 > hdrs2 &&\n+\tgit format-patch --stdout master..side >patch2 &&\n+\tsed -e \"/^\\$/q\" patch2 >hdrs2 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs2 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs2\n '\n@@ -136,7 +136,7 @@ test_expect_success 'extra headers without newlines' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"Cc: S E Cipient <scipient@example.com>\" &&\n \tgit format-patch --stdout master..side >patch3 &&\n-\tsed -e \"/^\\$/q\" patch3 > hdrs3 &&\n+\tsed -e \"/^\\$/q\" patch3 >hdrs3 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs3 &&\n \tgrep \"^Cc: S E Cipient <scipient@example.com>\\$\" hdrs3\n '\n@@ -144,8 +144,8 @@ test_expect_success 'extra headers without newlines' '\n test_expect_success 'extra headers with multiple To:s' '\n \tgit config --replace-all format.headers \"To: R E Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S E Cipient <scipient@example.com>\" &&\n-\tgit format-patch --stdout master..side > patch4 &&\n-\tsed -e \"/^\\$/q\" patch4 > hdrs4 &&\n+\tgit format-patch --stdout master..side >patch4 &&\n+\tsed -e \"/^\\$/q\" patch4 >hdrs4 &&\n \tgrep \"^To: R E Cipient <rcipient@example.com>,\\$\" hdrs4 &&\n \tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs4\n '\n@@ -318,7 +318,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? > status.out) |\n+\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -333,12 +333,12 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' > actual &&\n+\t' >actual &&\n \ttest 0 = \"$(cat status.out)\" &&\n \ttest_cmp \"$expect\" actual\n }\n \n-cat >> expect.no-threading <<EOF\n+cat >>expect.no-threading <<EOF\n ---\n ---\n ---\n@@ -349,7 +349,7 @@ test_expect_success 'no threading' '\n \tcheck_threading expect.no-threading master\n '\n \n-cat > expect.thread <<EOF\n+cat >expect.thread <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -366,7 +366,7 @@ test_expect_success 'thread' '\n \tcheck_threading expect.thread --thread master\n '\n \n-cat > expect.in-reply-to <<EOF\n+cat >expect.in-reply-to <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -386,7 +386,7 @@ test_expect_success 'thread in-reply-to' '\n \t\t--thread master\n '\n \n-cat > expect.cover-letter <<EOF\n+cat >expect.cover-letter <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -407,7 +407,7 @@ test_expect_success 'thread cover-letter' '\n \tcheck_threading expect.cover-letter --cover-letter --thread master\n '\n \n-cat > expect.cl-irt <<EOF\n+cat >expect.cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -439,7 +439,7 @@ test_expect_success 'thread explicit shallow' '\n \t\t--in-reply-to=\"<test.message>\" --thread=shallow master\n '\n \n-cat > expect.deep <<EOF\n+cat >expect.deep <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -457,7 +457,7 @@ test_expect_success 'thread deep' '\n \tcheck_threading expect.deep --thread=deep master\n '\n \n-cat > expect.deep-irt <<EOF\n+cat >expect.deep-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -480,7 +480,7 @@ test_expect_success 'thread deep in-reply-to' '\n \t\t--in-reply-to=\"<test.message>\" master\n '\n \n-cat > expect.deep-cl <<EOF\n+cat >expect.deep-cl <<EOF\n ---\n Message-Id: <0>\n ---\n@@ -504,7 +504,7 @@ test_expect_success 'thread deep cover-letter' '\n \tcheck_threading expect.deep-cl --cover-letter --thread=deep master\n '\n \n-cat > expect.deep-cl-irt <<EOF\n+cat >expect.deep-cl-irt <<EOF\n ---\n Message-Id: <0>\n In-Reply-To: <1>\n@@ -584,7 +584,7 @@ test_expect_success 'cover-letter inherits diff options' '\n \tgrep \"file => foo .* 0 *\\$\" 0000-cover-letter.patch\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n   This is an excessively long subject line for a message due to the\n     habit some projects have of not having a short, one-line subject at\n     the start of the commit message, but rather sticking a whole\n@@ -596,11 +596,11 @@ EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \tgit format-patch --cover-letter -2 &&\n-\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" < 0000-cover-letter.patch > output &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" <0000-cover-letter.patch >output &&\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n index $before..$after 100644\n --- a/file\n +++ b/file\n@@ -620,7 +620,7 @@ test_expect_success 'format-patch respects -U' '\n \ttest_cmp expect output\n '\n \n-cat > expect << EOF\n+cat >expect <<EOF\n \n diff --git a/file b/file\n index $before..$after 100644\n@@ -635,7 +635,7 @@ EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n \tgit format-patch -p -2 &&\n-\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&\n+\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n \ttest_cmp expect output\n '\n \n@@ -689,7 +689,7 @@ test_expect_success 'format-patch from a subdirectory (3)' '\n '\n \n test_expect_success 'format-patch --in-reply-to' '\n-\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" > patch8 &&\n+\tgit format-patch -1 --stdout --in-reply-to \"baz@foo.bar\" >patch8 &&\n \tgrep \"^In-Reply-To: <baz@foo.bar>\" patch8 &&\n \tgrep \"^References: <baz@foo.bar>\" patch8\n '\n@@ -780,21 +780,21 @@ test_expect_success 'format-patch with multiple notes refs' '\n \t! grep \"this is note 2\" out\n '\n \n-echo \"fatal: --name-only does not make sense\" > expect.name-only\n-echo \"fatal: --name-status does not make sense\" > expect.name-status\n-echo \"fatal: --check does not make sense\" > expect.check\n+echo \"fatal: --name-only does not make sense\" >expect.name-only\n+echo \"fatal: --name-status does not make sense\" >expect.name-status\n+echo \"fatal: --check does not make sense\" >expect.check\n \n test_expect_success 'options no longer allowed for format-patch' '\n-\ttest_must_fail git format-patch --name-only 2> output &&\n+\ttest_must_fail git format-patch --name-only 2>output &&\n \ttest_i18ncmp expect.name-only output &&\n-\ttest_must_fail git format-patch --name-status 2> output &&\n+\ttest_must_fail git format-patch --name-status 2>output &&\n \ttest_i18ncmp expect.name-status output &&\n-\ttest_must_fail git format-patch --check 2> output &&\n+\ttest_must_fail git format-patch --check 2>output &&\n \ttest_i18ncmp expect.check output\n '\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n-\tgit format-patch --numstat --stdout master..side > output &&\n+\tgit format-patch --numstat --stdout master..side >output &&\n \ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n '\n \n@@ -1610,14 +1610,14 @@ test_expect_success 'format-patch --base' '\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n-\tsignature >> expect &&\n+\tsignature >>expect &&\n \ttest_cmp expect actual1 &&\n \ttest_cmp expect actual2 &&\n \techo >fail &&\n \techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n \techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\tsignature >> fail &&\n+\tsignature >>fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381294","messageId":"90ad0fcf703e8b932789194b0a86ce061ffd48e0.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 06/13] t4014: use indentable here-docs","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:03Z","receivedAt":"2019-08-27T04:05:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The convention is to use indentable here-docs within test cases so that\nthe here-docs line up with the rest of the code within the test case.\nChange here-docs from `<<\\EOF` to `<<-\\EOF` so that they can be indented\nalong with the rest of the test case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 368 ++++++++++++++++++++--------------------\n 1 file changed, 184 insertions(+), 184 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 075affb1e5..c07d868491 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1211,282 +1211,282 @@ append_signoff()\n \n test_expect_success 'signoff: commit with no body' '\n \tappend_signoff </dev/null >actual &&\n-\tcat <<\\EOF | sed \"s/EOL$//\" >expect &&\n-4:Subject: [PATCH] EOL\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat <<-\\EOF | sed \"s/EOL$//\" >expect &&\n+\t4:Subject: [PATCH] EOL\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject' '\n \techo subject | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: commit with only subject that does not end with NL' '\n \tprintf subject | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: no existing signoffs and no trailing NL' '\n \tprintf \"subject\\n\\nbody\" | append_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: misc conforming footer elements' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: my@house\n-(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n-Tested-by: Some One <someone@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: my@house\n-15:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: my@house\n+\t(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)\n+\tTested-by: Some One <someone@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: my@house\n+\t15:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: some random signoff-alike' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n-Fooled-by-me: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tbody\n+\tFooled-by-me: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-I want to mention about Signed-off-by: here.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:I want to mention about Signed-off-by: here.\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tI want to mention about Signed-off-by: here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:I want to mention about Signed-off-by: here.\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: not really a signoff (2)' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-My unfortunate\n-Signed-off-by: example happens to be wrapped here.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:Signed-off-by: example happens to be wrapped here.\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMy unfortunate\n+\tSigned-off-by: example happens to be wrapped here.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:Signed-off-by: example happens to be wrapped here.\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: valid S-o-b paragraph in the middle' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Signed-off-by: my@house\n-Signed-off-by: your@house\n+\tSigned-off-by: my@house\n+\tSigned-off-by: your@house\n \n-A lot of houses.\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: my@house\n-10:Signed-off-by: your@house\n-11:\n-13:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tA lot of houses.\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: my@house\n+\t10:Signed-off-by: your@house\n+\t11:\n+\t13:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff at the end, no trailing NL' '\n \tprintf \"subject\\n\\nSigned-off-by: C O Mitter <committer@example.com>\" |\n \t\tappend_signoff >actual &&\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-9:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t9:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: the same signoff NOT at the end' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Signed-off-by: C O Mitter <committer@example.com>\n-Signed-off-by: my@house\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-12:Signed-off-by: my@house\n-EOF\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tSigned-off-by: my@house\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\t12:Signed-off-by: my@house\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: tolerate garbage in conforming footer' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Tested-by: my@house\n-Some Trash\n-Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-13:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tTested-by: my@house\n+\tSome Trash\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t13:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: respect trailer config' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:\n-12:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:\n+\t12:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual &&\n \n \ttest_config trailer.Myfooter.ifexists add &&\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-Myfooter: x\n-Some Trash\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-11:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tMyfooter: x\n+\tSome Trash\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t11:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n test_expect_success 'signoff: footer begins with non-signoff without @ sign' '\n-\tappend_signoff <<\\EOF >actual &&\n-subject\n+\tappend_signoff <<-\\EOF >actual &&\n+\tsubject\n \n-body\n+\tbody\n \n-Reviewed-id: Noone\n-Tested-by: my@house\n-Change-id: Ideadbeef\n-Signed-off-by: C O Mitter <committer@example.com>\n-Bug: 1234\n-EOF\n-\tcat >expect <<\\EOF &&\n-4:Subject: [PATCH] subject\n-8:\n-10:\n-14:Signed-off-by: C O Mitter <committer@example.com>\n-EOF\n+\tReviewed-id: Noone\n+\tTested-by: my@house\n+\tChange-id: Ideadbeef\n+\tSigned-off-by: C O Mitter <committer@example.com>\n+\tBug: 1234\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\t4:Subject: [PATCH] subject\n+\t8:\n+\t10:\n+\t14:Signed-off-by: C O Mitter <committer@example.com>\n+\tEOF\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381295","messageId":"804b3163f866cce0b8a928256b5009fc42dbc709.1566878373.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 07/13] t4014: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:05Z","receivedAt":"2019-08-27T04:05:10Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex c07d868491..2048fb2008 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1502,42 +1502,42 @@ test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (2)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (3)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter ^master rebuild-1 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (4)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter master.. >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (5)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 HEAD >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter using branch description (6)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n \tgit format-patch --stdout --cover-letter -2 >actual &&\n-\tgrep hello actual >/dev/null\n+\tgrep hello actual\n '\n \n test_expect_success 'cover letter with nothing' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381296","messageId":"967e624bb4ade3ec1ddaa4e30566e2d938a6cfed.1566878374.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 08/13] t4014: let sed open its own files","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:07Z","receivedAt":"2019-08-27T04:05:13Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In some cases, we were using a redirection operator to feed input into\nsed. However, since sed is capable of opening its own files, make sed\nopen its own files instead of redirecting input into it.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 28 ++++++++++++++--------------\n 1 file changed, 14 insertions(+), 14 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 2048fb2008..35cf798847 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -596,7 +596,7 @@ EOF\n \n test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n \tgit format-patch --cover-letter -2 &&\n-\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" <0000-cover-letter.patch >output &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^\\$/q\" 0000-cover-letter.patch >output &&\n \ttest_cmp expect output\n '\n \n@@ -635,7 +635,7 @@ EOF\n \n test_expect_success 'format-patch -p suppresses stat' '\n \tgit format-patch -p -2 &&\n-\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n+\tsed -e \"1,/^\\$/d\" -e \"/^+5/q\" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&\n \ttest_cmp expect output\n '\n \n@@ -890,7 +890,7 @@ test_expect_success 'prepare mail-signature input' '\n test_expect_success '--signature-file=file works' '\n \tgit format-patch --stdout --signature-file=mail-signature -1 >output &&\n \tcheck_patch output &&\n-\tsed -e \"1,/^-- \\$/d\" <output >actual &&\n+\tsed -e \"1,/^-- \\$/d\" output >actual &&\n \t{\n \t\tcat mail-signature && echo\n \t} >expect &&\n@@ -901,7 +901,7 @@ test_expect_success 'format.signaturefile works' '\n \ttest_config format.signaturefile mail-signature &&\n \tgit format-patch --stdout -1 >output &&\n \tcheck_patch output &&\n-\tsed -e \"1,/^-- \\$/d\" <output >actual &&\n+\tsed -e \"1,/^-- \\$/d\" output >actual &&\n \t{\n \t\tcat mail-signature && echo\n \t} >expect &&\n@@ -923,7 +923,7 @@ test_expect_success '--signature-file overrides format.signaturefile' '\n \tgit format-patch --stdout \\\n \t\t\t--signature-file=other-mail-signature -1 >output &&\n \tcheck_patch output &&\n-\tsed -e \"1,/^-- \\$/d\" <output >actual &&\n+\tsed -e \"1,/^-- \\$/d\" output >actual &&\n \t{\n \t\tcat other-mail-signature && echo\n \t} >expect &&\n@@ -992,7 +992,7 @@ test_expect_success 'format-patch wraps extremely long subject (ascii)' '\n \tgit add file &&\n \tgit commit -m \"$M512\" &&\n \tgit format-patch --stdout -1 >patch &&\n-\tsed -n \"/^Subject/p; /^ /p; /^$/q\" <patch >subject &&\n+\tsed -n \"/^Subject/p; /^ /p; /^$/q\" patch >subject &&\n \ttest_cmp expect subject\n '\n \n@@ -1031,7 +1031,7 @@ test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '\n \tgit add file &&\n \tgit commit -m \"$M512\" &&\n \tgit format-patch --stdout -1 >patch &&\n-\tsed -n \"/^Subject/p; /^ /p; /^$/q\" <patch >subject &&\n+\tsed -n \"/^Subject/p; /^ /p; /^$/q\" patch >subject &&\n \ttest_cmp expect subject\n '\n \n@@ -1040,7 +1040,7 @@ check_author() {\n \tgit add file &&\n \tGIT_AUTHOR_NAME=$1 git commit -m author-check &&\n \tgit format-patch --stdout -1 >patch &&\n-\tsed -n \"/^From: /p; /^ /p; /^$/q\" <patch >actual &&\n+\tsed -n \"/^From: /p; /^ /p; /^$/q\" patch >actual &&\n \ttest_cmp expect actual\n }\n \n@@ -1160,7 +1160,7 @@ test_expect_success '--from=ident replaces author' '\n \tFrom: A U Thor <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1172,7 +1172,7 @@ test_expect_success '--from uses committer ident' '\n \tFrom: A U Thor <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1182,7 +1182,7 @@ test_expect_success '--from omits redundant in-body header' '\n \tFrom: A U Thor <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1197,7 +1197,7 @@ test_expect_success 'in-body headers trigger content encoding' '\n \tFrom: éxötìc <author@example.com>\n \n \tEOF\n-\tsed -ne \"/^From:/p; /^$/p; /^Content-Type/p; /^---$/q\" <patch >patch.head &&\n+\tsed -ne \"/^From:/p; /^$/p; /^Content-Type/p; /^---$/q\" patch >patch.head &&\n \ttest_cmp expect patch.head\n '\n \n@@ -1788,7 +1788,7 @@ test_expect_success 'interdiff: cover-letter' '\n \tgit format-patch --cover-letter --interdiff=boop~2 -1 boop &&\n \ttest_i18ngrep \"^Interdiff:$\" 0000-cover-letter.patch &&\n \ttest_i18ngrep ! \"^Interdiff:$\" 0001-fleep.patch &&\n-\tsed \"1,/^@@ /d; /^-- $/q\" <0000-cover-letter.patch >actual &&\n+\tsed \"1,/^@@ /d; /^-- $/q\" 0000-cover-letter.patch >actual &&\n \ttest_cmp expect actual\n '\n \n@@ -1804,7 +1804,7 @@ test_expect_success 'interdiff: solo-patch' '\n \tEOF\n \tgit format-patch --interdiff=boop~2 -1 boop &&\n \ttest_i18ngrep \"^Interdiff:$\" 0001-fleep.patch &&\n-\tsed \"1,/^  @@ /d; /^$/q\" <0001-fleep.patch >actual &&\n+\tsed \"1,/^  @@ /d; /^$/q\" 0001-fleep.patch >actual &&\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381297","messageId":"9a42ec2b7e5f9bea3676655e3a066acac3bee1f6.1566878374.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 09/13] t4014: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:10Z","receivedAt":"2019-08-27T04:05:15Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Convert all instances of `cnt=$(... | wc -l) && test $cnt = N` into uses\nof `test_line_count()`.\n\nWhile we're at it, convert one instance of a Git command upstream of a\npipe into two commands. This prevents a failure of a Git command from\nbeing masked since only the return code of the last member of the pipe\nis shown.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 35 +++++++++++++++++++----------------\n 1 file changed, 19 insertions(+), 16 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 35cf798847..18142ee5fa 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -60,23 +60,23 @@ test_expect_success setup '\n \n test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout master..side >patch0 &&\n-\tcnt=$(grep \"^From \" patch0 | wc -l) &&\n-\ttest $cnt = 3\n+\tgrep \"^From \" patch0 >from0 &&\n+\ttest_line_count = 3 from0\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream' '\n \tgit format-patch --stdout \\\n \t\t--ignore-if-in-upstream master..side >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '\n \tgit tag -a v1 -m tag side &&\n \tgit tag -a v2 -m tag master &&\n \tgit format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&\n-\tcnt=$(grep \"^From \" patch1 | wc -l) &&\n-\ttest $cnt = 2\n+\tgrep \"^From \" patch1 >from1 &&\n+\ttest_line_count = 2 from1\n '\n \n test_expect_success \"format-patch doesn't consider merge commits\" '\n@@ -90,22 +90,23 @@ test_expect_success \"format-patch doesn't consider merge commits\" '\n \tgit checkout -b merger master &&\n \ttest_tick &&\n \tgit merge --no-ff slave &&\n-\tcnt=$(git format-patch -3 --stdout | grep \"^From \" | wc -l) &&\n-\ttest $cnt = 3\n+\tgit format-patch -3 --stdout >patch &&\n+\tgrep \"^From \" patch >from &&\n+\ttest_line_count = 3 from\n '\n \n test_expect_success 'format-patch result applies' '\n \tgit checkout -b rebuild-0 master &&\n \tgit am -3 patch0 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n \tgit checkout -b rebuild-1 master &&\n \tgit am -3 patch1 &&\n-\tcnt=$(git rev-list master.. | wc -l) &&\n-\ttest $cnt = 2\n+\tgit rev-list master.. >list &&\n+\ttest_line_count = 2 list\n '\n \n test_expect_success 'commit did not screw up the log message' '\n@@ -795,7 +796,8 @@ test_expect_success 'options no longer allowed for format-patch' '\n \n test_expect_success 'format-patch --numstat should produce a patch' '\n \tgit format-patch --numstat --stdout master..side >output &&\n-\ttest 5 = $(grep \"^diff --git a/\" output | wc -l)\n+\tgrep \"^diff --git a/\" output >diff &&\n+\ttest_line_count = 5 diff\n '\n \n test_expect_success 'format-patch -- <path>' '\n@@ -852,8 +854,8 @@ test_expect_success 'format-patch --signature --cover-letter' '\n \tgit config --unset-all format.signature &&\n \tgit format-patch --stdout --signature=\"my sig\" --cover-letter \\\n \t\t-1 >output &&\n-\tgrep \"my sig\" output &&\n-\ttest 2 = $(grep \"my sig\" output | wc -l)\n+\tgrep \"my sig\" output >sig &&\n+\ttest_line_count = 2 sig\n '\n \n test_expect_success 'format.signature=\"\" suppresses signatures' '\n@@ -1591,7 +1593,8 @@ test_expect_success 'format-patch format.outputDirectory option' '\n \ttest_config format.outputDirectory patches &&\n \trm -fr patches &&\n \tgit format-patch master..side &&\n-\ttest $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)\n+\tgit rev-list master..side >list &&\n+\ttest_line_count = $(ls patches | wc -l) list\n '\n \n test_expect_success 'format-patch -o overrides format.outputDirectory' '\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381298","messageId":"8acc90f74d89301646f8120ebb79eb9170f64743.1566878374.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 10/13] t4014: remove confusing pipe in check_threading()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:12Z","receivedAt":"2019-08-27T04:05:17Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In check_threading(), there was a Git command in the upstream of a pipe.\nIn order to not lose its status code, it was saved into a file. However,\nthis may be confusing so rewrite to redirect IO to file. This allows us\nto directly use the conventional &&-chain.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 5 ++---\n 1 file changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 18142ee5fa..67f4c62ed6 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -319,7 +319,7 @@ test_expect_success 'reroll count (-v)' '\n check_threading () {\n \texpect=\"$1\" &&\n \tshift &&\n-\t(git format-patch --stdout \"$@\"; echo $? >status.out) |\n+\tgit format-patch --stdout \"$@\" >patch &&\n \t# Prints everything between the Message-ID and In-Reply-To,\n \t# and replaces all Message-ID-lookalikes by a sequence number\n \tperl -ne '\n@@ -334,8 +334,7 @@ check_threading () {\n \t\t\tprint;\n \t\t}\n \t\tprint \"---\\n\" if /^From /i;\n-\t' >actual &&\n-\ttest 0 = \"$(cat status.out)\" &&\n+\t' <patch >actual &&\n \ttest_cmp \"$expect\" actual\n }\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381299","messageId":"bc7355485f81af8a8d6ac8c29e1ffc82925c5fd1.1566878374.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 11/13] t4014: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:15Z","receivedAt":"2019-08-27T04:05:20Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of Git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no Git commands upstream.\n\nThe other way is when a command is in a non-assignment subshell. The\nreturn code will be lost in favour of the surrounding command's. Rewrite\ninstances of this such that Git commands output to a file and\nsurrounding commands only call subshells with non-Git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4014-format-patch.sh | 197 ++++++++++++++++++++++++----------------\n 1 file changed, 120 insertions(+), 77 deletions(-)\n\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 67f4c62ed6..83f52614d3 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -33,7 +33,8 @@ test_expect_success setup '\n \tgit commit -m \"Side changes #3 with \\\\n backslash-n in it.\" &&\n \n \tgit checkout master &&\n-\tgit diff-tree -p C2 | git apply --index &&\n+\tgit diff-tree -p C2 >patch &&\n+\tgit apply --index <patch &&\n \ttest_tick &&\n \tgit commit -m \"Master accepts moral equivalent of #2\" &&\n \n@@ -110,7 +111,8 @@ test_expect_success 'format-patch --ignore-if-in-upstream result applies' '\n '\n \n test_expect_success 'commit did not screw up the log message' '\n-\tgit cat-file commit side | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit side >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n '\n \n test_expect_success 'format-patch did not screw up the log message' '\n@@ -119,7 +121,8 @@ test_expect_success 'format-patch did not screw up the log message' '\n '\n \n test_expect_success 'replay did not screw up the log message' '\n-\tgit cat-file commit rebuild-1 | grep \"^Side .* with .* backslash-n\"\n+\tgit cat-file commit rebuild-1 >actual &&\n+\tgrep \"^Side .* with .* backslash-n\" actual\n '\n \n test_expect_success 'extra headers' '\n@@ -153,63 +156,73 @@ test_expect_success 'extra headers with multiple To:s' '\n \n test_expect_success 'additional command line cc (ascii)' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S E Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_failure 'additional command line cc (rfc822)' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch5 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch5 &&\n-\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" patch5\n+\tgit format-patch --cc=\"S. E. Cipient <scipient@example.com>\" --stdout master..side >patch5 &&\n+\tsed -e \"/^\\$/q\" patch5 >hdrs5 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs5 &&\n+\tgrep \"^ *\\\"S. E. Cipient\\\" <scipient@example.com>\\$\" hdrs5\n '\n \n test_expect_success 'command line headers' '\n \tgit config --unset-all format.headers &&\n-\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch6 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" patch6\n+\tgit format-patch --add-header=\"Cc: R E Cipient <rcipient@example.com>\" --stdout master..side >patch6 &&\n+\tsed -e \"/^\\$/q\" patch6 >hdrs6 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>\\$\" hdrs6\n '\n \n test_expect_success 'configuration headers and command line headers' '\n \tgit config --replace-all format.headers \"Cc: R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch7 &&\n-\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" patch7 &&\n-\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" patch7\n+\tgit format-patch --add-header=\"Cc: S E Cipient <scipient@example.com>\" --stdout master..side >patch7 &&\n+\tsed -e \"/^\\$/q\" patch7 >hdrs7 &&\n+\tgrep \"^Cc: R E Cipient <rcipient@example.com>,\\$\" hdrs7 &&\n+\tgrep \"^ *S E Cipient <scipient@example.com>\\$\" hdrs7\n '\n \n test_expect_success 'command line To: header (ascii)' '\n \tgit config --unset-all format.headers &&\n-\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R E Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc822)' '\n-\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R. E. Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_failure 'command line To: header (rfc2047)' '\n-\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side | sed -e \"/^\\$/q\" >patch8 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch8\n+\tgit format-patch --to=\"R Ä Cipient <rcipient@example.com>\" --stdout master..side >patch8 &&\n+\tsed -e \"/^\\$/q\" patch8 >hdrs8 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs8\n '\n \n test_expect_success 'configuration To: header (ascii)' '\n \tgit config format.to \"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc822)' '\n \tgit config format.to \"R. E. Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: \\\"R. E. Cipient\\\" <rcipient@example.com>\\$\" hdrs9\n '\n \n test_expect_failure 'configuration To: header (rfc2047)' '\n \tgit config format.to \"R Ä Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --stdout master..side | sed -e \"/^\\$/q\" >patch9 &&\n-\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" patch9\n+\tgit format-patch --stdout master..side >patch9 &&\n+\tsed -e \"/^\\$/q\" patch9 >hdrs9 &&\n+\tgrep \"^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\\$\" hdrs9\n '\n \n # check_patch <patch>: Verify that <patch> looks like a half-sane\n@@ -221,76 +234,76 @@ check_patch () {\n }\n \n test_expect_success 'format.from=false' '\n-\tgit -c format.from=false format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n+\tgit -c format.from=false format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n \tcheck_patch patch &&\n-\t! grep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\t! grep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from=true' '\n-\tgit -c format.from=true format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: C O Mitter <committer@example.com>\\$\" patch\n+\tgit -c format.from=true format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: C O Mitter <committer@example.com>\\$\" hdrs\n '\n \n test_expect_success 'format.from with address' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\tgrep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\tgrep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-from overrides format.from' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --no-from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--from overrides format.from' '\n-\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch &&\n-\tcheck_patch patch &&\n-\t! grep \"^From: F R Om <from@example.com>\\$\" patch\n+\tgit -c format.from=\"F R Om <from@example.com>\" format-patch --from --stdout master..side >patch &&\n+\tsed -e \"/^\\$/q\" patch >hdrs &&\n+\tcheck_patch hdrs &&\n+\t! grep \"^From: F R Om <from@example.com>\\$\" hdrs\n '\n \n test_expect_success '--no-to overrides config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"R E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-to --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch10 &&\n-\tcheck_patch patch10 &&\n-\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" patch10\n+\tgit format-patch --no-to --stdout master..side >patch10 &&\n+\tsed -e \"/^\\$/q\" patch10 >hdrs10 &&\n+\tcheck_patch hdrs10 &&\n+\t! grep \"^To: R E Cipient <rcipient@example.com>\\$\" hdrs10\n '\n \n test_expect_success '--no-to and --to replaces config.to' '\n \tgit config --replace-all format.to \\\n \t\t\"Someone <someone@out.there>\" &&\n \tgit format-patch --no-to --to=\"Someone Else <else@out.there>\" \\\n-\t\t--stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch11 &&\n-\tcheck_patch patch11 &&\n-\t! grep \"^To: Someone <someone@out.there>\\$\" patch11 &&\n-\tgrep \"^To: Someone Else <else@out.there>\\$\" patch11\n+\t\t--stdout master..side >patch11 &&\n+\tsed -e \"/^\\$/q\" patch11 >hdrs11 &&\n+\tcheck_patch hdrs11 &&\n+\t! grep \"^To: Someone <someone@out.there>\\$\" hdrs11 &&\n+\tgrep \"^To: Someone Else <else@out.there>\\$\" hdrs11\n '\n \n test_expect_success '--no-cc overrides config.cc' '\n \tgit config --replace-all format.cc \\\n \t\t\"C E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-cc --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch12 &&\n-\tcheck_patch patch12 &&\n-\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" patch12\n+\tgit format-patch --no-cc --stdout master..side >patch12 &&\n+\tsed -e \"/^\\$/q\" patch12 >hdrs12 &&\n+\tcheck_patch hdrs12 &&\n+\t! grep \"^Cc: C E Cipient <rcipient@example.com>\\$\" hdrs12\n '\n \n test_expect_success '--no-add-header overrides config.headers' '\n \tgit config --replace-all format.headers \\\n \t\t\"Header1: B E Cipient <rcipient@example.com>\" &&\n-\tgit format-patch --no-add-header --stdout master..side |\n-\tsed -e \"/^\\$/q\" >patch13 &&\n-\tcheck_patch patch13 &&\n-\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" patch13\n+\tgit format-patch --no-add-header --stdout master..side >patch13 &&\n+\tsed -e \"/^\\$/q\" patch13 >hdrs13 &&\n+\tcheck_patch hdrs13 &&\n+\t! grep \"^Header1: B E Cipient <rcipient@example.com>\\$\" hdrs13\n '\n \n test_expect_success 'multiple files' '\n@@ -808,20 +821,25 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '\n \tgit format-patch --ignore-if-in-upstream HEAD\n '\n \n-git_version=\"$(git --version | sed \"s/.* //\")\"\n+test_expect_success 'get git version' '\n+\tgit_version=$(git --version) &&\n+\tgit_version=${git_version##* }\n+'\n \n signature() {\n \tprintf \"%s\\n%s\\n\\n\" \"-- \" \"${1:-$git_version}\"\n }\n \n test_expect_success 'format-patch default signature' '\n-\tgit format-patch --stdout -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature >expect &&\n \ttest_cmp expect output\n '\n \n test_expect_success 'format-patch --signature' '\n-\tgit format-patch --stdout --signature=\"my sig\" -1 | tail -n 3 >output &&\n+\tgit format-patch --stdout --signature=\"my sig\" -1 >patch &&\n+\ttail -n 3 patch >output &&\n \tsignature \"my sig\" >expect &&\n \ttest_cmp expect output\n '\n@@ -1606,19 +1624,40 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' '\n \n test_expect_success 'format-patch --base' '\n \tgit checkout patchid &&\n-\tgit format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&\n-\tgit format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 -1 >patch &&\n+\ttail -n 7 patch >actual1 &&\n+\n+\tgit format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&\n+\ttail -n 7 patch >actual2 &&\n+\n \techo >expect &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>expect &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk \"{print \\$1}\")\" >>expect &&\n+\tgit rev-parse HEAD~3 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>expect &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --stable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>expect &&\n+\n \tsignature >>expect &&\n \ttest_cmp expect actual1 &&\n \ttest_cmp expect actual2 &&\n+\n \techo >fail &&\n-\techo \"base-commit: $(git rev-parse HEAD~3)\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n-\techo \"prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk \"{print \\$1}\")\" >>fail &&\n+\techo \"base-commit: $(cat commit-id-base)\" >>fail &&\n+\n+\tgit show --patch HEAD~2 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n+\tgit show --patch HEAD~1 >patch &&\n+\tgit patch-id --unstable <patch >patch.id.raw &&\n+\tawk \"{print \\\"prerequisite-patch-id:\\\", \\$1}\" <patch.id.raw >>fail &&\n+\n \tsignature >>fail &&\n \t! test_cmp fail actual1 &&\n \t! test_cmp fail actual2\n@@ -1629,7 +1668,8 @@ test_expect_success 'format-patch --base errors out when base commit is in revis\n \ttest_must_fail git format-patch --base=HEAD~1 -2 &&\n \tgit format-patch --stdout --base=HEAD~2 -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~2)\" >expect &&\n+\tgit rev-parse HEAD~2 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1668,7 +1708,8 @@ test_expect_success 'format-patch --base=auto' '\n \ttest_commit N2 &&\n \tgit format-patch --stdout --base=auto -2 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1705,7 +1746,8 @@ test_expect_success 'format-patch format.useAutoBaseoption' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse upstream)\" >expect &&\n+\tgit rev-parse upstream >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -1714,7 +1756,8 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '\n \tgit config format.useAutoBase true &&\n \tgit format-patch --stdout --base=HEAD~1 -1 >patch &&\n \tgrep \"^base-commit:\" patch >actual &&\n-\techo \"base-commit: $(git rev-parse HEAD~1)\" >expect &&\n+\tgit rev-parse HEAD~1 >commit-id-base &&\n+\techo \"base-commit: $(cat commit-id-base)\" >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381300","messageId":"fd343b99c5bc3a73c3896805ea4283c9f39a9d04.1566878374.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 12/13] Doc: add more detail for git-format-patch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:17Z","receivedAt":"2019-08-27T04:05:22Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In git-format-patch.txt, we were missing some key user information.\nFirst of all, document the special value of `--base=auto`.\n\nNext, while we're at it, surround option arguments with <> and change\nexisting names such as \"Message-Id\" to \"message id\", which conforms with\nhow existing documentation is written.\n\nFinally, document the `format.outputDirectory` config and change\n`format.coverletter` to use camel case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-format-patch.txt | 23 +++++++++++++----------\n 1 file changed, 13 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex b9b97e63ae..0ac56f4b70 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -17,9 +17,9 @@ SYNOPSIS\n \t\t   [--signature-file=<file>]\n \t\t   [-n | --numbered | -N | --no-numbered]\n \t\t   [--start-number <n>] [--numbered-files]\n-\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n+\t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n-\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n+\t\t   [--rfc] [--subject-prefix=<subject prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n \t\t   [--[no-]cover-letter] [--quiet]\n@@ -159,9 +159,9 @@ Beware that the default for 'git send-email' is to thread emails\n itself.  If you want `git format-patch` to take care of threading, you\n will want to ensure that threading is disabled for `git send-email`.\n \n---in-reply-to=Message-Id::\n+--in-reply-to=<message id>::\n \tMake the first mail (or all the mails with `--no-thread`) appear as a\n-\treply to the given Message-Id, which avoids breaking threads to\n+\treply to the given <message id>, which avoids breaking threads to\n \tprovide a new patch series.\n \n --ignore-if-in-upstream::\n@@ -171,9 +171,9 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n---subject-prefix=<Subject-Prefix>::\n+--subject-prefix=<subject prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n-\tline, instead use '[<Subject-Prefix>]'. This\n+\tline, instead use '[<subject prefix>]'. This\n \tallows for useful naming of a patch series, and can be\n \tcombined with the `--numbered` option.\n \n@@ -314,7 +314,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n --base=<commit>::\n \tRecord the base tree information to identify the state the\n \tpatch series applies to.  See the BASE TREE INFORMATION section\n-\tbelow for details.\n+\tbelow for details. If <commit> is \"auto\", a base commit is\n+\tautomatically chosen.\n \n --root::\n \tTreat the revision argument as a <revision range>, even if it\n@@ -330,8 +331,9 @@ CONFIGURATION\n -------------\n You can specify extra mail header lines to be added to each message,\n defaults for the subject prefix and file suffix, number patches when\n-outputting more than one patch, add \"To\" or \"Cc:\" headers, configure\n-attachments, and sign off patches with configuration variables.\n+outputting more than one patch, add \"To:\" or \"Cc:\" headers, configure\n+attachments, change the patch output directory, and sign off patches\n+with configuration variables.\n \n ------------\n [format]\n@@ -343,7 +345,8 @@ attachments, and sign off patches with configuration variables.\n \tcc = <email>\n \tattach [ = mime-boundary-string ]\n \tsignOff = true\n-\tcoverletter = auto\n+\toutputDirectory = <directory>\n+\tcoverLetter = auto\n ------------\n \n \n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381301","messageId":"4e429e1989173e07bcb9b622b732e46bf3dab828.1566878374.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"[PATCH v2 13/13] config/format.txt: specify default value of format.coverLetter","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-08-27T04:05:20Z","receivedAt":"2019-08-27T04:05:25Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex 414a5a8a9d..cb629fa769 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -77,6 +77,7 @@ format.coverLetter::\n \tA boolean that controls whether to generate a cover-letter when\n \tformat-patch is invoked, but in addition can be set to \"auto\", to\n \tgenerate a cover-letter only when there's more than one patch.\n+\tDefault is false.\n \n format.outputDirectory::\n \tSet a custom directory to store the resulting files instead of the\n-- \n2.23.0.248.g3a9dd8fb08\n\n"},{"id":"381800","messageId":"20190904112105.GA27933@archbookpro.localdomain","threadId":"51687","inReplyTo":"cover.1566878373.git.liu.denton@gmail.com","subject":"Re: [PATCH v2 00/13] format-patch: clean up tests and documentation","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-09-04T11:21:05Z","receivedAt":"2019-09-04T11:21:10Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio,\n\nI see that \"dl/format-patch-doc-test-cleanup\" currently has the comment\n\"Expecting a reroll.\" This should be the reroll that you're expecting ;)\n\nAlso, since there haven't been any comments on the topic in a while, I\npropose that it should be ready for inclusion.\n\nThanks,\n\nDenton\n\nOn Tue, Aug 27, 2019 at 12:04:47AM -0400, Denton Liu wrote:\n> In this reroll, I squashed Junio's suggestion into the correct patch.\n> Also, I took Eric's suggestion and removed the weak justification (i.e.\n> better error messages) from the sed patch since it doesn't really\n> contribute.\n> \n> \n> As one of the older parts of the Git, the tests and documentation for\n> format-patch have been needing cleanup for a while. Let's do that in\n> this patchset!\n> \n> This patchset is based on v3 of \"format-patch: learn\n> --infer-cover-subject option (also t4014 cleanup)\"[1].\n> \n> Changes since v1:\n> \n> * Squash Junio's patch into the correct patch ;)\n> \n> * Remove weak justification (better error messages) in 8/13\n> \n> Changes since v3 of \"format-patch: learn --infer-cover-subject option (also\n> t4014 cleanup)\":\n> \n> * Squash in Junio's and Hannes' suggestions\n> \n> * Add 't4014: let sed open its own files'\n> \n> [1]: https://public-inbox.org/git/xmqqwof3ljcz.fsf@gitster-ct.c.googlers.com/T/#m19570aff4828dfbd65d57cacf231c2938af1dc9f\n> \n> \n> Denton Liu (13):\n>   t4014: drop unnecessary blank lines from test cases\n>   t4014: s/expected/expect/\n>   t4014: move closing sq onto its own line\n>   t4014: use sq for test case names\n>   t4014: remove spaces after redirect operators\n>   t4014: use indentable here-docs\n>   t4014: drop redirections to /dev/null\n>   t4014: let sed open its own files\n>   t4014: use test_line_count() where possible\n>   t4014: remove confusing pipe in check_threading()\n>   t4014: stop losing return codes of git commands\n>   Doc: add more detail for git-format-patch\n>   config/format.txt: specify default value of format.coverLetter\n> \n>  Documentation/config/format.txt    |   1 +\n>  Documentation/git-format-patch.txt |  23 +-\n>  t/t4014-format-patch.sh            | 814 ++++++++++++++---------------\n>  3 files changed, 421 insertions(+), 417 deletions(-)\n> \n> Range-diff against v1:\n>  1:  fb000bfca2 =  1:  fb000bfca2 t4014: drop unnecessary blank lines from test cases\n>  2:  0a5ce9b95f =  2:  0a5ce9b95f t4014: s/expected/expect/\n>  3:  5c49703aa4 =  3:  5c49703aa4 t4014: move closing sq onto its own line\n>  4:  02a11147fd =  4:  02a11147fd t4014: use sq for test case names\n>  5:  8d9791c061 =  5:  8d9791c061 t4014: remove spaces after redirect operators\n>  6:  90ad0fcf70 =  6:  90ad0fcf70 t4014: use indentable here-docs\n>  7:  804b3163f8 =  7:  804b3163f8 t4014: drop redirections to /dev/null\n>  8:  7d9a24a979 !  8:  967e624bb4 t4014: let sed open its own files\n>     @@ Commit message\n>          t4014: let sed open its own files\n>      \n>          In some cases, we were using a redirection operator to feed input into\n>     -    sed. However, since sed is capable of opening its own files and provides\n>     -    better error messages on IO failure, make sed open its own files instead\n>     -    of redirecting input into it.\n>     +    sed. However, since sed is capable of opening its own files, make sed\n>     +    open its own files instead of redirecting input into it.\n>      \n>          Signed-off-by: Denton Liu <liu.denton@gmail.com>\n>      \n>  9:  d068d42098 =  9:  9a42ec2b7e t4014: use test_line_count() where possible\n> 10:  6a9409cee0 = 10:  8acc90f74d t4014: remove confusing pipe in check_threading()\n> 11:  c580ce447b = 11:  bc7355485f t4014: stop losing return codes of git commands\n> 12:  a97f861e6a ! 12:  fd343b99c5 Doc: add more detail for git-format-patch\n>     @@ Commit message\n>          In git-format-patch.txt, we were missing some key user information.\n>          First of all, document the special value of `--base=auto`.\n>      \n>     -    Next, while we're at it, surround option arguments with <>.\n>     +    Next, while we're at it, surround option arguments with <> and change\n>     +    existing names such as \"Message-Id\" to \"message id\", which conforms with\n>     +    how existing documentation is written.\n>      \n>          Finally, document the `format.outputDirectory` config and change\n>          `format.coverletter` to use camel case.\n>     @@ Documentation/git-format-patch.txt: SYNOPSIS\n>       \t\t   [-n | --numbered | -N | --no-numbered]\n>       \t\t   [--start-number <n>] [--numbered-files]\n>      -\t\t   [--in-reply-to=Message-Id] [--suffix=.<sfx>]\n>     -+\t\t   [--in-reply-to=<Message-Id>] [--suffix=.<sfx>]\n>     ++\t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n>       \t\t   [--ignore-if-in-upstream]\n>      -\t\t   [--rfc] [--subject-prefix=Subject-Prefix]\n>     -+\t\t   [--rfc] [--subject-prefix=<Subject-Prefix>]\n>     ++\t\t   [--rfc] [--subject-prefix=<subject prefix>]\n>       \t\t   [(--reroll-count|-v) <n>]\n>       \t\t   [--to=<email>] [--cc=<email>]\n>       \t\t   [--[no-]cover-letter] [--quiet]\n>     @@ Documentation/git-format-patch.txt: Beware that the default for 'git send-email'\n>       will want to ensure that threading is disabled for `git send-email`.\n>       \n>      ---in-reply-to=Message-Id::\n>     -+--in-reply-to=<Message-Id>::\n>     ++--in-reply-to=<message id>::\n>       \tMake the first mail (or all the mails with `--no-thread`) appear as a\n>     - \treply to the given Message-Id, which avoids breaking threads to\n>     +-\treply to the given Message-Id, which avoids breaking threads to\n>     ++\treply to the given <message id>, which avoids breaking threads to\n>       \tprovide a new patch series.\n>     + \n>     + --ignore-if-in-upstream::\n>     +@@ Documentation/git-format-patch.txt: will want to ensure that threading is disabled for `git send-email`.\n>     + \tpatches being generated, and any patch that matches is\n>     + \tignored.\n>     + \n>     +---subject-prefix=<Subject-Prefix>::\n>     ++--subject-prefix=<subject prefix>::\n>     + \tInstead of the standard '[PATCH]' prefix in the subject\n>     +-\tline, instead use '[<Subject-Prefix>]'. This\n>     ++\tline, instead use '[<subject prefix>]'. This\n>     + \tallows for useful naming of a patch series, and can be\n>     + \tcombined with the `--numbered` option.\n>     + \n>      @@ Documentation/git-format-patch.txt: you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n>       --base=<commit>::\n>       \tRecord the base tree information to identify the state the\n> 13:  7c8522abf2 <  -:  ---------- config/format.txt: specify default value of format.coverLetter\n>  -:  ---------- > 13:  4e429e1989 config/format.txt: specify default value of format.coverLetter\n> -- \n> 2.23.0.248.g3a9dd8fb08\n> \n"},{"id":"381909","messageId":"xmqqef0uplex.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"20190904112105.GA27933@archbookpro.localdomain","subject":"Re: [PATCH v2 00/13] format-patch: clean up tests and documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-09-05T19:56:06Z","receivedAt":"2019-09-05T19:56:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Hi Junio,\n>\n> I see that \"dl/format-patch-doc-test-cleanup\" currently has the comment\n> \"Expecting a reroll.\" This should be the reroll that you're expecting ;)\n>\n> Also, since there haven't been any comments on the topic in a while, I\n> propose that it should be ready for inclusion.\n\nI may be the only person who had issues applying that series from\nthe list, with mixtures of iso-8859-1 and utf-8 causing troubles,\nbut if I am not alone, I suspect that the reason why nobody gave a\ncomment is because the patches did not even apply so there is\nnothing to base their comments on.\n\nI wiggled them and compared the result.  The range diff against what\nhas been queued seems a bit different from what you gave below\n(e.g. I see log message got modified on patch #2 and the dropping of\nthe comma made it harder to read), but the endpoint diff looks not\ntoo bad (IOW, the alloted time for the topic ran out before I\nstarted looking at each individual patches in more depth).\n\n\n\n"},{"id":"381918","messageId":"20190905213933.GA62578@dentonliu-ltm.internal.salesforce.com","threadId":"51687","inReplyTo":"xmqqef0uplex.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v2 00/13] format-patch: clean up tests and documentation","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-09-05T21:40:25Z","receivedAt":"2019-09-05T21:40:29Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Thu, Sep 05, 2019 at 12:56:06PM -0700, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> > Hi Junio,\n> >\n> > I see that \"dl/format-patch-doc-test-cleanup\" currently has the comment\n> > \"Expecting a reroll.\" This should be the reroll that you're expecting ;)\n> >\n> > Also, since there haven't been any comments on the topic in a while, I\n> > propose that it should be ready for inclusion.\n> \n> I may be the only person who had issues applying that series from\n> the list, with mixtures of iso-8859-1 and utf-8 causing troubles,\n> but if I am not alone, I suspect that the reason why nobody gave a\n> comment is because the patches did not even apply so there is\n> nothing to base their comments on.\n\nWhich patches weren't applying properly? I managed to apply both the\npatchset I had locally and a fresh one I downloaded from public-inbox\nand both applied cleanly.\n\n> \n> I wiggled them and compared the result.  The range diff against what\n> has been queued seems a bit different from what you gave below\n> (e.g. I see log message got modified on patch #2 and the dropping of\n> the comma made it harder to read), but the endpoint diff looks not\n> too bad (IOW, the alloted time for the topic ran out before I\n> started looking at each individual patches in more depth).\n\nHmmm, I don't think my workflow uses your topic branches properly. I've\nbeen range-diffing against the previously submitted patchsets but it\nseems like you expect a range-diff against the actual topic branch.\n\nWhat should the ideal workflow be? I've been avoiding working directly\nfrom the topic branch since that would require me to manually remove\nyour SOB line whenever I generate new patchsets. I guess I could\nmanually remove your SOB line from each patch manually. I dunno. Any\nideas?\n\nThanks,\n\nDenton\n"},{"id":"383920","messageId":"cover.1570821015.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1566285151.git.liu.denton@gmail.com","subject":"[PATCH v4 0/3] format-patch: learn --cover-from-description option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-11T19:12:49Z","receivedAt":"2019-10-11T19:12:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi all, since 'dl/format-patch-doc-test-cleanup' has calmed down and\nmerged into 'master', I think now's a good time to revive this topic.\nI've incorporated Philip's --cover-letter-from-description idea (and\nshortened it so it's not so verbose) so now it should be a lot more\ngeneral than the old --infer-cover-subject.\n\nCurrently, format-patch only puts \"*** SUBJECT HERE ***\" when a cover\nletter is generated. However, it is already smart enough to be able to\npopulate the cover letter with the branch description so there's no\nreason why it cannot populate the subject as well.\n\nTeach format-patch the `--cover-from-description` option and\ncorresponding `format.coverFromDescripion` configuration option which\nwill allow it to populate not only the body but the subject as well.\n\nChanges since v3:\n\n* Change --infer-cover-subject to --cover-from-description\n\n* No more test cleanup patches (they were merged in\n  'dl/format-patch-doc-test-cleanup')\n\nChanges since v2:\n\n* Break 1/4 into many different patches (one per paragraph of the\n  original patch)\n\n* Incorporate Eric's documentation/commit message suggestions\n\nChanges since v1:\n\n* Incorporate Eric's suggestions for cleanup in all patches\n\n* Add patch 3/4 to make it clear what is the default value for\n  format.coverLetter (since format.inferCoverSubject was borrowed from\n  this config but it also did not state what the default value was)\n\n* In 1/4, rename all instances of \"expected\" to \"expect\"\n\n\nDenton Liu (3):\n  format-patch: remove erroneous and condition\n  format-patch: use enum variables\n  format-patch: teach --cover-from-description option\n\n Documentation/config/format.txt    |   6 +\n Documentation/git-format-patch.txt |  22 ++++\n builtin/log.c                      | 114 +++++++++++++------\n t/t4014-format-patch.sh            | 172 +++++++++++++++++++++++++++++\n 4 files changed, 280 insertions(+), 34 deletions(-)\n\n-- \n2.23.0.17.g7cce04acd6.dirty\n\n"},{"id":"383921","messageId":"5fa7cbbd7a68eae76347b90371201e20cba1c381.1570821015.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1570821015.git.liu.denton@gmail.com","subject":"[PATCH v4 1/3] format-patch: remove erroneous and condition","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-11T19:12:52Z","receivedAt":"2019-10-11T19:12:56Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Commit 30984ed2e9 (format-patch: support deep threading, 2009-02-19),\nintroduced the following lines:\n\n\t#define THREAD_SHALLOW 1\n\n\t[...]\n\n\tthread = git_config_bool(var, value) && THREAD_SHALLOW;\n\nSince git_config_bool() returns a bool, the trailing `&& THREAD_SHALLOW`\nis a no-op. Remove this erroneous and condition.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n builtin/log.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 44b10b3415..7d658cecef 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -835,7 +835,7 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\t\tthread = THREAD_SHALLOW;\n \t\t\treturn 0;\n \t\t}\n-\t\tthread = git_config_bool(var, value) && THREAD_SHALLOW;\n+\t\tthread = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n \tif (!strcmp(var, \"format.signoff\")) {\n-- \n2.23.0.17.g7cce04acd6.dirty\n\n"},{"id":"383922","messageId":"19ee1f71493fa584991f530e952d9198880208eb.1570821015.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1570821015.git.liu.denton@gmail.com","subject":"[PATCH v4 2/3] format-patch: use enum variables","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-11T19:12:54Z","receivedAt":"2019-10-11T19:12:59Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, `thread` and `config_cover_letter` were defined as ints even\nthough they behaved as enums. Define actual enums and change these\nvariables to use these new definitions.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n builtin/log.c | 30 +++++++++++++++++-------------\n 1 file changed, 17 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 7d658cecef..f06f5d586b 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -764,24 +764,28 @@ static void add_header(const char *value)\n \titem->string[len] = '\\0';\n }\n \n-#define THREAD_SHALLOW 1\n-#define THREAD_DEEP 2\n-static int thread;\n+enum cover_setting {\n+\tCOVER_UNSET,\n+\tCOVER_OFF,\n+\tCOVER_ON,\n+\tCOVER_AUTO\n+};\n+\n+enum thread_level {\n+\tTHREAD_UNSET,\n+\tTHREAD_SHALLOW,\n+\tTHREAD_DEEP\n+};\n+\n+static enum thread_level thread;\n static int do_signoff;\n static int base_auto;\n static char *from;\n static const char *signature = git_version_string;\n static const char *signature_file;\n-static int config_cover_letter;\n+static enum cover_setting config_cover_letter;\n static const char *config_output_directory;\n \n-enum {\n-\tCOVER_UNSET,\n-\tCOVER_OFF,\n-\tCOVER_ON,\n-\tCOVER_AUTO\n-};\n-\n static int git_format_config(const char *var, const char *value, void *cb)\n {\n \tstruct rev_info *rev = cb;\n@@ -1248,9 +1252,9 @@ static int output_directory_callback(const struct option *opt, const char *arg,\n \n static int thread_callback(const struct option *opt, const char *arg, int unset)\n {\n-\tint *thread = (int *)opt->value;\n+\tenum thread_level *thread = (enum thread_level *)opt->value;\n \tif (unset)\n-\t\t*thread = 0;\n+\t\t*thread = THREAD_UNSET;\n \telse if (!arg || !strcmp(arg, \"shallow\"))\n \t\t*thread = THREAD_SHALLOW;\n \telse if (!strcmp(arg, \"deep\"))\n-- \n2.23.0.17.g7cce04acd6.dirty\n\n"},{"id":"383923","messageId":"9b8c3dcb539054ba483fc34c6ff509e4ca73517c.1570821015.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1570821015.git.liu.denton@gmail.com","subject":"[PATCH v4 3/3] format-patch: teach --cover-from-description option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-11T19:12:56Z","receivedAt":"2019-10-11T19:13:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, when format-patch generated a cover letter, only the body would\nbe populated with a branch's description while the subject would be\npopulated with placeholder text. However, users may want to have the\nsubject of their cover letter automatically populated in the same way.\n\nTeach format-patch to accept the `--cover-from-description` option and\ncorresponding `format.coverFromDescription` config, allowing users to\npopulate different parts of the cover letter (including the subject\nnow).\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt    |   6 +\n Documentation/git-format-patch.txt |  22 ++++\n builtin/log.c                      |  84 ++++++++++----\n t/t4014-format-patch.sh            | 172 +++++++++++++++++++++++++++++\n 4 files changed, 263 insertions(+), 21 deletions(-)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex cb629fa769..735dfcf827 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -36,6 +36,12 @@ format.subjectPrefix::\n \tThe default for format-patch is to output files with the '[PATCH]'\n \tsubject prefix. Use this variable to change that prefix.\n \n+format.coverFromDescription::\n+\tThe default mode for format-patch to determine which parts of\n+\tthe cover letter will be populated using the branch's\n+\tdescription. See the `--cover-from-description` option in\n+\tlinkgit:git-format-patch[1].\n+\n format.signature::\n \tThe default for format-patch is to output a signature containing\n \tthe Git version number. Use this variable to change that default.\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 0ac56f4b70..86114e4c22 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -19,6 +19,7 @@ SYNOPSIS\n \t\t   [--start-number <n>] [--numbered-files]\n \t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n+\t\t   [--cover-from-description=<mode>]\n \t\t   [--rfc] [--subject-prefix=<subject prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n@@ -171,6 +172,26 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n+--cover-from-description=<mode>::\n+\tControls which parts of the cover letter will be automatically\n+\tpopulated using the branch's description.\n++\n+If `<mode>` is `message` or `default`, the cover letter subject will be\n+populated with placeholder text. The body of the cover letter will be\n+populated with the branch's description.\n++\n+If `<mode>` is `subject`, the beginning of the branch description (up to\n+the first blank line) will populate the cover letter subject. The\n+remainder of the description will populate the body of the cover\n+letter.\n++\n+If `<mode>` is `auto`, if the beginning of the branch description (up to\n+the first line) is greater than 100 characters then the mode will be\n+`message`, otherwise `subject` will be used.\n++\n+If `<mode>` is `none`, both the cover letter subject and body will be\n+populated with placeholder text.\n+\n --subject-prefix=<subject prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n \tline, instead use '[<subject prefix>]'. This\n@@ -347,6 +368,7 @@ with configuration variables.\n \tsignOff = true\n \toutputDirectory = <directory>\n \tcoverLetter = auto\n+\tinferCoverSubject = true\n ------------\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex f06f5d586b..0cc8b59991 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -37,6 +37,7 @@\n #include \"range-diff.h\"\n \n #define MAIL_DEFAULT_WRAP 72\n+#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100\n \n /* Set a default date-time format for git log (\"log.date\" config variable) */\n static const char *default_date_mode = NULL;\n@@ -777,6 +778,13 @@ enum thread_level {\n \tTHREAD_DEEP\n };\n \n+enum cover_from_description {\n+\tCOVER_FROM_NONE,\n+\tCOVER_FROM_MESSAGE,\n+\tCOVER_FROM_SUBJECT,\n+\tCOVER_FROM_AUTO\n+};\n+\n static enum thread_level thread;\n static int do_signoff;\n static int base_auto;\n@@ -785,6 +793,23 @@ static const char *signature = git_version_string;\n static const char *signature_file;\n static enum cover_setting config_cover_letter;\n static const char *config_output_directory;\n+static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;\n+\n+static enum cover_from_description parse_cover_from_description(const char *arg)\n+{\n+\tif (!arg || !strcmp(arg, \"default\"))\n+\t\treturn COVER_FROM_MESSAGE;\n+\telse if (!strcmp(arg, \"none\"))\n+\t\treturn COVER_FROM_NONE;\n+\telse if (!strcmp(arg, \"message\"))\n+\t\treturn COVER_FROM_MESSAGE;\n+\telse if (!strcmp(arg, \"subject\"))\n+\t\treturn COVER_FROM_SUBJECT;\n+\telse if (!strcmp(arg, \"auto\"))\n+\t\treturn COVER_FROM_AUTO;\n+\telse\n+\t\tdie(_(\"%s: invalid cover from description mode\"), arg);\n+}\n \n static int git_format_config(const char *var, const char *value, void *cb)\n {\n@@ -891,6 +916,10 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\t}\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"format.coverfromdescription\")) {\n+\t\tcover_from_description_mode = parse_cover_from_description(value);\n+\t\treturn 0;\n+\t}\n \n \treturn git_log_config(var, value, cb);\n }\n@@ -997,20 +1026,6 @@ static void print_signature(FILE *file)\n \tputc('\\n', file);\n }\n \n-static void add_branch_description(struct strbuf *buf, const char *branch_name)\n-{\n-\tstruct strbuf desc = STRBUF_INIT;\n-\tif (!branch_name || !*branch_name)\n-\t\treturn;\n-\tread_branch_desc(&desc, branch_name);\n-\tif (desc.len) {\n-\t\tstrbuf_addch(buf, '\\n');\n-\t\tstrbuf_addbuf(buf, &desc);\n-\t\tstrbuf_addch(buf, '\\n');\n-\t}\n-\tstrbuf_release(&desc);\n-}\n-\n static char *find_branch_name(struct rev_info *rev)\n {\n \tint i, positive = -1;\n@@ -1061,13 +1076,16 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t      struct commit *origin,\n \t\t\t      int nr, struct commit **list,\n \t\t\t      const char *branch_name,\n+\t\t\t      enum cover_from_description cover_from_description_mode,\n \t\t\t      int quiet)\n {\n \tconst char *committer;\n-\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n-\tconst char *msg;\n+\tconst char *subject = \"*** SUBJECT HERE ***\";\n+\tconst char *body = \"*** BLURB HERE ***\";\n \tstruct shortlog log;\n \tstruct strbuf sb = STRBUF_INIT;\n+\tstruct strbuf description_sb = STRBUF_INIT;\n+\tstruct strbuf subject_sb = STRBUF_INIT;\n \tint i;\n \tconst char *encoding = \"UTF-8\";\n \tint need_8bit_cte = 0;\n@@ -1095,17 +1113,34 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (!branch_name)\n \t\tbranch_name = find_branch_name(rev);\n \n-\tmsg = body;\n+\tif (branch_name && *branch_name)\n+\t\tread_branch_desc(&description_sb, branch_name);\n+\n+\tif (cover_from_description_mode != COVER_FROM_NONE && description_sb.len) {\n+\t\tif (cover_from_description_mode == COVER_FROM_SUBJECT ||\n+\t\t\t\tcover_from_description_mode == COVER_FROM_AUTO)\n+\t\t\tbody = format_subject(&subject_sb, description_sb.buf, \" \");\n+\n+\t\tif (cover_from_description_mode == COVER_FROM_MESSAGE ||\n+\t\t\t\t(cover_from_description_mode == COVER_FROM_AUTO &&\n+\t\t\t\t subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))\n+\t\t\tbody = description_sb.buf;\n+\t\telse\n+\t\t\tsubject = subject_sb.buf;\n+\t}\n+\n \tpp.fmt = CMIT_FMT_EMAIL;\n \tpp.date_mode.type = DATE_RFC2822;\n \tpp.rev = rev;\n \tpp.print_email_subject = 1;\n \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n-\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n-\tpp_remainder(&pp, &msg, &sb, 0);\n-\tadd_branch_description(&sb, branch_name);\n+\tpp_title_line(&pp, &subject, &sb, encoding, need_8bit_cte);\n+\tpp_remainder(&pp, &body, &sb, 0);\n+\tstrbuf_addch(&sb, '\\n');\n \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n \n+\tstrbuf_release(&description_sb);\n+\tstrbuf_release(&subject_sb);\n \tstrbuf_release(&sb);\n \n \tshortlog_init(&log);\n@@ -1545,6 +1580,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tint use_patch_format = 0;\n \tint quiet = 0;\n \tint reroll_count = -1;\n+\tchar *cover_from_description_arg = NULL;\n \tchar *branch_name = NULL;\n \tchar *base_commit = NULL;\n \tstruct base_tree_info bases;\n@@ -1581,6 +1617,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t{ OPTION_CALLBACK, 0, \"rfc\", &rev, NULL,\n \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n+\t\tOPT_STRING(0, \"cover-from-description\", &cover_from_description_arg,\n+\t\t\t    N_(\"cover-from-description-mode\"),\n+\t\t\t    N_(\"generate parts of a cover letter based on a branch's description\")),\n \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n@@ -1672,6 +1711,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n+\tif (cover_from_description_arg)\n+\t\tcover_from_description_mode = parse_cover_from_description(cover_from_description_arg);\n+\n \tif (0 < reroll_count) {\n \t\tstruct strbuf sprefix = STRBUF_INIT;\n \t\tstrbuf_addf(&sprefix, \"%s v%d\",\n@@ -1920,7 +1962,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tif (thread)\n \t\t\tgen_message_id(&rev, \"cover\");\n \t\tmake_cover_letter(&rev, use_stdout,\n-\t\t\t\t  origin, nr, list, branch_name, quiet);\n+\t\t\t\t  origin, nr, list, branch_name, cover_from_description_mode, quiet);\n \t\tprint_bases(&bases, rev.diffopt.file);\n \t\tprint_signature(rev.diffopt.file);\n \t\ttotal++;\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 72b09896cf..88db01308a 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1517,6 +1517,178 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cover letter with invalid --cover-from-description and config' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_must_fail git format-patch --cover-letter --cover-from-description garbage master &&\n+\ttest_config format.coverFromDescription garbage &&\n+\ttest_must_fail git format-patch --cover-letter master\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = default' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription default &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description default' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description default master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = none' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription none &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\t! grep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description none' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description none master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\t! grep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = message' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription message &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description message' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description message master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = subject' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription subject &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description subject' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription auto &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description auto master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '\n+\ttest_config branch.rebuild-1.description \"this is a really long first line and it is over 100 characters long which is the threshold for long subjects\n+\n+body\" &&\n+\ttest_config format.coverFromDescription auto &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '\n+\ttest_config branch.rebuild-1.description \"this is a really long first line and it is over 100 characters long which is the threshold for long subjects\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description auto master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line --cover-from-description overrides config' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription none &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\n-- \n2.23.0.17.g7cce04acd6.dirty\n\n"},{"id":"383924","messageId":"d3d07c31a7c5d4db0b3efd1e7fa074966399254b.1570821731.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1570821015.git.liu.denton@gmail.com","subject":"[PATCH v4 4/3] fixup! format-patch: teach --cover-from-description option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-11T19:23:07Z","receivedAt":"2019-10-11T19:24:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Signed-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-format-patch.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 86114e4c22..4c652c97f5 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -368,7 +368,7 @@ with configuration variables.\n \tsignOff = true\n \toutputDirectory = <directory>\n \tcoverLetter = auto\n-\tinferCoverSubject = true\n+\tcoverFromDescription = auto\n ------------\n \n \n-- \n2.23.0.746.g72fc0fc0b9\n\n"},{"id":"383963","messageId":"xmqqk19aemi2.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"19ee1f71493fa584991f530e952d9198880208eb.1570821015.git.liu.denton@gmail.com","subject":"Re: [PATCH v4 2/3] format-patch: use enum variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-10-12T02:16:53Z","receivedAt":"2019-10-12T02:17:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> -#define THREAD_SHALLOW 1\n> -#define THREAD_DEEP 2\n> -static int thread;\n> +enum thread_level {\n> +\tTHREAD_UNSET,\n> +\tTHREAD_SHALLOW,\n> +\tTHREAD_DEEP\n> +};\n> +static enum thread_level thread;\n\nAs the assignment of values do not change, this is a safe conversion\neven if an existing code did things like\n\n\tif (!thread)\n        \t... do this ...;\n\nHopefully nobody did arithmetic on it; thread_level may now become\nunsigned depending on the compiler.\n\n> -static int config_cover_letter;\n> +static enum cover_setting config_cover_letter;\n\nLikewise about the signedness.\n\n"},{"id":"383964","messageId":"xmqqd0f2elli.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"9b8c3dcb539054ba483fc34c6ff509e4ca73517c.1570821015.git.liu.denton@gmail.com","subject":"Re: [PATCH v4 3/3] format-patch: teach --cover-from-description option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-10-12T02:36:25Z","receivedAt":"2019-10-12T02:36:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> +format.coverFromDescription::\n> +\tThe default mode for format-patch to determine which parts of\n> +\tthe cover letter will be populated using the branch's\n> +\tdescription. See the `--cover-from-description` option in\n> +\tlinkgit:git-format-patch[1].\n> +\n>  format.signature::\n>  \tThe default for format-patch is to output a signature containing\n>  \tthe Git version number. Use this variable to change that default.\n> diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\n> index 0ac56f4b70..86114e4c22 100644\n> --- a/Documentation/git-format-patch.txt\n> +++ b/Documentation/git-format-patch.txt\n> @@ -19,6 +19,7 @@ SYNOPSIS\n>  \t\t   [--start-number <n>] [--numbered-files]\n>  \t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n>  \t\t   [--ignore-if-in-upstream]\n> +\t\t   [--cover-from-description=<mode>]\n>  \t\t   [--rfc] [--subject-prefix=<subject prefix>]\n>  \t\t   [(--reroll-count|-v) <n>]\n>  \t\t   [--to=<email>] [--cc=<email>]\n> @@ -171,6 +172,26 @@ will want to ensure that threading is disabled for `git send-email`.\n>  \tpatches being generated, and any patch that matches is\n>  \tignored.\n>  \n> +--cover-from-description=<mode>::\n> +\tControls which parts of the cover letter will be automatically\n> +\tpopulated using the branch's description.\n> ++\n> +If `<mode>` is `message` or `default`, the cover letter subject will be\n> +populated with placeholder text. The body of the cover letter will be\n> +populated with the branch's description.\n\nI understand that this is what we do now, so those who want to live\nin the past can set the configuration variable to 'message'.\n\n> +If `<mode>` is `subject`, the beginning of the branch description (up to\n> +the first blank line) will populate the cover letter subject. The\n> +remainder of the description will populate the body of the cover\n> +letter.\n\ns/the beginning of .*blank line)/the first paragraph of the branch description/\nmay be shorter, but the above is OK, too.\n\nWhen description is prepared appropriately, this mode would fill\nboth subject and body, which sounds sensible.\n\n> +If `<mode>` is `auto`, if the beginning of the branch description (up to\n> +the first line) is greater than 100 characters then the mode will be\n> +`message`, otherwise `subject` will be used.\n\nI understand that this is a more clever and safer variant of\n'subject'.  Do you want to say 100 characters or 100 bytes?\n\n> +If `<mode>` is `none`, both the cover letter subject and body will be\n> +populated with placeholder text.\n\nOK, this is done for completeness?  I wonder who finds it useful to\nset it to 'none' *AND* set the branch description.  Not a rhetorical\nquestion that suggests removing this choice, but purely soliciting\nopinions from others.\n\nIt is unclear (other than the mode word being 'default' for one of\nthe choices) what the new default mode of operation is after the\npatch is applied among the four presented mode.  \"This is the\ndefault when no configuration nor command line option specifies the\ndesired mode\" or something may want to be added to one of these\nparagraphs.\n\n> @@ -1061,13 +1076,16 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \t\t\t      struct commit *origin,\n>  \t\t\t      int nr, struct commit **list,\n>  \t\t\t      const char *branch_name,\n> +\t\t\t      enum cover_from_description cover_from_description_mode,\n>  \t\t\t      int quiet)\n>  {\n>  \tconst char *committer;\n> -\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n> -\tconst char *msg;\n> +\tconst char *subject = \"*** SUBJECT HERE ***\";\n> +\tconst char *body = \"*** BLURB HERE ***\";\n>  \tstruct shortlog log;\n>  \tstruct strbuf sb = STRBUF_INIT;\n> +\tstruct strbuf description_sb = STRBUF_INIT;\n> +\tstruct strbuf subject_sb = STRBUF_INIT;\n>  \tint i;\n>  \tconst char *encoding = \"UTF-8\";\n>  \tint need_8bit_cte = 0;\n> @@ -1095,17 +1113,34 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \tif (!branch_name)\n>  \t\tbranch_name = find_branch_name(rev);\n>  \n> -\tmsg = body;\n> +\tif (branch_name && *branch_name)\n> +\t\tread_branch_desc(&description_sb, branch_name);\n\nIt may not matter in practice but strictly speaking there is no need\nto read the description if we know that the mode is NONE.  Removing\nthe support for the NONE mode may be an easier fix than adding \"&&\nmode != NONE\" to the if () condition guarding this call---I dunno.\n\n> +\tif (cover_from_description_mode != COVER_FROM_NONE && description_sb.len) {\n> +\t\tif (cover_from_description_mode == COVER_FROM_SUBJECT ||\n> +\t\t\t\tcover_from_description_mode == COVER_FROM_AUTO)\n> +\t\t\tbody = format_subject(&subject_sb, description_sb.buf, \" \");\n> +\n> +\t\tif (cover_from_description_mode == COVER_FROM_MESSAGE ||\n> +\t\t\t\t(cover_from_description_mode == COVER_FROM_AUTO &&\n> +\t\t\t\t subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))\n> +\t\t\tbody = description_sb.buf;\n> +\t\telse\n> +\t\t\tsubject = subject_sb.buf;\n> +\t}\n\nI wonder if it make the end result cleaner and easier to follow to\nreplace all of the above with a single line:\n\n\tcover_from_desc(&subject, &body, branch_name, desc_mode);\n\nin this caller, and move the logic (and a handful of strbuf used as\nits implementation detail) into the helper function, including the\nchoice of the default \"*** SOMETHING HERE ***\", etc., and make the\nhelper *always* return allocated piece of memory in subject and body\nso that this caller can unconditionally free them.\n\nThanks.\n"},{"id":"383965","messageId":"xmqq8spqeguz.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"cover.1570821015.git.liu.denton@gmail.com","subject":"Re: [PATCH v4 0/3] format-patch: learn --cover-from-description option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-10-12T04:18:44Z","receivedAt":"2019-10-12T04:18:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Changes since v3:\n>\n> * Change --infer-cover-subject to --cover-from-description\n>\n> * No more test cleanup patches (they were merged in\n>   'dl/format-patch-doc-test-cleanup')\n\nWith these patches, t4013 and t9902 seem to break, when queued on\ntop of dl/format-patch-doc-test-cleanup and also when merged to\n'pu'.\n\nThanks.\n"},{"id":"384036","messageId":"cover.1571085952.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1570821015.git.liu.denton@gmail.com","subject":"[PATCH v5 0/3] format-patch: learn --cover-from-description option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-14T20:46:55Z","receivedAt":"2019-10-14T20:47:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, format-patch only puts \"*** SUBJECT HERE ***\" when a cover\nletter is generated. However, it is already smart enough to be able to\npopulate the cover letter with the branch description so there's no\nreason why it cannot populate the subject as well.\n\nTeach format-patch the `--cover-from-description` option and\ncorresponding `format.coverFromDescription` configuration option which\nwill allow it to populate not only the body but the subject as well.\n\nChanges since v4:\n\n* Modify 1/3 to more closely reflect intent of the original author\n\n* Incorporate Junio's suggestions into the documentation\n\n* Extract branch desc logic into pp_from_desc()\n\n* Fix broken tests\n\nChanges since v3:\n\n* Change --infer-cover-subject to --cover-from-description\n\n* No more test cleanup patches (they were merged in\n  'dl/format-patch-doc-test-cleanup')\n\nChanges since v2:\n\n* Break 1/4 into many different patches (one per paragraph of the\n  original patch)\n\n* Incorporate Eric's documentation/commit message suggestions\n\nChanges since v1:\n\n* Incorporate Eric's suggestions for cleanup in all patches\n\n* Add patch 3/4 to make it clear what is the default value for\n  format.coverLetter (since format.inferCoverSubject was borrowed from\n  this config but it also did not state what the default value was)\n\n* In 1/4, rename all instances of \"expected\" to \"expect\"\n\nDenton Liu (3):\n  format-patch: change erroneous and condition\n  format-patch: use enum variables\n  format-patch: teach --cover-from-description option\n\n Documentation/config/format.txt    |   6 +\n Documentation/git-format-patch.txt |  22 ++++\n builtin/log.c                      | 125 +++++++++++++++------\n t/t4014-format-patch.sh            | 172 +++++++++++++++++++++++++++++\n t/t9902-completion.sh              |   5 +-\n 5 files changed, 296 insertions(+), 34 deletions(-)\n\nRange-diff against v4:\n1:  267bc00dc8 ! 1:  56fb230ad2 format-patch: remove erroneous and condition\n    @@ Metadata\n     Author: Denton Liu <liu.denton@gmail.com>\n     \n      ## Commit message ##\n    -    format-patch: remove erroneous and condition\n    +    format-patch: change erroneous and condition\n     \n         Commit 30984ed2e9 (format-patch: support deep threading, 2009-02-19),\n         introduced the following lines:\n    @@ Commit message\n                 thread = git_config_bool(var, value) && THREAD_SHALLOW;\n     \n         Since git_config_bool() returns a bool, the trailing `&& THREAD_SHALLOW`\n    -    is a no-op. Remove this erroneous and condition.\n    +    is a no-op.\n    +\n    +    In Python, `x and y` is equivalent to `y if x else x`[1]. Since this\n    +    seems to be a Python-ism that's mistakenly leaked into our code, convert\n    +    this to the equivalent C expression.\n    +\n    +    [1]: https://docs.python.org/3/reference/expressions.html#boolean-operations\n     \n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     \n      ## builtin/log.c ##\n     @@ builtin/log.c: static int git_format_config(const char *var, const char *value, void *cb)\n    @@ builtin/log.c: static int git_format_config(const char *var, const char *value,\n      \t\t\treturn 0;\n      \t\t}\n     -\t\tthread = git_config_bool(var, value) && THREAD_SHALLOW;\n    -+\t\tthread = git_config_bool(var, value);\n    ++\t\tthread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;\n      \t\treturn 0;\n      \t}\n      \tif (!strcmp(var, \"format.signoff\")) {\n2:  638a5b40d2 ! 2:  e2769092fa format-patch: use enum variables\n    @@ Commit message\n         variables to use these new definitions.\n     \n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     \n      ## builtin/log.c ##\n     @@ builtin/log.c: static void add_header(const char *value)\n3:  3289ce62bb ! 3:  315c308950 format-patch: teach --cover-from-description option\n    @@ Commit message\n         populate different parts of the cover letter (including the subject\n         now).\n     \n    -    Signed-off-by: Denton Liu <liu.denton@gmail.com>\n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n    -\n      ## Documentation/config/format.txt ##\n     @@ Documentation/config/format.txt: format.subjectPrefix::\n      \tThe default for format-patch is to output files with the '[PATCH]'\n    @@ Documentation/git-format-patch.txt: will want to ensure that threading is disabl\n     ++\n     +If `<mode>` is `message` or `default`, the cover letter subject will be\n     +populated with placeholder text. The body of the cover letter will be\n    -+populated with the branch's description.\n    ++populated with the branch's description. This is the default mode when\n    ++no configuration nor command line option is specified.\n     ++\n    -+If `<mode>` is `subject`, the beginning of the branch description (up to\n    -+the first blank line) will populate the cover letter subject. The\n    -+remainder of the description will populate the body of the cover\n    -+letter.\n    ++If `<mode>` is `subject`, the first paragraph of the branch description will\n    ++populate the cover letter subject. The remainder of the description will\n    ++populate the body of the cover letter.\n     ++\n    -+If `<mode>` is `auto`, if the beginning of the branch description (up to\n    -+the first line) is greater than 100 characters then the mode will be\n    -+`message`, otherwise `subject` will be used.\n    ++If `<mode>` is `auto`, if the first paragraph of the branch description\n    ++is greater than 100 bytes, then the mode will be `message`, otherwise\n    ++`subject` will be used.\n     ++\n     +If `<mode>` is `none`, both the cover letter subject and body will be\n     +populated with placeholder text.\n    @@ builtin/log.c: static void print_signature(FILE *file)\n      static char *find_branch_name(struct rev_info *rev)\n      {\n      \tint i, positive = -1;\n    -@@ builtin/log.c: static void make_cover_letter(struct rev_info *rev, int use_stdout,\n    +@@ builtin/log.c: static void show_diffstat(struct rev_info *rev,\n    + \tfprintf(rev->diffopt.file, \"\\n\");\n    + }\n    + \n    ++static void pp_from_desc(struct pretty_print_context *pp,\n    ++\t\t\t const char *branch_name,\n    ++\t\t\t struct strbuf *sb,\n    ++\t\t\t const char *encoding,\n    ++\t\t\t int need_8bit_cte)\n    ++{\n    ++\tconst char *subject = \"*** SUBJECT HERE ***\";\n    ++\tconst char *body = \"*** BLURB HERE ***\";\n    ++\tstruct strbuf description_sb = STRBUF_INIT;\n    ++\tstruct strbuf subject_sb = STRBUF_INIT;\n    ++\n    ++\tif (cover_from_description_mode == COVER_FROM_NONE)\n    ++\t\tgoto do_pp;\n    ++\n    ++\tif (branch_name && *branch_name)\n    ++\t\tread_branch_desc(&description_sb, branch_name);\n    ++\tif (!description_sb.len)\n    ++\t\tgoto do_pp;\n    ++\n    ++\tif (cover_from_description_mode == COVER_FROM_SUBJECT ||\n    ++\t\t\tcover_from_description_mode == COVER_FROM_AUTO)\n    ++\t\tbody = format_subject(&subject_sb, description_sb.buf, \" \");\n    ++\n    ++\tif (cover_from_description_mode == COVER_FROM_MESSAGE ||\n    ++\t\t\t(cover_from_description_mode == COVER_FROM_AUTO &&\n    ++\t\t\t subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))\n    ++\t\tbody = description_sb.buf;\n    ++\telse\n    ++\t\tsubject = subject_sb.buf;\n    ++\n    ++do_pp:\n    ++\tpp_title_line(pp, &subject, sb, encoding, need_8bit_cte);\n    ++\tpp_remainder(pp, &body, sb, 0);\n    ++\n    ++\tstrbuf_release(&description_sb);\n    ++\tstrbuf_release(&subject_sb);\n    ++}\n    ++\n    + static void make_cover_letter(struct rev_info *rev, int use_stdout,\n      \t\t\t      struct commit *origin,\n      \t\t\t      int nr, struct commit **list,\n    - \t\t\t      const char *branch_name,\n    -+\t\t\t      enum cover_from_description cover_from_description_mode,\n    +@@ builtin/log.c: static void make_cover_letter(struct rev_info *rev, int use_stdout,\n      \t\t\t      int quiet)\n      {\n      \tconst char *committer;\n     -\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n     -\tconst char *msg;\n    -+\tconst char *subject = \"*** SUBJECT HERE ***\";\n    -+\tconst char *body = \"*** BLURB HERE ***\";\n      \tstruct shortlog log;\n      \tstruct strbuf sb = STRBUF_INIT;\n    -+\tstruct strbuf description_sb = STRBUF_INIT;\n    -+\tstruct strbuf subject_sb = STRBUF_INIT;\n      \tint i;\n    - \tconst char *encoding = \"UTF-8\";\n    - \tint need_8bit_cte = 0;\n     @@ builtin/log.c: static void make_cover_letter(struct rev_info *rev, int use_stdout,\n      \tif (!branch_name)\n      \t\tbranch_name = find_branch_name(rev);\n      \n     -\tmsg = body;\n    -+\tif (branch_name && *branch_name)\n    -+\t\tread_branch_desc(&description_sb, branch_name);\n    -+\n    -+\tif (cover_from_description_mode != COVER_FROM_NONE && description_sb.len) {\n    -+\t\tif (cover_from_description_mode == COVER_FROM_SUBJECT ||\n    -+\t\t\t\tcover_from_description_mode == COVER_FROM_AUTO)\n    -+\t\t\tbody = format_subject(&subject_sb, description_sb.buf, \" \");\n    -+\n    -+\t\tif (cover_from_description_mode == COVER_FROM_MESSAGE ||\n    -+\t\t\t\t(cover_from_description_mode == COVER_FROM_AUTO &&\n    -+\t\t\t\t subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))\n    -+\t\t\tbody = description_sb.buf;\n    -+\t\telse\n    -+\t\t\tsubject = subject_sb.buf;\n    -+\t}\n    -+\n      \tpp.fmt = CMIT_FMT_EMAIL;\n      \tpp.date_mode.type = DATE_RFC2822;\n      \tpp.rev = rev;\n    @@ builtin/log.c: static void make_cover_letter(struct rev_info *rev, int use_stdou\n     -\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n     -\tpp_remainder(&pp, &msg, &sb, 0);\n     -\tadd_branch_description(&sb, branch_name);\n    -+\tpp_title_line(&pp, &subject, &sb, encoding, need_8bit_cte);\n    -+\tpp_remainder(&pp, &body, &sb, 0);\n    -+\tstrbuf_addch(&sb, '\\n');\n    ++\tpp_from_desc(&pp, branch_name, &sb, encoding, need_8bit_cte);\n      \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n      \n    -+\tstrbuf_release(&description_sb);\n    -+\tstrbuf_release(&subject_sb);\n      \tstrbuf_release(&sb);\n    - \n    - \tshortlog_init(&log);\n     @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)\n      \tint use_patch_format = 0;\n      \tint quiet = 0;\n    @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *pre\n      \tif (0 < reroll_count) {\n      \t\tstruct strbuf sprefix = STRBUF_INIT;\n      \t\tstrbuf_addf(&sprefix, \"%s v%d\",\n    -@@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)\n    - \t\tif (thread)\n    - \t\t\tgen_message_id(&rev, \"cover\");\n    - \t\tmake_cover_letter(&rev, use_stdout,\n    --\t\t\t\t  origin, nr, list, branch_name, quiet);\n    -+\t\t\t\t  origin, nr, list, branch_name, cover_from_description_mode, quiet);\n    - \t\tprint_bases(&bases, rev.diffopt.file);\n    - \t\tprint_signature(rev.diffopt.file);\n    - \t\ttotal++;\n     \n      ## t/t4014-format-patch.sh ##\n     @@ t/t4014-format-patch.sh: test_expect_success 'format patch ignores color.ui' '\n    @@ t/t4014-format-patch.sh: test_expect_success 'format patch ignores color.ui' '\n      test_expect_success 'cover letter using branch description (1)' '\n      \tgit checkout rebuild-1 &&\n      \ttest_config branch.rebuild-1.description hello &&\n    +\n    + ## t/t9902-completion.sh ##\n    +@@ t/t9902-completion.sh: test_expect_success 'complete tree filename with metacharacters' '\n    + '\n    + \n    + test_expect_success PERL 'send-email' '\n    +-\ttest_completion \"git send-email --cov\" \"--cover-letter \" &&\n    ++\ttest_completion \"git send-email --cov\" <<-\\EOF &&\n    ++\t--cover-from-description=Z\n    ++\t--cover-letter Z\n    ++\tEOF\n    + \ttest_completion \"git send-email ma\" \"master \"\n    + '\n    + \n-- \n2.23.0.17.g315c308950\n\n"},{"id":"384037","messageId":"56fb230ad271dc9aa91c0f43ac8e4e7085c15775.1571085952.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1571085952.git.liu.denton@gmail.com","subject":"[PATCH v5 1/3] format-patch: change erroneous and condition","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-14T20:46:59Z","receivedAt":"2019-10-14T20:47:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Commit 30984ed2e9 (format-patch: support deep threading, 2009-02-19),\nintroduced the following lines:\n\n\t#define THREAD_SHALLOW 1\n\n\t[...]\n\n\tthread = git_config_bool(var, value) && THREAD_SHALLOW;\n\nSince git_config_bool() returns a bool, the trailing `&& THREAD_SHALLOW`\nis a no-op.\n\nIn Python, `x and y` is equivalent to `y if x else x`[1]. Since this\nseems to be a Python-ism that's mistakenly leaked into our code, convert\nthis to the equivalent C expression.\n\n[1]: https://docs.python.org/3/reference/expressions.html#boolean-operations\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n builtin/log.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 44b10b3415..351f4ffcfd 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -835,7 +835,7 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\t\tthread = THREAD_SHALLOW;\n \t\t\treturn 0;\n \t\t}\n-\t\tthread = git_config_bool(var, value) && THREAD_SHALLOW;\n+\t\tthread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;\n \t\treturn 0;\n \t}\n \tif (!strcmp(var, \"format.signoff\")) {\n-- \n2.23.0.17.g315c308950\n\n"},{"id":"384038","messageId":"e2769092fad4a6fa8830a54ffa5afe782e5fb1bf.1571085952.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1571085952.git.liu.denton@gmail.com","subject":"[PATCH v5 2/3] format-patch: use enum variables","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-14T20:47:01Z","receivedAt":"2019-10-14T20:47:06Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, `thread` and `config_cover_letter` were defined as ints even\nthough they behaved as enums. Define actual enums and change these\nvariables to use these new definitions.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\nHi Junio, I double-checked and made sure that there is no arithmetic\ndone on the new enums.\n\n builtin/log.c | 30 +++++++++++++++++-------------\n 1 file changed, 17 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 351f4ffcfd..d212a8305d 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -764,24 +764,28 @@ static void add_header(const char *value)\n \titem->string[len] = '\\0';\n }\n \n-#define THREAD_SHALLOW 1\n-#define THREAD_DEEP 2\n-static int thread;\n+enum cover_setting {\n+\tCOVER_UNSET,\n+\tCOVER_OFF,\n+\tCOVER_ON,\n+\tCOVER_AUTO\n+};\n+\n+enum thread_level {\n+\tTHREAD_UNSET,\n+\tTHREAD_SHALLOW,\n+\tTHREAD_DEEP\n+};\n+\n+static enum thread_level thread;\n static int do_signoff;\n static int base_auto;\n static char *from;\n static const char *signature = git_version_string;\n static const char *signature_file;\n-static int config_cover_letter;\n+static enum cover_setting config_cover_letter;\n static const char *config_output_directory;\n \n-enum {\n-\tCOVER_UNSET,\n-\tCOVER_OFF,\n-\tCOVER_ON,\n-\tCOVER_AUTO\n-};\n-\n static int git_format_config(const char *var, const char *value, void *cb)\n {\n \tstruct rev_info *rev = cb;\n@@ -1248,9 +1252,9 @@ static int output_directory_callback(const struct option *opt, const char *arg,\n \n static int thread_callback(const struct option *opt, const char *arg, int unset)\n {\n-\tint *thread = (int *)opt->value;\n+\tenum thread_level *thread = (enum thread_level *)opt->value;\n \tif (unset)\n-\t\t*thread = 0;\n+\t\t*thread = THREAD_UNSET;\n \telse if (!arg || !strcmp(arg, \"shallow\"))\n \t\t*thread = THREAD_SHALLOW;\n \telse if (!strcmp(arg, \"deep\"))\n-- \n2.23.0.17.g315c308950\n\n"},{"id":"384039","messageId":"315c308950270968293c92c94fdadd3be3340c33.1571085952.git.liu.denton@gmail.com","threadId":"51687","inReplyTo":"cover.1571085952.git.liu.denton@gmail.com","subject":"[PATCH v5 3/3] format-patch: teach --cover-from-description option","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-14T20:47:04Z","receivedAt":"2019-10-14T20:47:09Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, when format-patch generated a cover letter, only the body would\nbe populated with a branch's description while the subject would be\npopulated with placeholder text. However, users may want to have the\nsubject of their cover letter automatically populated in the same way.\n\nTeach format-patch to accept the `--cover-from-description` option and\ncorresponding `format.coverFromDescription` config, allowing users to\npopulate different parts of the cover letter (including the subject\nnow).\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/config/format.txt    |   6 +\n Documentation/git-format-patch.txt |  22 ++++\n builtin/log.c                      |  95 ++++++++++++----\n t/t4014-format-patch.sh            | 172 +++++++++++++++++++++++++++++\n t/t9902-completion.sh              |   5 +-\n 5 files changed, 279 insertions(+), 21 deletions(-)\n\ndiff --git a/Documentation/config/format.txt b/Documentation/config/format.txt\nindex cb629fa769..735dfcf827 100644\n--- a/Documentation/config/format.txt\n+++ b/Documentation/config/format.txt\n@@ -36,6 +36,12 @@ format.subjectPrefix::\n \tThe default for format-patch is to output files with the '[PATCH]'\n \tsubject prefix. Use this variable to change that prefix.\n \n+format.coverFromDescription::\n+\tThe default mode for format-patch to determine which parts of\n+\tthe cover letter will be populated using the branch's\n+\tdescription. See the `--cover-from-description` option in\n+\tlinkgit:git-format-patch[1].\n+\n format.signature::\n \tThe default for format-patch is to output a signature containing\n \tthe Git version number. Use this variable to change that default.\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 0ac56f4b70..6800e1ab9a 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -19,6 +19,7 @@ SYNOPSIS\n \t\t   [--start-number <n>] [--numbered-files]\n \t\t   [--in-reply-to=<message id>] [--suffix=.<sfx>]\n \t\t   [--ignore-if-in-upstream]\n+\t\t   [--cover-from-description=<mode>]\n \t\t   [--rfc] [--subject-prefix=<subject prefix>]\n \t\t   [(--reroll-count|-v) <n>]\n \t\t   [--to=<email>] [--cc=<email>]\n@@ -171,6 +172,26 @@ will want to ensure that threading is disabled for `git send-email`.\n \tpatches being generated, and any patch that matches is\n \tignored.\n \n+--cover-from-description=<mode>::\n+\tControls which parts of the cover letter will be automatically\n+\tpopulated using the branch's description.\n++\n+If `<mode>` is `message` or `default`, the cover letter subject will be\n+populated with placeholder text. The body of the cover letter will be\n+populated with the branch's description. This is the default mode when\n+no configuration nor command line option is specified.\n++\n+If `<mode>` is `subject`, the first paragraph of the branch description will\n+populate the cover letter subject. The remainder of the description will\n+populate the body of the cover letter.\n++\n+If `<mode>` is `auto`, if the first paragraph of the branch description\n+is greater than 100 bytes, then the mode will be `message`, otherwise\n+`subject` will be used.\n++\n+If `<mode>` is `none`, both the cover letter subject and body will be\n+populated with placeholder text.\n+\n --subject-prefix=<subject prefix>::\n \tInstead of the standard '[PATCH]' prefix in the subject\n \tline, instead use '[<subject prefix>]'. This\n@@ -347,6 +368,7 @@ with configuration variables.\n \tsignOff = true\n \toutputDirectory = <directory>\n \tcoverLetter = auto\n+\tcoverFromDescription = auto\n ------------\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex d212a8305d..af33fe9ffb 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -37,6 +37,7 @@\n #include \"range-diff.h\"\n \n #define MAIL_DEFAULT_WRAP 72\n+#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100\n \n /* Set a default date-time format for git log (\"log.date\" config variable) */\n static const char *default_date_mode = NULL;\n@@ -777,6 +778,13 @@ enum thread_level {\n \tTHREAD_DEEP\n };\n \n+enum cover_from_description {\n+\tCOVER_FROM_NONE,\n+\tCOVER_FROM_MESSAGE,\n+\tCOVER_FROM_SUBJECT,\n+\tCOVER_FROM_AUTO\n+};\n+\n static enum thread_level thread;\n static int do_signoff;\n static int base_auto;\n@@ -785,6 +793,23 @@ static const char *signature = git_version_string;\n static const char *signature_file;\n static enum cover_setting config_cover_letter;\n static const char *config_output_directory;\n+static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;\n+\n+static enum cover_from_description parse_cover_from_description(const char *arg)\n+{\n+\tif (!arg || !strcmp(arg, \"default\"))\n+\t\treturn COVER_FROM_MESSAGE;\n+\telse if (!strcmp(arg, \"none\"))\n+\t\treturn COVER_FROM_NONE;\n+\telse if (!strcmp(arg, \"message\"))\n+\t\treturn COVER_FROM_MESSAGE;\n+\telse if (!strcmp(arg, \"subject\"))\n+\t\treturn COVER_FROM_SUBJECT;\n+\telse if (!strcmp(arg, \"auto\"))\n+\t\treturn COVER_FROM_AUTO;\n+\telse\n+\t\tdie(_(\"%s: invalid cover from description mode\"), arg);\n+}\n \n static int git_format_config(const char *var, const char *value, void *cb)\n {\n@@ -891,6 +916,10 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\t}\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"format.coverfromdescription\")) {\n+\t\tcover_from_description_mode = parse_cover_from_description(value);\n+\t\treturn 0;\n+\t}\n \n \treturn git_log_config(var, value, cb);\n }\n@@ -997,20 +1026,6 @@ static void print_signature(FILE *file)\n \tputc('\\n', file);\n }\n \n-static void add_branch_description(struct strbuf *buf, const char *branch_name)\n-{\n-\tstruct strbuf desc = STRBUF_INIT;\n-\tif (!branch_name || !*branch_name)\n-\t\treturn;\n-\tread_branch_desc(&desc, branch_name);\n-\tif (desc.len) {\n-\t\tstrbuf_addch(buf, '\\n');\n-\t\tstrbuf_addbuf(buf, &desc);\n-\t\tstrbuf_addch(buf, '\\n');\n-\t}\n-\tstrbuf_release(&desc);\n-}\n-\n static char *find_branch_name(struct rev_info *rev)\n {\n \tint i, positive = -1;\n@@ -1057,6 +1072,44 @@ static void show_diffstat(struct rev_info *rev,\n \tfprintf(rev->diffopt.file, \"\\n\");\n }\n \n+static void pp_from_desc(struct pretty_print_context *pp,\n+\t\t\t const char *branch_name,\n+\t\t\t struct strbuf *sb,\n+\t\t\t const char *encoding,\n+\t\t\t int need_8bit_cte)\n+{\n+\tconst char *subject = \"*** SUBJECT HERE ***\";\n+\tconst char *body = \"*** BLURB HERE ***\";\n+\tstruct strbuf description_sb = STRBUF_INIT;\n+\tstruct strbuf subject_sb = STRBUF_INIT;\n+\n+\tif (cover_from_description_mode == COVER_FROM_NONE)\n+\t\tgoto do_pp;\n+\n+\tif (branch_name && *branch_name)\n+\t\tread_branch_desc(&description_sb, branch_name);\n+\tif (!description_sb.len)\n+\t\tgoto do_pp;\n+\n+\tif (cover_from_description_mode == COVER_FROM_SUBJECT ||\n+\t\t\tcover_from_description_mode == COVER_FROM_AUTO)\n+\t\tbody = format_subject(&subject_sb, description_sb.buf, \" \");\n+\n+\tif (cover_from_description_mode == COVER_FROM_MESSAGE ||\n+\t\t\t(cover_from_description_mode == COVER_FROM_AUTO &&\n+\t\t\t subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))\n+\t\tbody = description_sb.buf;\n+\telse\n+\t\tsubject = subject_sb.buf;\n+\n+do_pp:\n+\tpp_title_line(pp, &subject, sb, encoding, need_8bit_cte);\n+\tpp_remainder(pp, &body, sb, 0);\n+\n+\tstrbuf_release(&description_sb);\n+\tstrbuf_release(&subject_sb);\n+}\n+\n static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t      struct commit *origin,\n \t\t\t      int nr, struct commit **list,\n@@ -1064,8 +1117,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t      int quiet)\n {\n \tconst char *committer;\n-\tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n-\tconst char *msg;\n \tstruct shortlog log;\n \tstruct strbuf sb = STRBUF_INIT;\n \tint i;\n@@ -1095,15 +1146,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (!branch_name)\n \t\tbranch_name = find_branch_name(rev);\n \n-\tmsg = body;\n \tpp.fmt = CMIT_FMT_EMAIL;\n \tpp.date_mode.type = DATE_RFC2822;\n \tpp.rev = rev;\n \tpp.print_email_subject = 1;\n \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n-\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n-\tpp_remainder(&pp, &msg, &sb, 0);\n-\tadd_branch_description(&sb, branch_name);\n+\tpp_from_desc(&pp, branch_name, &sb, encoding, need_8bit_cte);\n \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n \n \tstrbuf_release(&sb);\n@@ -1545,6 +1593,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tint use_patch_format = 0;\n \tint quiet = 0;\n \tint reroll_count = -1;\n+\tchar *cover_from_description_arg = NULL;\n \tchar *branch_name = NULL;\n \tchar *base_commit = NULL;\n \tstruct base_tree_info bases;\n@@ -1581,6 +1630,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t{ OPTION_CALLBACK, 0, \"rfc\", &rev, NULL,\n \t\t\t    N_(\"Use [RFC PATCH] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },\n+\t\tOPT_STRING(0, \"cover-from-description\", &cover_from_description_arg,\n+\t\t\t    N_(\"cover-from-description-mode\"),\n+\t\t\t    N_(\"generate parts of a cover letter based on a branch's description\")),\n \t\t{ OPTION_CALLBACK, 0, \"subject-prefix\", &rev, N_(\"prefix\"),\n \t\t\t    N_(\"Use [<prefix>] instead of [PATCH]\"),\n \t\t\t    PARSE_OPT_NONEG, subject_prefix_callback },\n@@ -1672,6 +1724,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n+\tif (cover_from_description_arg)\n+\t\tcover_from_description_mode = parse_cover_from_description(cover_from_description_arg);\n+\n \tif (0 < reroll_count) {\n \t\tstruct strbuf sprefix = STRBUF_INIT;\n \t\tstrbuf_addf(&sprefix, \"%s v%d\",\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 72b09896cf..88db01308a 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1517,6 +1517,178 @@ test_expect_success 'format patch ignores color.ui' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'cover letter with invalid --cover-from-description and config' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_must_fail git format-patch --cover-letter --cover-from-description garbage master &&\n+\ttest_config format.coverFromDescription garbage &&\n+\ttest_must_fail git format-patch --cover-letter master\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = default' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription default &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description default' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description default master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = none' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription none &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\t! grep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description none' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description none master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\t! grep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = message' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription message &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description message' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description message master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = subject' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription subject &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description subject' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription auto &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description auto master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '\n+\ttest_config branch.rebuild-1.description \"this is a really long first line and it is over 100 characters long which is the threshold for long subjects\n+\n+body\" &&\n+\ttest_config format.coverFromDescription auto &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '\n+\ttest_config branch.rebuild-1.description \"this is a really long first line and it is over 100 characters long which is the threshold for long subjects\n+\n+body\" &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description auto master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] \\*\\*\\* SUBJECT HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\tgrep \"^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n+test_expect_success 'cover letter with command-line --cover-from-description overrides config' '\n+\ttest_config branch.rebuild-1.description \"config subject\n+\n+body\" &&\n+\ttest_config format.coverFromDescription none &&\n+\tgit checkout rebuild-1 &&\n+\tgit format-patch --stdout --cover-letter --cover-from-description subject master >actual &&\n+\tgrep \"^Subject: \\[PATCH 0/2\\] config subject$\" actual &&\n+\t! grep \"^\\*\\*\\* BLURB HERE \\*\\*\\*$\" actual &&\n+\t! grep \"^config subject$\" actual &&\n+\tgrep \"^body$\" actual\n+'\n+\n test_expect_success 'cover letter using branch description (1)' '\n \tgit checkout rebuild-1 &&\n \ttest_config branch.rebuild-1.description hello &&\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 75512c3403..5187e2ede5 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -1548,7 +1548,10 @@ test_expect_success 'complete tree filename with metacharacters' '\n '\n \n test_expect_success PERL 'send-email' '\n-\ttest_completion \"git send-email --cov\" \"--cover-letter \" &&\n+\ttest_completion \"git send-email --cov\" <<-\\EOF &&\n+\t--cover-from-description=Z\n+\t--cover-letter Z\n+\tEOF\n \ttest_completion \"git send-email ma\" \"master \"\n '\n \n-- \n2.23.0.17.g315c308950\n\n"},{"id":"384058","messageId":"xmqqeezeda7w.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"56fb230ad271dc9aa91c0f43ac8e4e7085c15775.1571085952.git.liu.denton@gmail.com","subject":"Re: [PATCH v5 1/3] format-patch: change erroneous and condition","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-10-15T02:16:35Z","receivedAt":"2019-10-15T02:16:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> .... Since this\n> seems to be a Python-ism that's mistakenly leaked into our code, convert\n\nThe conclusion is OK, but as the inventor of format-patch and a\nnon-pythonista, I do not think the above claim is correct, and even\nif Thomas thought it was a good idea to follow Python style in\n30984ed2 (\"format-patch: support deep threading\", 2009-02-19), which\nI doubt he did, I do not think there is much point in speculating.\n\nBoth the log message and the patch text in the previous round were\nbetter than this round, I would have to say.\n\nThanks.\n\n\n\n> diff --git a/builtin/log.c b/builtin/log.c\n> index 44b10b3415..351f4ffcfd 100644\n> --- a/builtin/log.c\n> +++ b/builtin/log.c\n> @@ -835,7 +835,7 @@ static int git_format_config(const char *var, const char *value, void *cb)\n>  \t\t\tthread = THREAD_SHALLOW;\n>  \t\t\treturn 0;\n>  \t\t}\n> -\t\tthread = git_config_bool(var, value) && THREAD_SHALLOW;\n> +\t\tthread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;\n>  \t\treturn 0;\n>  \t}\n>  \tif (!strcmp(var, \"format.signoff\")) {\n"},{"id":"384059","messageId":"xmqqa7a2d9su.fsf@gitster-ct.c.googlers.com","threadId":"51687","inReplyTo":"315c308950270968293c92c94fdadd3be3340c33.1571085952.git.liu.denton@gmail.com","subject":"Re: [PATCH v5 3/3] format-patch: teach --cover-from-description option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-10-15T02:25:37Z","receivedAt":"2019-10-15T02:25:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> diff --git a/builtin/log.c b/builtin/log.c\n> index d212a8305d..af33fe9ffb 100644\n> --- a/builtin/log.c\n> +++ b/builtin/log.c\n> @@ -1057,6 +1072,44 @@ static void show_diffstat(struct rev_info *rev,\n>  \tfprintf(rev->diffopt.file, \"\\n\");\n>  }\n>  \n> +static void pp_from_desc(struct pretty_print_context *pp,\n> +\t\t\t const char *branch_name,\n> +\t\t\t struct strbuf *sb,\n> +\t\t\t const char *encoding,\n> +\t\t\t int need_8bit_cte)\n> +{\n> +\tconst char *subject = \"*** SUBJECT HERE ***\";\n> +\tconst char *body = \"*** BLURB HERE ***\";\n> +\tstruct strbuf description_sb = STRBUF_INIT;\n> +\tstruct strbuf subject_sb = STRBUF_INIT;\n> +\n> +\tif (cover_from_description_mode == COVER_FROM_NONE)\n> +\t\tgoto do_pp;\n> +\n> +\tif (branch_name && *branch_name)\n> +\t\tread_branch_desc(&description_sb, branch_name);\n> +\tif (!description_sb.len)\n> +\t\tgoto do_pp;\n> +\n> +\tif (cover_from_description_mode == COVER_FROM_SUBJECT ||\n> +\t\t\tcover_from_description_mode == COVER_FROM_AUTO)\n> +\t\tbody = format_subject(&subject_sb, description_sb.buf, \" \");\n> +\n> +\tif (cover_from_description_mode == COVER_FROM_MESSAGE ||\n> +\t\t\t(cover_from_description_mode == COVER_FROM_AUTO &&\n> +\t\t\t subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))\n> +\t\tbody = description_sb.buf;\n> +\telse\n> +\t\tsubject = subject_sb.buf;\n> +\n> +do_pp:\n> +\tpp_title_line(pp, &subject, sb, encoding, need_8bit_cte);\n> +\tpp_remainder(pp, &body, sb, 0);\n> +\n> +\tstrbuf_release(&description_sb);\n> +\tstrbuf_release(&subject_sb);\n> +}\n> +\n\nThis implementation is very clear and easy to follow, and ...\n\n> @@ -1064,8 +1117,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \t\t\t      int quiet)\n>  {\n>  \tconst char *committer;\n>  \tstruct shortlog log;\n>  \tstruct strbuf sb = STRBUF_INIT;\n>  \tint i;\n> @@ -1095,15 +1146,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \tif (!branch_name)\n>  \t\tbranch_name = find_branch_name(rev);\n>  \n>  \tpp.fmt = CMIT_FMT_EMAIL;\n>  \tpp.date_mode.type = DATE_RFC2822;\n>  \tpp.rev = rev;\n>  \tpp.print_email_subject = 1;\n>  \tpp_user_info(&pp, NULL, &sb, committer, encoding);\n> +\tpp_from_desc(&pp, branch_name, &sb, encoding, need_8bit_cte);\n>  \tfprintf(rev->diffopt.file, \"%s\\n\", sb.buf);\n>  \n>  \tstrbuf_release(&sb);\n\n... made the caller much simpler.\n\nOne large nit is that pp_user_info() is about \"pretty printing the\nuser info\", pp_title_line() is about \"pretty printing the title\nline\", but pp_from_desc() is not about \"pretty printing the from\ndesc\".  Naming matters.\n\nHow about calling it with more emphasis on what it does (i.e. the\nhelper is about preparing the subject and body of the cover letter\ne-mail) and less emphasis on how it does or what it bases its\ndecision on?  prepare_cover_text() or soemthing, perhaps?\n\nOther than that, this version is very much more preferrable than the\nprevious one.  Quite nicely done.\n\nThanks.\n"},{"id":"384064","messageId":"20191015034546.GA61505@generichostname","threadId":"51687","inReplyTo":"xmqqeezeda7w.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v5 1/3] format-patch: change erroneous and condition","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-10-15T03:45:46Z","receivedAt":"2019-10-15T03:45:52Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio,\n\nThanks for the feedback.\n\nOn Tue, Oct 15, 2019 at 11:16:35AM +0900, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> > .... Since this\n> > seems to be a Python-ism that's mistakenly leaked into our code, convert\n> \n> The conclusion is OK, but as the inventor of format-patch and a\n> non-pythonista, I do not think the above claim is correct, and even\n> if Thomas thought it was a good idea to follow Python style in\n> 30984ed2 (\"format-patch: support deep threading\", 2009-02-19), which\n> I doubt he did, I do not think there is much point in speculating.\n\nI agree, I probably shouldn't be putting speculation in the log\nmessages. I'll change this for the next reroll.\n\n> \n> Both the log message and the patch text in the previous round were\n> better than this round, I would have to say.\n\nI'll probably keep the patch text, however. In the previous version, we\nwere implicitly relying on the value of THREAD_SHALLOW to be 1. This\nseems a little bit flimsy to me since it's possible that the enum can be\nchanged in the future and it may invalidate that assumption.\n\nI'll keep it explicit so that it's a little bit more robust and also, so\nthat it's more obvious to future readers what's going on.\n\nThanks,\n\nDenton\n\n> \n> Thanks.\n> \n> \n> \n> > diff --git a/builtin/log.c b/builtin/log.c\n> > index 44b10b3415..351f4ffcfd 100644\n> > --- a/builtin/log.c\n> > +++ b/builtin/log.c\n> > @@ -835,7 +835,7 @@ static int git_format_config(const char *var, const char *value, void *cb)\n> >  \t\t\tthread = THREAD_SHALLOW;\n> >  \t\t\treturn 0;\n> >  \t\t}\n> > -\t\tthread = git_config_bool(var, value) && THREAD_SHALLOW;\n> > +\t\tthread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;\n> >  \t\treturn 0;\n> >  \t}\n> >  \tif (!strcmp(var, \"format.signoff\")) {\n"}]}