{"thread":{"id":"60067","subject":"[PATCH 0/5] Fixes to trailer test script, help text, and documentation","startedAt":"2023-08-05T04:45:47Z","lastAt":"2023-11-10T06:33:33Z","messageCount":52,"participants":["Linus Arver via GitGitGadget","Junio C Hamano","Linus Arver","Jonathan Tan","Teng Long"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"480172","messageId":"pull.1564.git.1691210737.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":null,"subject":"[PATCH 0/5] Fixes to trailer test script, help text, and documentation","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-05T04:45:32Z","receivedAt":"2023-08-05T04:45:47Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"This series contains various fixes to the trailer code. They pertain to\nfixes to the test script, the command line help text for the\ninterpret-trailers builtin, and the documentation.\n\nPatch 1 is the biggest one, but also perhaps the most important as it does\ncleanups in the tests where we used 'git config' in a test case without\ncleaning up that state for the next test. This makes the tests\nself-contained, making it easier to add new tests anywhere along the script,\nwithout worrying about previously-set implicit state. These test cleanups\nexposed lots of cases where the test cases are mutating more configuration\nstate than is necessary to test the specific behavior in the test; however\nsuch extraneous configurations were not cleaned up to make these patches\neasier to review (again, we are not changing any behavior and we are also\nnot changing what the test cases themselves purport to do).\n\nNote that Patch 1 was originally a 22-commit series, but was squashed\ntogether to make it easier to see the final diff for each test case. You can\nsee the 22-commit breakdown at\nhttps://github.com/listx/git/tree/backup-trailer-22-commit-breakdown\n\nPatch 3 adds some tests to check the behavior of '--no-if-exists' and\n'--no-if-missing', which weren't previously tested. It also adds\nsimilarly-themed test cases for '--no-where' which only had 1 test case for\nit.\n\nThe other patches aren't as important, but are included here because I think\nthey are too small to include in a separate series.\n\nLinus Arver (5):\n  trailer tests: make test cases self-contained\n  trailer test description: this tests --where=after, not --where=before\n  trailer: add tests to check defaulting behavior with --no-* flags\n  trailer: trailer location is a place, not an action\n  trailer --no-divider help: describe usual \"---\" meaning\n\n Documentation/git-interpret-trailers.txt |  14 +-\n builtin/interpret-trailers.c             |   4 +-\n t/t7513-interpret-trailers.sh            | 506 +++++++++++++++++++----\n 3 files changed, 443 insertions(+), 81 deletions(-)\n\n\nbase-commit: 1b0a5129563ebe720330fdc8f5c6843d27641137\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1564%2Flistx%2Ftrailer-fixes-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1564/listx/trailer-fixes-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/1564\n-- \ngitgitgadget\n"},{"id":"480173","messageId":"100a2297fa3710dc107c095778b86ce3d2a3b0a6.1691210737.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.git.1691210737.gitgitgadget@gmail.com","subject":"[PATCH 2/5] trailer test description: this tests --where=after, not --where=before","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-05T04:45:34Z","receivedAt":"2023-08-05T04:45:51Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n t/t7513-interpret-trailers.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex 5b31896070a..ed0fc04bd95 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -792,7 +792,7 @@ test_expect_success 'overriding configuration with \"--where after\"' '\n \ttest_cmp expected actual\n '\n \n-test_expect_success 'using \"where = before\" with \"--no-where\"' '\n+test_expect_success 'using \"--where after\" with \"--no-where\"' '\n \ttest_config trailer.ack.key \"Acked-by= \" &&\n \ttest_config trailer.ack.where \"before\" &&\n \ttest_config trailer.bug.key \"Bug #\" &&\n-- \ngitgitgadget\n\n"},{"id":"480174","messageId":"68bc89beb2a26e8ae0ae67d1489a06af9fc37fa0.1691210737.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.git.1691210737.gitgitgadget@gmail.com","subject":"[PATCH 5/5] trailer --no-divider help: describe usual \"---\" meaning","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-05T04:45:37Z","receivedAt":"2023-08-05T04:45:53Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nIt's unclear what treating something \"specially\" means.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n builtin/interpret-trailers.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex cf4f703c4e2..a7623dbfb2e 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -109,7 +109,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"set parsing options\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n-\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat --- specially\")),\n+\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n \t\tOPT_CALLBACK(0, \"trailer\", &trailers, N_(\"trailer\"),\n \t\t\t\tN_(\"trailer(s) to add\"), option_parse_trailer),\n \t\tOPT_END()\n-- \ngitgitgadget\n"},{"id":"480175","messageId":"6d67ae6b1f62a2be076d752a2af65bb07998ca73.1691210737.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.git.1691210737.gitgitgadget@gmail.com","subject":"[PATCH 1/5] trailer tests: make test cases self-contained","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-05T04:45:33Z","receivedAt":"2023-08-05T04:45:55Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nBy using \"test_config\" instead of \"git config\", we avoid leaking\nconfiguration state across test cases. This in turn helps to make the\ntests more self-contained, by explicitly capturing the configuration\nsetup. It then makes it easier to add tests anywhere in this 1500+ line\nfile, without worrying about what implicit state was set in some prior\ntest case defined earlier up in the script.\n\nThis commit was created mechanically as follows: we changed the first\noccurrence of a particular \"git config trailer.*\" option, then ran the\ntests repeatedly to see which ones broke, adding in the extra\n\"test_config\" equivalents to make them pass again. This was done until\nthere were no more unbridled \"git config\" invocations. Some \"git config\"\ninvocations still do exist in the script, but they were already cleaned\nup properly with\n\n    test_when_finished \"git config --remove-section ...\"\n\nso they were left alone.\n\nNote that these cleanups result in generally longer test case setups\nbecause the previously hidden state is now being exposed. Although we\ncould then clean up the test cases' \"expected\" values to be less\nverbose (the verbosity arising from the use of implicit state), we\nchoose not to do so here, to make sure that this cleanup does not change\nany meanings behind the test cases.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n t/t7513-interpret-trailers.sh | 374 +++++++++++++++++++++++++++-------\n 1 file changed, 300 insertions(+), 74 deletions(-)\n\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex 97f10905d23..5b31896070a 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -489,7 +489,7 @@ test_expect_success 'multiline field treated as atomic for neighbor check' '\n '\n \n test_expect_success 'with config setup' '\n-\tgit config trailer.ack.key \"Acked-by: \" &&\n+\ttest_config trailer.ack.key \"Acked-by: \" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tAcked-by: Peff\n@@ -503,8 +503,8 @@ test_expect_success 'with config setup' '\n '\n \n test_expect_success 'with config setup and \":=\" as separators' '\n-\tgit config trailer.separators \":=\" &&\n-\tgit config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tAcked-by= Peff\n@@ -518,7 +518,7 @@ test_expect_success 'with config setup and \":=\" as separators' '\n '\n \n test_expect_success 'with config setup and \"%\" as separators' '\n-\tgit config trailer.separators \"%\" &&\n+\ttest_config trailer.separators \"%\" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tbug% 42\n@@ -532,6 +532,7 @@ test_expect_success 'with config setup and \"%\" as separators' '\n '\n \n test_expect_success 'with \"%\" as separators and a message with trailers' '\n+\ttest_config trailer.separators \"%\" &&\n \tcat >special_message <<-\\EOF &&\n \t\tSpecial Message\n \n@@ -553,8 +554,8 @@ test_expect_success 'with \"%\" as separators and a message with trailers' '\n '\n \n test_expect_success 'with config setup and \":=#\" as separators' '\n-\tgit config trailer.separators \":=#\" &&\n-\tgit config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tBug #42\n@@ -581,6 +582,8 @@ test_expect_success 'with basic patch' '\n '\n \n test_expect_success 'with commit complex message as argument' '\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat complex_message_body complex_message_trailers >complex_message &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n@@ -594,6 +597,8 @@ test_expect_success 'with commit complex message as argument' '\n '\n \n test_expect_success 'with 2 files arguments' '\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat basic_message >>expected &&\n \techo >>expected &&\n \tcat basic_patch >>expected &&\n@@ -677,6 +682,9 @@ test_expect_success 'with message that has an old style conflict block' '\n '\n \n test_expect_success 'with commit complex message and trailer args' '\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -692,6 +700,9 @@ test_expect_success 'with commit complex message and trailer args' '\n '\n \n test_expect_success 'with complex patch, args and --trim-empty' '\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat complex_message >complex_patch &&\n \tcat basic_patch >>complex_patch &&\n \tcat complex_message_body >expected &&\n@@ -746,7 +757,10 @@ test_expect_success POSIXPERM,SANITY \"in-place editing doesn't clobber original\n '\n \n test_expect_success 'using \"where = before\"' '\n-\tgit config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -762,7 +776,9 @@ test_expect_success 'using \"where = before\"' '\n '\n \n test_expect_success 'overriding configuration with \"--where after\"' '\n-\tgit config trailer.ack.where \"before\" &&\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -777,6 +793,11 @@ test_expect_success 'overriding configuration with \"--where after\"' '\n '\n \n test_expect_success 'using \"where = before\" with \"--no-where\"' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -792,7 +813,11 @@ test_expect_success 'using \"where = before\" with \"--no-where\"' '\n '\n \n test_expect_success 'using \"where = after\"' '\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -808,8 +833,11 @@ test_expect_success 'using \"where = after\"' '\n '\n \n test_expect_success 'using \"where = end\"' '\n-\tgit config trailer.review.key \"Reviewed-by\" &&\n-\tgit config trailer.review.where \"end\" &&\n+\ttest_config trailer.review.key \"Reviewed-by\" &&\n+\ttest_config trailer.review.where \"end\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -827,8 +855,11 @@ test_expect_success 'using \"where = end\"' '\n '\n \n test_expect_success 'using \"where = start\"' '\n-\tgit config trailer.review.key \"Reviewed-by\" &&\n-\tgit config trailer.review.where \"start\" &&\n+\ttest_config trailer.review.key \"Reviewed-by\" &&\n+\ttest_config trailer.review.where \"start\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tReviewed-by: Johannes\n@@ -846,8 +877,13 @@ test_expect_success 'using \"where = start\"' '\n '\n \n test_expect_success 'using \"where = before\" for a token in the middle of the message' '\n-\tgit config trailer.review.key \"Reviewed-by:\" &&\n-\tgit config trailer.review.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -864,6 +900,12 @@ test_expect_success 'using \"where = before\" for a token in the middle of the mes\n '\n \n test_expect_success 'using \"where = before\" and --trim-empty' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tcat >>expected <<-\\EOF &&\n \t\tBug #46\n@@ -878,6 +920,13 @@ test_expect_success 'using \"where = before\" and --trim-empty' '\n '\n \n test_expect_success 'the default is \"ifExists = addIfDifferentNeighbor\"' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -896,7 +945,13 @@ test_expect_success 'the default is \"ifExists = addIfDifferentNeighbor\"' '\n '\n \n test_expect_success 'default \"ifExists\" is now \"addIfDifferent\"' '\n-\tgit config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -914,8 +969,14 @@ test_expect_success 'default \"ifExists\" is now \"addIfDifferent\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -932,8 +993,14 @@ test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = before\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.ack.where \"before\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -950,8 +1017,14 @@ test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = before\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -973,8 +1046,14 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" with \"where = end\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\"  with \"where = after\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -995,7 +1074,11 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\"  with \"where = af\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" and --trim-empty' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tcat >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1011,8 +1094,14 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" and --trim-empty'\n '\n \n test_expect_success 'using \"ifExists = add\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"add\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1036,8 +1125,14 @@ test_expect_success 'using \"ifExists = add\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifExists = add\" with \"where = after\"' '\n-\tgit config trailer.ack.ifExists \"add\" &&\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1058,8 +1153,15 @@ test_expect_success 'using \"ifExists = add\" with \"where = after\"' '\n '\n \n test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n-\tgit config trailer.fix.key \"Fixes: \" &&\n-\tgit config trailer.fix.ifExists \"add\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1075,8 +1177,15 @@ test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n '\n \n test_expect_success 'using \"ifExists = replace\"' '\n-\tgit config trailer.fix.key \"Fixes: \" &&\n-\tgit config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1095,7 +1204,16 @@ test_expect_success 'using \"ifExists = replace\"' '\n '\n \n test_expect_success 'using \"ifExists = replace\" with \"where = after\"' '\n-\tgit config trailer.fix.where \"after\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1114,7 +1232,15 @@ test_expect_success 'using \"ifExists = replace\" with \"where = after\"' '\n '\n \n test_expect_success 'using \"ifExists = doNothing\"' '\n-\tgit config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1133,8 +1259,17 @@ test_expect_success 'using \"ifExists = doNothing\"' '\n '\n \n test_expect_success 'the default is \"ifMissing = add\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"before\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1154,7 +1289,14 @@ test_expect_success 'the default is \"ifMissing = add\"' '\n '\n \n test_expect_success 'overriding configuration with \"--if-missing doNothing\"' '\n-\tgit config trailer.ifmissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifmissing \"add\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1173,7 +1315,13 @@ test_expect_success 'overriding configuration with \"--if-missing doNothing\"' '\n '\n \n test_expect_success 'when default \"ifMissing\" is \"doNothing\"' '\n-\tgit config trailer.ifmissing \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifmissing \"doNothing\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1187,14 +1335,21 @@ test_expect_success 'when default \"ifMissing\" is \"doNothing\"' '\n \t\t--trailer \"cc=Linus\" --trailer \"ack: Junio\" \\\n \t\t--trailer \"fix=22\" --trailer \"bug: 42\" --trailer \"ack: Peff\" \\\n \t\t<complex_message >actual &&\n-\ttest_cmp expected actual &&\n-\tgit config trailer.ifmissing \"add\"\n+\ttest_cmp expected actual\n '\n \n test_expect_success 'using \"ifMissing = add\" with \"where = end\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"end\" &&\n-\tgit config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.cc.where \"end\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1214,9 +1369,17 @@ test_expect_success 'using \"ifMissing = add\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifMissing = add\" with \"where = before\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"before\" &&\n-\tgit config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.cc.where \"before\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tCc: Linus\n@@ -1236,7 +1399,15 @@ test_expect_success 'using \"ifMissing = add\" with \"where = before\"' '\n '\n \n test_expect_success 'using \"ifMissing = doNothing\"' '\n-\tgit config trailer.cc.ifMissing \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.ifMissing \"doNothing\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1256,7 +1427,15 @@ test_expect_success 'using \"ifMissing = doNothing\"' '\n \n test_expect_success 'default \"where\" is now \"after\"' '\n \tgit config trailer.where \"after\" &&\n-\tgit config --unset trailer.ack.where &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1280,10 +1459,15 @@ test_expect_success 'default \"where\" is now \"after\"' '\n '\n \n test_expect_success 'with simple command' '\n-\tgit config trailer.sign.key \"Signed-off-by: \" &&\n-\tgit config trailer.sign.where \"after\" &&\n-\tgit config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.sign.command \"echo \\\"A U Thor <author@example.com>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"A U Thor <author@example.com>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.sign.where \"after\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1298,8 +1482,14 @@ test_expect_success 'with simple command' '\n '\n \n test_expect_success 'with command using committer information' '\n-\tgit config trailer.sign.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.sign.command \"echo \\\"\\$GIT_COMMITTER_NAME <\\$GIT_COMMITTER_EMAIL>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_COMMITTER_NAME <\\$GIT_COMMITTER_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1314,10 +1504,15 @@ test_expect_success 'with command using committer information' '\n '\n \n test_expect_success 'with command using author information' '\n-\tgit config trailer.sign.key \"Signed-off-by: \" &&\n-\tgit config trailer.sign.where \"after\" &&\n-\tgit config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.sign.where \"after\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1338,12 +1533,19 @@ test_expect_success 'setup a commit' '\n '\n \n test_expect_success 'cmd takes precedence over command' '\n-\ttest_when_finished \"git config --unset trailer.fix.cmd\" &&\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.cmd \"test -n \\\"\\$1\\\" && git log -1 --oneline --format=\\\"%h (%aN)\\\" \\\n-\t--abbrev-commit --abbrev=14 \\\"\\$1\\\" || true\" &&\n-\tgit config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" \\\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" \\\n \t\t--abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.fix.cmd \"test -n \\\"\\$1\\\" && git log -1 --oneline --format=\\\"%h (%aN)\\\" \\\n+\t--abbrev-commit --abbrev=14 \\\"\\$1\\\" || true\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tFIXED=$(git log -1 --oneline --format=\"%h (%aN)\" --abbrev-commit --abbrev=14 HEAD) &&\n \tcat complex_message_body >expected2 &&\n \tsed -e \"s/ Z\\$/ /\" >>expected2 <<-EOF &&\n@@ -1359,8 +1561,16 @@ test_expect_success 'cmd takes precedence over command' '\n '\n \n test_expect_success 'with command using $ARG' '\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" --abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" --abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tFIXED=$(git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 HEAD) &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-EOF &&\n@@ -1376,8 +1586,16 @@ test_expect_success 'with command using $ARG' '\n '\n \n test_expect_success 'with failing command using $ARG' '\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.command \"false \\$ARG\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"false \\$ARG\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-EOF &&\n \t\tFixes: Z\n@@ -1392,7 +1610,9 @@ test_expect_success 'with failing command using $ARG' '\n '\n \n test_expect_success 'with empty tokens' '\n-\tgit config --unset trailer.fix.command &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\tSigned-off-by: A U Thor <author@example.com>\n@@ -1403,7 +1623,8 @@ test_expect_success 'with empty tokens' '\n '\n \n test_expect_success 'with command but no key' '\n-\tgit config --unset trailer.sign.key &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\tsign: A U Thor <author@example.com>\n@@ -1414,7 +1635,9 @@ test_expect_success 'with command but no key' '\n '\n \n test_expect_success 'with no command and no key' '\n-\tgit config --unset trailer.review.key &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\treview: Junio\n@@ -1426,6 +1649,8 @@ test_expect_success 'with no command and no key' '\n '\n \n test_expect_success 'with cut line' '\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n \tcat >expected <<-\\EOF &&\n \t\tmy subject\n \n@@ -1443,7 +1668,8 @@ test_expect_success 'with cut line' '\n '\n \n test_expect_success 'only trailers' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-\\EOF &&\n \t\texisting: existing-value\n \t\tsign: config-value\n@@ -1462,7 +1688,7 @@ test_expect_success 'only trailers' '\n '\n \n test_expect_success 'only-trailers omits non-trailer in middle of block' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n \tcat >expected <<-\\EOF &&\n \t\tSigned-off-by: nobody <nobody@nowhere>\n \t\tSigned-off-by: somebody <somebody@somewhere>\n@@ -1482,7 +1708,7 @@ test_expect_success 'only-trailers omits non-trailer in middle of block' '\n '\n \n test_expect_success 'only input' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n \tcat >expected <<-\\EOF &&\n \t\texisting: existing-value\n \tEOF\n-- \ngitgitgadget\n\n"},{"id":"480176","messageId":"53adcd9bf14548187bd2ee0f4d0073959fde66cb.1691210737.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.git.1691210737.gitgitgadget@gmail.com","subject":"[PATCH 4/5] trailer: trailer location is a place, not an action","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-05T04:45:36Z","receivedAt":"2023-08-05T04:45:57Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nFix the help text to say \"placement\" instead of \"action\" because the\nvalues are placements, not actions.\n\nWhile we're at it, tweak the documentation to say \"placements\" instead\nof \"values\", similar to how the existing language for \"--if-exists\" uses\nthe word \"action\" to describe both the syntax (with the phrase\n\"--if-exists <action>\") and the possible values (with the phrase\n\"possible actions\").\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 2 +-\n builtin/interpret-trailers.c             | 2 +-\n 2 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 91a4dbc9a72..c9b1e60251d 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -116,7 +116,7 @@ OPTIONS\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n \teffect of any previous use of '--where', such that the relevant configuration\n-\tvariables are no longer overridden. Possible values are `after`,\n+\tvariables are no longer overridden. Possible placements are `after`,\n \t`before`, `end` or `start`.\n \n --if-exists <action>::\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex c5e83452654..cf4f703c4e2 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -97,7 +97,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"in-place\", &opts.in_place, N_(\"edit files in place\")),\n \t\tOPT_BOOL(0, \"trim-empty\", &opts.trim_empty, N_(\"trim empty trailers\")),\n \n-\t\tOPT_CALLBACK(0, \"where\", NULL, N_(\"action\"),\n+\t\tOPT_CALLBACK(0, \"where\", NULL, N_(\"placement\"),\n \t\t\t     N_(\"where to place the new trailer\"), option_parse_where),\n \t\tOPT_CALLBACK(0, \"if-exists\", NULL, N_(\"action\"),\n \t\t\t     N_(\"action if trailer already exists\"), option_parse_if_exists),\n-- \ngitgitgadget\n\n"},{"id":"480177","messageId":"6b427b4b1e82b1f01640f1f49fe8d1c2fd02111e.1691210737.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.git.1691210737.gitgitgadget@gmail.com","subject":"[PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-05T04:45:35Z","receivedAt":"2023-08-05T04:45:59Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nWhile the \"--no-where\" flag is tested, the \"--no-if-exists\" and\n\"--no-if-missing\" flags are not, so add tests for them. But also add\ntests for all \"--no-*\" flags to check their effects, both when (1) there\nare relevant configuration variables set, and (2) they are not set.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt |  14 ++-\n t/t7513-interpret-trailers.sh            | 130 +++++++++++++++++++++++\n 2 files changed, 140 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 55d89614661..91a4dbc9a72 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -114,8 +114,10 @@ OPTIONS\n \tSpecify where all new trailers will be added.  A setting\n \tprovided with '--where' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--where' or '--no-where'. Possible values are `after`, `before`,\n-\t`end` or `start`.\n+\t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n+\teffect of any previous use of '--where', such that the relevant configuration\n+\tvariables are no longer overridden. Possible values are `after`,\n+\t`before`, `end` or `start`.\n \n --if-exists <action>::\n --no-if-exists::\n@@ -123,7 +125,9 @@ OPTIONS\n \tleast one trailer with the same <token> in the input.  A setting\n \tprovided with '--if-exists' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--if-exists' or '--no-if-exists'. Possible actions are `addIfDifferent`,\n+\t'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists, clear the\n+\teffect of any previous use of '--if-exists, such that the relevant configuration\n+\tvariables are no longer overridden. Possible actions are `addIfDifferent`,\n \t`addIfDifferentNeighbor`, `add`, `replace` and `doNothing`.\n \n --if-missing <action>::\n@@ -132,7 +136,9 @@ OPTIONS\n \ttrailer with the same <token> in the input.  A setting\n \tprovided with '--if-missing' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--if-missing' or '--no-if-missing'. Possible actions are `doNothing`\n+\t'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing,\n+\tclear the effect of any previous use of '--if-missing, such that the relevant\n+\tconfiguration variables are no longer overridden. Possible actions are `doNothing`\n \tor `add`.\n \n --only-trailers::\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex ed0fc04bd95..832aff06167 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -812,6 +812,53 @@ test_expect_success 'using \"--where after\" with \"--no-where\"' '\n \ttest_cmp expected actual\n '\n \n+# Check whether using \"--no-where\" clears out only the \"--where after\", such\n+# that we still use the configuration in trailer.where (which is different from\n+# the hardcoded default (in WHERE_END) assuming the absence of .gitconfig).\n+# Here, the \"start\" setting of trailer.where is respected, so the new \"Acked-by\"\n+# and \"Bug\" trailers are placed at the beginning, and not at the end which is\n+# the harcoded default.\n+test_expect_success 'using \"--where after\" with \"--no-where\" defaults to configuration' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.where \"start\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tBug #42\n+\t\tAcked-by= Peff\n+\t\tFixes: Z\n+\t\tAcked-by= Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --where after --no-where --trailer \"ack: Peff\" \\\n+\t\t--trailer \"bug: 42\" complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# The \"--where after\" will only get respected for the trailer that came\n+# immediately after it. For the next trailer (Bug #42), we default to using the\n+# hardcoded WHERE_END because we don't have any \"trailer.where\" or\n+# \"trailer.bug.where\" configured.\n+test_expect_success 'using \"--no-where\" defaults to harcoded default if nothing configured' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tFixes: Z\n+\t\tAcked-by= Z\n+\t\tAcked-by= Peff\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tBug #42\n+\tEOF\n+\tgit interpret-trailers --where after --trailer \"ack: Peff\" --no-where \\\n+\t\t--trailer \"bug: 42\" complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'using \"where = after\"' '\n \ttest_config trailer.ack.key \"Acked-by= \" &&\n \ttest_config trailer.ack.where \"after\" &&\n@@ -1176,6 +1223,56 @@ test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n \ttest_cmp expected actual\n '\n \n+# \"trailer.ifexists\" is set to \"doNothing\", so using \"--no-if-exists\" defaults\n+# to this \"doNothing\" behavior. So the \"Fixes: 53\" trailer does not get added.\n+test_expect_success 'using \"--if-exists replace\" with \"--no-if-exists\" defaults to configuration' '\n+\ttest_config trailer.ifexists \"doNothing\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tFixes: Z\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --no-if-exists --trailer \"Fixes: 53\" \\\n+\t\t<complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# No \"ifexists\" configuration is set, so using \"--no-if-exists\" makes it default\n+# to addIfDifferentNeighbor. Because we do have a different neighbor \"Fixes: 53\"\n+# (because it got added by overriding with \"--if-exists replace\" earlier in the\n+# arguments list), we add \"Signed-off-by: addme\".\n+test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tFixes: 53\n+\t\tSigned-off-by: addme\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n+\t\t--trailer \"Signed-off-by: addme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# The second \"Fixes: 53\" trailer is discarded, because the \"--no-if-exists\" here\n+# makes us default to addIfDifferentNeighbor, and we already added the \"Fixes:\n+# 53\" trailer earlier in the argument list.\n+test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured (no addition)' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tFixes: 53\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n+\t\t--trailer \"Fixes: 53\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'using \"ifExists = replace\"' '\n \ttest_config trailer.fix.key \"Fixes: \" &&\n \ttest_config trailer.fix.ifExists \"replace\" &&\n@@ -1425,6 +1522,39 @@ test_expect_success 'using \"ifMissing = doNothing\"' '\n \ttest_cmp expected actual\n '\n \n+# Ignore the \"IgnoredTrailer\" because of \"--if-missing doNothing\", but also\n+# ignore the \"StillIgnoredTrailer\" because we set \"trailer.ifMissing\" to\n+# \"doNothing\" in configuration.\n+test_expect_success 'using \"--no-if-missing\" defaults to configuration' '\n+\ttest_config trailer.ifMissing \"doNothing\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\t\tFixes: Z\n+\t\t\tAcked-by: Z\n+\t\t\tReviewed-by: Z\n+\t\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n+\t\t\t--trailer \"StillIgnoredTrailer: ignoreme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# Add the \"AddedTrailer\" because the \"--no-if-missing\" clears the \"--if-missing\n+# doNothing\" from earlier in the argument list.\n+test_expect_success 'using \"--no-if-missing\" defaults to hardcoded default if nothing configured' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\t\tFixes: Z\n+\t\t\tAcked-by: Z\n+\t\t\tReviewed-by: Z\n+\t\t\tSigned-off-by: Z\n+\t\t\tAddedTrailer: addme\n+\tEOF\n+\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n+\t\t\t--trailer \"AddedTrailer: addme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'default \"where\" is now \"after\"' '\n \tgit config trailer.where \"after\" &&\n \ttest_config trailer.ack.ifExists \"add\" &&\n-- \ngitgitgadget\n\n"},{"id":"480203","messageId":"xmqqjzu7irhw.fsf@gitster.g","threadId":"60067","inReplyTo":"6b427b4b1e82b1f01640f1f49fe8d1c2fd02111e.1691210737.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-08-07T01:13:47Z","receivedAt":"2023-08-07T01:13:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> @@ -114,8 +114,10 @@ OPTIONS\n>  \tSpecify where all new trailers will be added.  A setting\n>  \tprovided with '--where' overrides all configuration variables\n\nObviously this is not a new issue, but \"all configuration variables\"\nis misleading (the same comment applies to the description of the\n\"--[no-]if-exists\" and the \"--[no-]if-missing\" options).\n\nIf I am reading the code correctly, --where=value overrides the\ntrailer.where variable and nothing else, and --no-where stops the\noverriding of the trailer.where variable.  Ditto for the other two\nwith their relevant configuration variables.\n\n"},{"id":"480205","messageId":"owlyfs4vbeus.fsf@fine.c.googlers.com","threadId":"60067","inReplyTo":"xmqqjzu7irhw.fsf@gitster.g","subject":"Re: [PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Linus Arver","fromEmail":"linusa@google.com","sentAt":"2023-08-07T05:28:43Z","receivedAt":"2023-08-07T05:28:49Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> \"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n>> @@ -114,8 +114,10 @@ OPTIONS\n>>  \tSpecify where all new trailers will be added.  A setting\n>>  \tprovided with '--where' overrides all configuration variables\n>\n> Obviously this is not a new issue, but \"all configuration variables\"\n> is misleading (the same comment applies to the description of the\n> \"--[no-]if-exists\" and the \"--[no-]if-missing\" options).\n\nAgreed.\n\n> If I am reading the code correctly, --where=value overrides the\n> trailer.where variable and nothing else, and --no-where stops the\n> overriding of the trailer.where variable.  Ditto for the other two\n> with their relevant configuration variables.\n\nThat is also my understanding. Will update to remove the \"all\" wording.\n\nOn a separate note, I've realized there are more fixes to be done in\nthis area (as I get more familiar with the codebase). For example, we\nhave the following language in builtin/interpret-trailers.c inside\ncmd_interpret_trailers():\n\n    OPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply config rules\")),\n\nwhich should be fixed in similar style to what you suggested above,\nprobably with:\n\n    OPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply trailer.* configuration variables\")),\n\nWhen I reroll, I will include these additional fixes so expect the patch\nseries to grow (probably ~12 patches instead of the ~5).\n\nOne more thing. I think the documentation\n(Documentation/git-interpret-trailers.txt) uses the word \"<token>\" in\ntwo different ways. For example, if we have in the input\n\n    subject line\n\n    body text\n\n    Acked-by: Foo\n\nthe docs treat the word \"Acked-by:\" as the <token>. However, it defines\nthe relevant configuration section like this:\n\n    trailer.<token>.key::\n            This `key` will be used instead of <token> in the trailer. At\n            the end of this key, a separator can appear and then some\n            space characters. By default the only valid separator is ':',\n            but this can be changed using the `trailer.separators` config\n            variable.\n    +\n    If there is a separator, then the key will be used instead of both the\n    <token> and the default separator when adding the trailer.\n\nSo if I configure this like\n\n   git config trailer.ack.key \"Acked-by\" &&\n\nthe <token> is both the longer-form \"Acked-by:\" (per the meaning so far\nin the doc) but also the shorter string \"ack\" per the\n\"trailer.<token>.key\" configuration section syntax. This secondary\nmeaning is repeated again in the very start of the doc when we define\nthe --trailer option syntax as\n\n    SYNOPSIS\n    --------\n    [verse]\n    'git interpret-trailers' [--in-place] [--trim-empty]\n                [(--trailer <token>[(=|:)<value>])...]\n                [--parse] [<file>...]\n\nbecause the <token> here could be (using the example above) either\n\"Acked-by\" (as in \"--trailer=Acked-by:...\") if we did not configure\n\"trailer.ack.key\", or just \"ack\" (as in \"--trailer=ack:...\") if we did\nconfigure it. These two scenarios would give identical \"Acked-by: ...\"\noutput.\n\nThis is confusing and I don't like how we overload this \"token\" word\n(not to mention we already have the word \"key\" which we don't really use\nmuch in the docs).\n\nI am inclined to replace most uses of the word \"<token>\" with \"<key>\"\nwhile leaving the \"trailer.<token>.key\" configuration syntax intact.\nThis will result in a large diff but I think the removal of the double\nmeaning is worth it, and will include this fix also in the next reroll.\n\nThe main reason I bring this up is because this means also having to\nupdate our funciton names like \"token_len_without_separator\" in\ntrailer.c, to be \"key_len_without_separator\" if we want the nomenclature\nin the trailer.c internals to be consistent with the (updated)\nuser-facing docs. I am not sure whether we want to do this as part of\nthe same reroll, or if we should leave it as #leftoverbits for a future\nseries.\n"},{"id":"480206","messageId":"owlycyzzbefh.fsf@fine.c.googlers.com","threadId":"60067","inReplyTo":"owlyfs4vbeus.fsf@fine.c.googlers.com","subject":"Re: [PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Linus Arver","fromEmail":"linusa@google.com","sentAt":"2023-08-07T05:37:54Z","receivedAt":"2023-08-07T05:38:00Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"Linus Arver <linusa@google.com> writes:\n\n> So if I configure this like\n>\n>    git config trailer.ack.key \"Acked-by\" &&\n>\n\nOops, I meant just\n\n    git config trailer.ack.key \"Acked-by\"\n\nwithout the trailing \"&&\".\n"},{"id":"480207","messageId":"owlya5v3bdu5.fsf@fine.c.googlers.com","threadId":"60067","inReplyTo":"6d67ae6b1f62a2be076d752a2af65bb07998ca73.1691210737.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 1/5] trailer tests: make test cases self-contained","fromName":"Linus Arver","fromEmail":"linusa@google.com","sentAt":"2023-08-07T05:50:42Z","receivedAt":"2023-08-07T05:50:47Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Linus Arver <linusa@google.com>\n> ...\n> @@ -1392,7 +1610,9 @@ test_expect_success 'with failing command using $ARG' '\n>  '\n>  \n>  test_expect_success 'with empty tokens' '\n> -\tgit config --unset trailer.fix.command &&\n> +\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n> +\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n> +\ttest_config trailer.ifexists \"addIfDifferent\" &&\n>  \tcat >expected <<-EOF &&\n>  \n>  \t\tSigned-off-by: A U Thor <author@example.com>\n\nIn this test and some other places we get the chance to remove\ninvocations of \"git config --unset ...\" (because we don't leak config\nstate anymore). I will update the commit message accordingly in the next\nreroll.\n"},{"id":"480208","messageId":"owly7cq7bbr9.fsf@fine.c.googlers.com","threadId":"60067","inReplyTo":"owlyfs4vbeus.fsf@fine.c.googlers.com","subject":"Re: [PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Linus Arver","fromEmail":"linusa@google.com","sentAt":"2023-08-07T06:35:38Z","receivedAt":"2023-08-07T06:35:48Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"Linus Arver <linusa@google.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> \"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>>\n>>> @@ -114,8 +114,10 @@ OPTIONS\n>>>  \tSpecify where all new trailers will be added.  A setting\n>>>  \tprovided with '--where' overrides all configuration variables\n>>\n>> Obviously this is not a new issue, but \"all configuration variables\"\n>> is misleading (the same comment applies to the description of the\n>> \"--[no-]if-exists\" and the \"--[no-]if-missing\" options).\n>\n> Agreed.\n>\n>> If I am reading the code correctly, --where=value overrides the\n>> trailer.where variable and nothing else, and --no-where stops the\n>> overriding of the trailer.where variable.  Ditto for the other two\n>> with their relevant configuration variables.\n>\n> That is also my understanding. Will update to remove the \"all\" wording.\n\nHmph, actually it also overrides any applicable \"trailer.<token>.where\"\nconfigurations (these <token>-specific configurations override the\n\"trailer.where\" configuration where applicable). Still, the \"all\nconfiguration variables\" wording should be updated, probably like this:\n\n    ›  Specify where all new trailers will be added.  A setting\n    ›  provided with '--where' overrides the `trailer.where` and any\n    ›  applicable `trailer.<token>.where` configuration variables\n    ›  and applies to all '--trailer' options until the next occurrence of\n    ›  '--where' or '--no-where'.\n"},{"id":"480215","messageId":"xmqqbkfij1bh.fsf@gitster.g","threadId":"60067","inReplyTo":"owly7cq7bbr9.fsf@fine.c.googlers.com","subject":"Re: [PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-08-07T15:53:54Z","receivedAt":"2023-08-07T15:54:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Arver <linusa@google.com> writes:\n\n>>> If I am reading the code correctly, --where=value overrides the\n>>> trailer.where variable and nothing else, and --no-where stops the\n>>> overriding of the trailer.where variable.  Ditto for the other two\n>>> with their relevant configuration variables.\n>>\n>> That is also my understanding. Will update to remove the \"all\" wording.\n>\n> Hmph, actually it also overrides any applicable \"trailer.<token>.where\"\n> configurations (these <token>-specific configurations override the\n> \"trailer.where\" configuration where applicable). Still, the \"all\n> configuration variables\" wording should be updated, probably like this:\n>\n>     ›  Specify where all new trailers will be added.  A setting\n>     ›  provided with '--where' overrides the `trailer.where` and any\n>     ›  applicable `trailer.<token>.where` configuration variables\n>     ›  and applies to all '--trailer' options until the next occurrence of\n>     ›  '--where' or '--no-where'.\n\nYup, that was what I meant.  I found it troubling that the \"all\"\nphrasing felt like it meant all trailer.* configurations, not just\nthe \"where\" thing.  Your new description looks good.\n\nThanks.\n\n"},{"id":"480489","messageId":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.git.1691210737.gitgitgadget@gmail.com","subject":"[PATCH v2 00/13] Fixes to trailer test script, help text, and documentation","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:50Z","receivedAt":"2023-08-10T21:18:08Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"This series contains various fixes to the trailer code. They pertain to\nfixes to the test script, the command line help text for the\ninterpret-trailers builtin, and the documentation.\n\nPatch 1 is the most important as it does cleanups in the tests where we used\n'git config' in a test case without cleaning up that state for the next\ntest. This makes the tests self-contained, making it easier to add new tests\nanywhere along the script, without worrying about previously-set implicit\nstate. These test cleanups exposed lots of cases where the test cases are\nmutating more configuration state than is necessary to test the specific\nbehavior in the test; however such extraneous configurations were not\ncleaned up to make these patches easier to review (again, we are not\nchanging any behavior and we are also not changing what the test cases\nthemselves purport to do).\n\nNote that Patch 1 was originally a 22-commit series, but was squashed\ntogether to make it easier to see the final diff for each test case. You can\nsee the 22-commit breakdown at\nhttps://github.com/listx/git/tree/backup-trailer-22-commit-breakdown\n\nPatch 3 adds some tests to check the behavior of '--no-if-exists' and\n'--no-if-missing', which weren't previously tested. It also adds\nsimilarly-themed test cases for '--no-where' which only had 1 test case for\nit.\n\nThe other patches aren't as important, but are included here because I think\nthey are too small to include in a separate series.\n\n\nUpdates in v2\n=============\n\n * Many additional patches to fix the help text and docs. No changes to any\n   of the patches touching the actual tests (that is, Patch 1 and 3 have\n   stayed the same, other than a rewording of the commit message for Patch\n   1).\n * Of these new patches, I think the last one () is the most important as it\n   resolves a longtime ambiguity about what a can be.\n\nLinus Arver (13):\n  trailer tests: make test cases self-contained\n  trailer test description: this tests --where=after, not --where=before\n  trailer: add tests to check defaulting behavior with --no-* flags\n  trailer doc: narrow down scope of --where and related flags\n  trailer: trailer location is a place, not an action\n  trailer --no-divider help: describe usual \"---\" meaning\n  trailer --parse help: expose aliased options\n  trailer --only-input: prefer \"configuration variables\" over \"rules\"\n  trailer --parse docs: add explanation for its usefulness\n  trailer --unfold help: prefer \"reformat\" over \"join\"\n  trailer doc: emphasize the effect of configuration variables\n  trailer doc: separator within key suppresses default separator\n  trailer doc: <token> is a <key> or <keyAlias>, not both\n\n Documentation/git-interpret-trailers.txt | 183 ++++----\n builtin/interpret-trailers.c             |  10 +-\n t/t7513-interpret-trailers.sh            | 506 +++++++++++++++++++----\n 3 files changed, 544 insertions(+), 155 deletions(-)\n\n\nbase-commit: 1b0a5129563ebe720330fdc8f5c6843d27641137\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1564%2Flistx%2Ftrailer-fixes-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1564/listx/trailer-fixes-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/1564\n\nRange-diff vs v1:\n\n  1:  6d67ae6b1f6 !  1:  1623dd000dd trailer tests: make test cases self-contained\n     @@ Commit message\n          This commit was created mechanically as follows: we changed the first\n          occurrence of a particular \"git config trailer.*\" option, then ran the\n          tests repeatedly to see which ones broke, adding in the extra\n     -    \"test_config\" equivalents to make them pass again. This was done until\n     -    there were no more unbridled \"git config\" invocations. Some \"git config\"\n     -    invocations still do exist in the script, but they were already cleaned\n     -    up properly with\n     +    \"test_config\" equivalents to make them pass again. In addition, in some\n     +    test cases we removed \"git config --unset ...\" lines because they were\n     +    no longer necessary (as the --unset was being used to clean up leaked\n     +    configuration state from earlier test cases).\n     +\n     +    The process described above was done repeatedly until there were no more\n     +    unbridled \"git config\" invocations. Some \"git config\" invocations still\n     +    do exist in the script, but they were already cleaned up properly with\n      \n              test_when_finished \"git config --remove-section ...\"\n      \n  2:  100a2297fa3 =  2:  f680e76de84 trailer test description: this tests --where=after, not --where=before\n  3:  6b427b4b1e8 =  3:  4b5c458ef43 trailer: add tests to check defaulting behavior with --no-* flags\n  -:  ----------- >  4:  0df12c5c2dd trailer doc: narrow down scope of --where and related flags\n  4:  53adcd9bf14 =  5:  040766861e2 trailer: trailer location is a place, not an action\n  5:  68bc89beb2a =  6:  3e58b6f5ea2 trailer --no-divider help: describe usual \"---\" meaning\n  -:  ----------- >  7:  d1780a0127a trailer --parse help: expose aliased options\n  -:  ----------- >  8:  5cfff52da8f trailer --only-input: prefer \"configuration variables\" over \"rules\"\n  -:  ----------- >  9:  ef6b77016cd trailer --parse docs: add explanation for its usefulness\n  -:  ----------- > 10:  a08d78618ba trailer --unfold help: prefer \"reformat\" over \"join\"\n  -:  ----------- > 11:  4db823ac354 trailer doc: emphasize the effect of configuration variables\n  -:  ----------- > 12:  66087eaf5bd trailer doc: separator within key suppresses default separator\n  -:  ----------- > 13:  7b66cf29d29 trailer doc: <token> is a <key> or <keyAlias>, not both\n\n-- \ngitgitgadget\n"},{"id":"480490","messageId":"f680e76de847cf88fc4e4d63844829c6b344a697.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 02/13] trailer test description: this tests --where=after, not --where=before","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:52Z","receivedAt":"2023-08-10T21:18:10Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n t/t7513-interpret-trailers.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex 5b31896070a..ed0fc04bd95 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -792,7 +792,7 @@ test_expect_success 'overriding configuration with \"--where after\"' '\n \ttest_cmp expected actual\n '\n \n-test_expect_success 'using \"where = before\" with \"--no-where\"' '\n+test_expect_success 'using \"--where after\" with \"--no-where\"' '\n \ttest_config trailer.ack.key \"Acked-by= \" &&\n \ttest_config trailer.ack.where \"before\" &&\n \ttest_config trailer.bug.key \"Bug #\" &&\n-- \ngitgitgadget\n\n"},{"id":"480491","messageId":"1623dd000ddef40ffb6ca44cf7ce66d1c42b0d13.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 01/13] trailer tests: make test cases self-contained","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:51Z","receivedAt":"2023-08-10T21:18:15Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nBy using \"test_config\" instead of \"git config\", we avoid leaking\nconfiguration state across test cases. This in turn helps to make the\ntests more self-contained, by explicitly capturing the configuration\nsetup. It then makes it easier to add tests anywhere in this 1500+ line\nfile, without worrying about what implicit state was set in some prior\ntest case defined earlier up in the script.\n\nThis commit was created mechanically as follows: we changed the first\noccurrence of a particular \"git config trailer.*\" option, then ran the\ntests repeatedly to see which ones broke, adding in the extra\n\"test_config\" equivalents to make them pass again. In addition, in some\ntest cases we removed \"git config --unset ...\" lines because they were\nno longer necessary (as the --unset was being used to clean up leaked\nconfiguration state from earlier test cases).\n\nThe process described above was done repeatedly until there were no more\nunbridled \"git config\" invocations. Some \"git config\" invocations still\ndo exist in the script, but they were already cleaned up properly with\n\n    test_when_finished \"git config --remove-section ...\"\n\nso they were left alone.\n\nNote that these cleanups result in generally longer test case setups\nbecause the previously hidden state is now being exposed. Although we\ncould then clean up the test cases' \"expected\" values to be less\nverbose (the verbosity arising from the use of implicit state), we\nchoose not to do so here, to make sure that this cleanup does not change\nany meanings behind the test cases.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n t/t7513-interpret-trailers.sh | 374 +++++++++++++++++++++++++++-------\n 1 file changed, 300 insertions(+), 74 deletions(-)\n\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex 97f10905d23..5b31896070a 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -489,7 +489,7 @@ test_expect_success 'multiline field treated as atomic for neighbor check' '\n '\n \n test_expect_success 'with config setup' '\n-\tgit config trailer.ack.key \"Acked-by: \" &&\n+\ttest_config trailer.ack.key \"Acked-by: \" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tAcked-by: Peff\n@@ -503,8 +503,8 @@ test_expect_success 'with config setup' '\n '\n \n test_expect_success 'with config setup and \":=\" as separators' '\n-\tgit config trailer.separators \":=\" &&\n-\tgit config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tAcked-by= Peff\n@@ -518,7 +518,7 @@ test_expect_success 'with config setup and \":=\" as separators' '\n '\n \n test_expect_success 'with config setup and \"%\" as separators' '\n-\tgit config trailer.separators \"%\" &&\n+\ttest_config trailer.separators \"%\" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tbug% 42\n@@ -532,6 +532,7 @@ test_expect_success 'with config setup and \"%\" as separators' '\n '\n \n test_expect_success 'with \"%\" as separators and a message with trailers' '\n+\ttest_config trailer.separators \"%\" &&\n \tcat >special_message <<-\\EOF &&\n \t\tSpecial Message\n \n@@ -553,8 +554,8 @@ test_expect_success 'with \"%\" as separators and a message with trailers' '\n '\n \n test_expect_success 'with config setup and \":=#\" as separators' '\n-\tgit config trailer.separators \":=#\" &&\n-\tgit config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tBug #42\n@@ -581,6 +582,8 @@ test_expect_success 'with basic patch' '\n '\n \n test_expect_success 'with commit complex message as argument' '\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat complex_message_body complex_message_trailers >complex_message &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n@@ -594,6 +597,8 @@ test_expect_success 'with commit complex message as argument' '\n '\n \n test_expect_success 'with 2 files arguments' '\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat basic_message >>expected &&\n \techo >>expected &&\n \tcat basic_patch >>expected &&\n@@ -677,6 +682,9 @@ test_expect_success 'with message that has an old style conflict block' '\n '\n \n test_expect_success 'with commit complex message and trailer args' '\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -692,6 +700,9 @@ test_expect_success 'with commit complex message and trailer args' '\n '\n \n test_expect_success 'with complex patch, args and --trim-empty' '\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat complex_message >complex_patch &&\n \tcat basic_patch >>complex_patch &&\n \tcat complex_message_body >expected &&\n@@ -746,7 +757,10 @@ test_expect_success POSIXPERM,SANITY \"in-place editing doesn't clobber original\n '\n \n test_expect_success 'using \"where = before\"' '\n-\tgit config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -762,7 +776,9 @@ test_expect_success 'using \"where = before\"' '\n '\n \n test_expect_success 'overriding configuration with \"--where after\"' '\n-\tgit config trailer.ack.where \"before\" &&\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -777,6 +793,11 @@ test_expect_success 'overriding configuration with \"--where after\"' '\n '\n \n test_expect_success 'using \"where = before\" with \"--no-where\"' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -792,7 +813,11 @@ test_expect_success 'using \"where = before\" with \"--no-where\"' '\n '\n \n test_expect_success 'using \"where = after\"' '\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -808,8 +833,11 @@ test_expect_success 'using \"where = after\"' '\n '\n \n test_expect_success 'using \"where = end\"' '\n-\tgit config trailer.review.key \"Reviewed-by\" &&\n-\tgit config trailer.review.where \"end\" &&\n+\ttest_config trailer.review.key \"Reviewed-by\" &&\n+\ttest_config trailer.review.where \"end\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -827,8 +855,11 @@ test_expect_success 'using \"where = end\"' '\n '\n \n test_expect_success 'using \"where = start\"' '\n-\tgit config trailer.review.key \"Reviewed-by\" &&\n-\tgit config trailer.review.where \"start\" &&\n+\ttest_config trailer.review.key \"Reviewed-by\" &&\n+\ttest_config trailer.review.where \"start\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tReviewed-by: Johannes\n@@ -846,8 +877,13 @@ test_expect_success 'using \"where = start\"' '\n '\n \n test_expect_success 'using \"where = before\" for a token in the middle of the message' '\n-\tgit config trailer.review.key \"Reviewed-by:\" &&\n-\tgit config trailer.review.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -864,6 +900,12 @@ test_expect_success 'using \"where = before\" for a token in the middle of the mes\n '\n \n test_expect_success 'using \"where = before\" and --trim-empty' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tcat >>expected <<-\\EOF &&\n \t\tBug #46\n@@ -878,6 +920,13 @@ test_expect_success 'using \"where = before\" and --trim-empty' '\n '\n \n test_expect_success 'the default is \"ifExists = addIfDifferentNeighbor\"' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -896,7 +945,13 @@ test_expect_success 'the default is \"ifExists = addIfDifferentNeighbor\"' '\n '\n \n test_expect_success 'default \"ifExists\" is now \"addIfDifferent\"' '\n-\tgit config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -914,8 +969,14 @@ test_expect_success 'default \"ifExists\" is now \"addIfDifferent\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -932,8 +993,14 @@ test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = before\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.ack.where \"before\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -950,8 +1017,14 @@ test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = before\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -973,8 +1046,14 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" with \"where = end\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\"  with \"where = after\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -995,7 +1074,11 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\"  with \"where = af\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" and --trim-empty' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tcat >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1011,8 +1094,14 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" and --trim-empty'\n '\n \n test_expect_success 'using \"ifExists = add\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"add\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1036,8 +1125,14 @@ test_expect_success 'using \"ifExists = add\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifExists = add\" with \"where = after\"' '\n-\tgit config trailer.ack.ifExists \"add\" &&\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1058,8 +1153,15 @@ test_expect_success 'using \"ifExists = add\" with \"where = after\"' '\n '\n \n test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n-\tgit config trailer.fix.key \"Fixes: \" &&\n-\tgit config trailer.fix.ifExists \"add\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1075,8 +1177,15 @@ test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n '\n \n test_expect_success 'using \"ifExists = replace\"' '\n-\tgit config trailer.fix.key \"Fixes: \" &&\n-\tgit config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1095,7 +1204,16 @@ test_expect_success 'using \"ifExists = replace\"' '\n '\n \n test_expect_success 'using \"ifExists = replace\" with \"where = after\"' '\n-\tgit config trailer.fix.where \"after\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1114,7 +1232,15 @@ test_expect_success 'using \"ifExists = replace\" with \"where = after\"' '\n '\n \n test_expect_success 'using \"ifExists = doNothing\"' '\n-\tgit config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1133,8 +1259,17 @@ test_expect_success 'using \"ifExists = doNothing\"' '\n '\n \n test_expect_success 'the default is \"ifMissing = add\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"before\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1154,7 +1289,14 @@ test_expect_success 'the default is \"ifMissing = add\"' '\n '\n \n test_expect_success 'overriding configuration with \"--if-missing doNothing\"' '\n-\tgit config trailer.ifmissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifmissing \"add\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1173,7 +1315,13 @@ test_expect_success 'overriding configuration with \"--if-missing doNothing\"' '\n '\n \n test_expect_success 'when default \"ifMissing\" is \"doNothing\"' '\n-\tgit config trailer.ifmissing \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifmissing \"doNothing\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1187,14 +1335,21 @@ test_expect_success 'when default \"ifMissing\" is \"doNothing\"' '\n \t\t--trailer \"cc=Linus\" --trailer \"ack: Junio\" \\\n \t\t--trailer \"fix=22\" --trailer \"bug: 42\" --trailer \"ack: Peff\" \\\n \t\t<complex_message >actual &&\n-\ttest_cmp expected actual &&\n-\tgit config trailer.ifmissing \"add\"\n+\ttest_cmp expected actual\n '\n \n test_expect_success 'using \"ifMissing = add\" with \"where = end\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"end\" &&\n-\tgit config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.cc.where \"end\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1214,9 +1369,17 @@ test_expect_success 'using \"ifMissing = add\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifMissing = add\" with \"where = before\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"before\" &&\n-\tgit config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.cc.where \"before\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tCc: Linus\n@@ -1236,7 +1399,15 @@ test_expect_success 'using \"ifMissing = add\" with \"where = before\"' '\n '\n \n test_expect_success 'using \"ifMissing = doNothing\"' '\n-\tgit config trailer.cc.ifMissing \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.ifMissing \"doNothing\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1256,7 +1427,15 @@ test_expect_success 'using \"ifMissing = doNothing\"' '\n \n test_expect_success 'default \"where\" is now \"after\"' '\n \tgit config trailer.where \"after\" &&\n-\tgit config --unset trailer.ack.where &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1280,10 +1459,15 @@ test_expect_success 'default \"where\" is now \"after\"' '\n '\n \n test_expect_success 'with simple command' '\n-\tgit config trailer.sign.key \"Signed-off-by: \" &&\n-\tgit config trailer.sign.where \"after\" &&\n-\tgit config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.sign.command \"echo \\\"A U Thor <author@example.com>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"A U Thor <author@example.com>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.sign.where \"after\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1298,8 +1482,14 @@ test_expect_success 'with simple command' '\n '\n \n test_expect_success 'with command using committer information' '\n-\tgit config trailer.sign.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.sign.command \"echo \\\"\\$GIT_COMMITTER_NAME <\\$GIT_COMMITTER_EMAIL>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_COMMITTER_NAME <\\$GIT_COMMITTER_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1314,10 +1504,15 @@ test_expect_success 'with command using committer information' '\n '\n \n test_expect_success 'with command using author information' '\n-\tgit config trailer.sign.key \"Signed-off-by: \" &&\n-\tgit config trailer.sign.where \"after\" &&\n-\tgit config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.sign.where \"after\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1338,12 +1533,19 @@ test_expect_success 'setup a commit' '\n '\n \n test_expect_success 'cmd takes precedence over command' '\n-\ttest_when_finished \"git config --unset trailer.fix.cmd\" &&\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.cmd \"test -n \\\"\\$1\\\" && git log -1 --oneline --format=\\\"%h (%aN)\\\" \\\n-\t--abbrev-commit --abbrev=14 \\\"\\$1\\\" || true\" &&\n-\tgit config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" \\\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" \\\n \t\t--abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.fix.cmd \"test -n \\\"\\$1\\\" && git log -1 --oneline --format=\\\"%h (%aN)\\\" \\\n+\t--abbrev-commit --abbrev=14 \\\"\\$1\\\" || true\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tFIXED=$(git log -1 --oneline --format=\"%h (%aN)\" --abbrev-commit --abbrev=14 HEAD) &&\n \tcat complex_message_body >expected2 &&\n \tsed -e \"s/ Z\\$/ /\" >>expected2 <<-EOF &&\n@@ -1359,8 +1561,16 @@ test_expect_success 'cmd takes precedence over command' '\n '\n \n test_expect_success 'with command using $ARG' '\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" --abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" --abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tFIXED=$(git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 HEAD) &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-EOF &&\n@@ -1376,8 +1586,16 @@ test_expect_success 'with command using $ARG' '\n '\n \n test_expect_success 'with failing command using $ARG' '\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.command \"false \\$ARG\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"false \\$ARG\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-EOF &&\n \t\tFixes: Z\n@@ -1392,7 +1610,9 @@ test_expect_success 'with failing command using $ARG' '\n '\n \n test_expect_success 'with empty tokens' '\n-\tgit config --unset trailer.fix.command &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\tSigned-off-by: A U Thor <author@example.com>\n@@ -1403,7 +1623,8 @@ test_expect_success 'with empty tokens' '\n '\n \n test_expect_success 'with command but no key' '\n-\tgit config --unset trailer.sign.key &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\tsign: A U Thor <author@example.com>\n@@ -1414,7 +1635,9 @@ test_expect_success 'with command but no key' '\n '\n \n test_expect_success 'with no command and no key' '\n-\tgit config --unset trailer.review.key &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\treview: Junio\n@@ -1426,6 +1649,8 @@ test_expect_success 'with no command and no key' '\n '\n \n test_expect_success 'with cut line' '\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n \tcat >expected <<-\\EOF &&\n \t\tmy subject\n \n@@ -1443,7 +1668,8 @@ test_expect_success 'with cut line' '\n '\n \n test_expect_success 'only trailers' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-\\EOF &&\n \t\texisting: existing-value\n \t\tsign: config-value\n@@ -1462,7 +1688,7 @@ test_expect_success 'only trailers' '\n '\n \n test_expect_success 'only-trailers omits non-trailer in middle of block' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n \tcat >expected <<-\\EOF &&\n \t\tSigned-off-by: nobody <nobody@nowhere>\n \t\tSigned-off-by: somebody <somebody@somewhere>\n@@ -1482,7 +1708,7 @@ test_expect_success 'only-trailers omits non-trailer in middle of block' '\n '\n \n test_expect_success 'only input' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n \tcat >expected <<-\\EOF &&\n \t\texisting: existing-value\n \tEOF\n-- \ngitgitgadget\n\n"},{"id":"480492","messageId":"0df12c5c2dda5799074f0dcea696df0a63ca1145.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 04/13] trailer doc: narrow down scope of --where and related flags","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:54Z","receivedAt":"2023-08-10T21:18:17Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe wording \"all configuration variables\" is misleading (the same could\nbe said to the descriptions of the \"--[no-]if-exists\" and the\n\"--[no-]if-missing\" options).  Specifying --where=value overrides only\nthe trailer.where variable and applicable trailer.<token>.where\nvariables, and --no-where stops the overriding of these variables.\nDitto for the other two with their relevant configuration variables.\n\nReported-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 91a4dbc9a72..72f5bdb652f 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -112,7 +112,8 @@ OPTIONS\n --where <placement>::\n --no-where::\n \tSpecify where all new trailers will be added.  A setting\n-\tprovided with '--where' overrides all configuration variables\n+\tprovided with '--where' overrides the `trailer.where` and any\n+\tapplicable `trailer.<token>.where` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n \teffect of any previous use of '--where', such that the relevant configuration\n@@ -123,7 +124,8 @@ OPTIONS\n --no-if-exists::\n \tSpecify what action will be performed when there is already at\n \tleast one trailer with the same <token> in the input.  A setting\n-\tprovided with '--if-exists' overrides all configuration variables\n+\tprovided with '--if-exists' overrides the `trailer.ifExists` and any\n+\tapplicable `trailer.<token>.ifExists` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists, clear the\n \teffect of any previous use of '--if-exists, such that the relevant configuration\n@@ -134,7 +136,8 @@ OPTIONS\n --no-if-missing::\n \tSpecify what action will be performed when there is no other\n \ttrailer with the same <token> in the input.  A setting\n-\tprovided with '--if-missing' overrides all configuration variables\n+\tprovided with '--if-missing' overrides the `trailer.ifMissing` and any\n+\tapplicable `trailer.<token>.ifMissing` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing,\n \tclear the effect of any previous use of '--if-missing, such that the relevant\n-- \ngitgitgadget\n\n"},{"id":"480493","messageId":"4b5c458ef436c2d208e6d6d0a1f99c65e9a11125.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 03/13] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:53Z","receivedAt":"2023-08-10T21:18:18Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nWhile the \"--no-where\" flag is tested, the \"--no-if-exists\" and\n\"--no-if-missing\" flags are not, so add tests for them. But also add\ntests for all \"--no-*\" flags to check their effects, both when (1) there\nare relevant configuration variables set, and (2) they are not set.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt |  14 ++-\n t/t7513-interpret-trailers.sh            | 130 +++++++++++++++++++++++\n 2 files changed, 140 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 55d89614661..91a4dbc9a72 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -114,8 +114,10 @@ OPTIONS\n \tSpecify where all new trailers will be added.  A setting\n \tprovided with '--where' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--where' or '--no-where'. Possible values are `after`, `before`,\n-\t`end` or `start`.\n+\t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n+\teffect of any previous use of '--where', such that the relevant configuration\n+\tvariables are no longer overridden. Possible values are `after`,\n+\t`before`, `end` or `start`.\n \n --if-exists <action>::\n --no-if-exists::\n@@ -123,7 +125,9 @@ OPTIONS\n \tleast one trailer with the same <token> in the input.  A setting\n \tprovided with '--if-exists' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--if-exists' or '--no-if-exists'. Possible actions are `addIfDifferent`,\n+\t'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists, clear the\n+\teffect of any previous use of '--if-exists, such that the relevant configuration\n+\tvariables are no longer overridden. Possible actions are `addIfDifferent`,\n \t`addIfDifferentNeighbor`, `add`, `replace` and `doNothing`.\n \n --if-missing <action>::\n@@ -132,7 +136,9 @@ OPTIONS\n \ttrailer with the same <token> in the input.  A setting\n \tprovided with '--if-missing' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--if-missing' or '--no-if-missing'. Possible actions are `doNothing`\n+\t'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing,\n+\tclear the effect of any previous use of '--if-missing, such that the relevant\n+\tconfiguration variables are no longer overridden. Possible actions are `doNothing`\n \tor `add`.\n \n --only-trailers::\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex ed0fc04bd95..832aff06167 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -812,6 +812,53 @@ test_expect_success 'using \"--where after\" with \"--no-where\"' '\n \ttest_cmp expected actual\n '\n \n+# Check whether using \"--no-where\" clears out only the \"--where after\", such\n+# that we still use the configuration in trailer.where (which is different from\n+# the hardcoded default (in WHERE_END) assuming the absence of .gitconfig).\n+# Here, the \"start\" setting of trailer.where is respected, so the new \"Acked-by\"\n+# and \"Bug\" trailers are placed at the beginning, and not at the end which is\n+# the harcoded default.\n+test_expect_success 'using \"--where after\" with \"--no-where\" defaults to configuration' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.where \"start\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tBug #42\n+\t\tAcked-by= Peff\n+\t\tFixes: Z\n+\t\tAcked-by= Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --where after --no-where --trailer \"ack: Peff\" \\\n+\t\t--trailer \"bug: 42\" complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# The \"--where after\" will only get respected for the trailer that came\n+# immediately after it. For the next trailer (Bug #42), we default to using the\n+# hardcoded WHERE_END because we don't have any \"trailer.where\" or\n+# \"trailer.bug.where\" configured.\n+test_expect_success 'using \"--no-where\" defaults to harcoded default if nothing configured' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tFixes: Z\n+\t\tAcked-by= Z\n+\t\tAcked-by= Peff\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tBug #42\n+\tEOF\n+\tgit interpret-trailers --where after --trailer \"ack: Peff\" --no-where \\\n+\t\t--trailer \"bug: 42\" complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'using \"where = after\"' '\n \ttest_config trailer.ack.key \"Acked-by= \" &&\n \ttest_config trailer.ack.where \"after\" &&\n@@ -1176,6 +1223,56 @@ test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n \ttest_cmp expected actual\n '\n \n+# \"trailer.ifexists\" is set to \"doNothing\", so using \"--no-if-exists\" defaults\n+# to this \"doNothing\" behavior. So the \"Fixes: 53\" trailer does not get added.\n+test_expect_success 'using \"--if-exists replace\" with \"--no-if-exists\" defaults to configuration' '\n+\ttest_config trailer.ifexists \"doNothing\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tFixes: Z\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --no-if-exists --trailer \"Fixes: 53\" \\\n+\t\t<complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# No \"ifexists\" configuration is set, so using \"--no-if-exists\" makes it default\n+# to addIfDifferentNeighbor. Because we do have a different neighbor \"Fixes: 53\"\n+# (because it got added by overriding with \"--if-exists replace\" earlier in the\n+# arguments list), we add \"Signed-off-by: addme\".\n+test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tFixes: 53\n+\t\tSigned-off-by: addme\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n+\t\t--trailer \"Signed-off-by: addme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# The second \"Fixes: 53\" trailer is discarded, because the \"--no-if-exists\" here\n+# makes us default to addIfDifferentNeighbor, and we already added the \"Fixes:\n+# 53\" trailer earlier in the argument list.\n+test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured (no addition)' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tFixes: 53\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n+\t\t--trailer \"Fixes: 53\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'using \"ifExists = replace\"' '\n \ttest_config trailer.fix.key \"Fixes: \" &&\n \ttest_config trailer.fix.ifExists \"replace\" &&\n@@ -1425,6 +1522,39 @@ test_expect_success 'using \"ifMissing = doNothing\"' '\n \ttest_cmp expected actual\n '\n \n+# Ignore the \"IgnoredTrailer\" because of \"--if-missing doNothing\", but also\n+# ignore the \"StillIgnoredTrailer\" because we set \"trailer.ifMissing\" to\n+# \"doNothing\" in configuration.\n+test_expect_success 'using \"--no-if-missing\" defaults to configuration' '\n+\ttest_config trailer.ifMissing \"doNothing\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\t\tFixes: Z\n+\t\t\tAcked-by: Z\n+\t\t\tReviewed-by: Z\n+\t\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n+\t\t\t--trailer \"StillIgnoredTrailer: ignoreme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# Add the \"AddedTrailer\" because the \"--no-if-missing\" clears the \"--if-missing\n+# doNothing\" from earlier in the argument list.\n+test_expect_success 'using \"--no-if-missing\" defaults to hardcoded default if nothing configured' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\t\tFixes: Z\n+\t\t\tAcked-by: Z\n+\t\t\tReviewed-by: Z\n+\t\t\tSigned-off-by: Z\n+\t\t\tAddedTrailer: addme\n+\tEOF\n+\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n+\t\t\t--trailer \"AddedTrailer: addme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'default \"where\" is now \"after\"' '\n \tgit config trailer.where \"after\" &&\n \ttest_config trailer.ack.ifExists \"add\" &&\n-- \ngitgitgadget\n\n"},{"id":"480494","messageId":"040766861e21afe5f686299560677e429be11844.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 05/13] trailer: trailer location is a place, not an action","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:55Z","receivedAt":"2023-08-10T21:18:20Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nFix the help text to say \"placement\" instead of \"action\" because the\nvalues are placements, not actions.\n\nWhile we're at it, tweak the documentation to say \"placements\" instead\nof \"values\", similar to how the existing language for \"--if-exists\" uses\nthe word \"action\" to describe both the syntax (with the phrase\n\"--if-exists <action>\") and the possible values (with the phrase\n\"possible actions\").\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 2 +-\n builtin/interpret-trailers.c             | 2 +-\n 2 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 72f5bdb652f..b5284c3d33f 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -117,7 +117,7 @@ OPTIONS\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n \teffect of any previous use of '--where', such that the relevant configuration\n-\tvariables are no longer overridden. Possible values are `after`,\n+\tvariables are no longer overridden. Possible placements are `after`,\n \t`before`, `end` or `start`.\n \n --if-exists <action>::\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex c5e83452654..cf4f703c4e2 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -97,7 +97,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"in-place\", &opts.in_place, N_(\"edit files in place\")),\n \t\tOPT_BOOL(0, \"trim-empty\", &opts.trim_empty, N_(\"trim empty trailers\")),\n \n-\t\tOPT_CALLBACK(0, \"where\", NULL, N_(\"action\"),\n+\t\tOPT_CALLBACK(0, \"where\", NULL, N_(\"placement\"),\n \t\t\t     N_(\"where to place the new trailer\"), option_parse_where),\n \t\tOPT_CALLBACK(0, \"if-exists\", NULL, N_(\"action\"),\n \t\t\t     N_(\"action if trailer already exists\"), option_parse_if_exists),\n-- \ngitgitgadget\n\n"},{"id":"480495","messageId":"3e58b6f5ea264a2c42ffbd008405b46626e0f864.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 06/13] trailer --no-divider help: describe usual \"---\" meaning","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:56Z","receivedAt":"2023-08-10T21:18:21Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nIt's unclear what treating something \"specially\" means.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n builtin/interpret-trailers.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex cf4f703c4e2..a7623dbfb2e 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -109,7 +109,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"set parsing options\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n-\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat --- specially\")),\n+\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n \t\tOPT_CALLBACK(0, \"trailer\", &trailers, N_(\"trailer\"),\n \t\t\t\tN_(\"trailer(s) to add\"), option_parse_trailer),\n \t\tOPT_END()\n-- \ngitgitgadget\n\n"},{"id":"480496","messageId":"d1780a0127a749902d60249b531869ee9cd1a5f6.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 07/13] trailer --parse help: expose aliased options","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:57Z","receivedAt":"2023-08-10T21:18:22Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe existing description \"set parsing options\" is vague, because\narguably _all_ of the options for interpret-trailers have to do with\nparsing to some degree.\n\nExplain what this flag does to match what is in the docs, namely how\nit is an alias for \"--only-trailers --only-input --unfold\".\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n builtin/interpret-trailers.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex a7623dbfb2e..5f3e1a38eee 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -107,7 +107,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"only-trailers\", &opts.only_trailers, N_(\"output only the trailers\")),\n \t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply config rules\")),\n \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n-\t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"set parsing options\"),\n+\t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"alias for --only-trailers --only-input --unfold\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n \t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n \t\tOPT_CALLBACK(0, \"trailer\", &trailers, N_(\"trailer\"),\n-- \ngitgitgadget\n\n"},{"id":"480497","messageId":"ef6b77016cd50c438fb58d79ffb10f748ddc5244.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 09/13] trailer --parse docs: add explanation for its usefulness","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:59Z","receivedAt":"2023-08-10T21:18:24Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nFor users who are skimming the docs to go straight to the individual\nbreakdown of each flag, it may not be clear why --parse is a convenience\nalias (without them also looking at the other options that --parse turns\non). To save them the trouble of looking at the other options (and\ncomputing what that would mean), describe a summary of the overall\neffect.\n\nSimilarly update the area when we first mention --parse near the top of\nthe doc.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 9 +++++++--\n 1 file changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 0eea937c30e..2d49445b1c3 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -31,7 +31,9 @@ the last two lines starting with \"Signed-off-by\" are trailers.\n \n This command reads commit messages from either the\n <file> arguments or the standard input if no <file> is specified.\n-If `--parse` is specified, the output consists of the parsed trailers.\n+If `--parse` is specified, the output consists of the parsed trailers\n+coming from the input, without influencing them with any command line\n+options or configuration variables.\n Otherwise, this command applies the arguments passed using the\n `--trailer` option, if any, to each input file. The result is emitted on the\n standard output.\n@@ -158,7 +160,10 @@ OPTIONS\n \n --parse::\n \tA convenience alias for `--only-trailers --only-input\n-\t--unfold`.\n+\t--unfold`. This makes it easier to only see the trailers coming from the\n+\tinput without influencing them with any command line options or\n+\tconfiguration variables, while also making the output machine-friendly with\n+\t--unfold.\n \n --no-divider::\n \tDo not treat `---` as the end of the commit message. Use this\n-- \ngitgitgadget\n\n"},{"id":"480498","messageId":"a08d78618bac70c4bc72fa5c88fae08d9ed3ce52.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 10/13] trailer --unfold help: prefer \"reformat\" over \"join\"","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:18:00Z","receivedAt":"2023-08-10T21:18:25Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe phrase \"join whitespace-continued values\" requires some additional\ncontext. For example, \"whitespace\" means newlines (not just space\ncharacters), and \"join\" means to join only the multiple lines together\nfor a single trailer (and not that we are joining multiple trailers\ntogether). That is, \"join\" means to convert\n\n    token: This is a very long value, with spaces and\n      newlines in it.\n\nto\n\n    token: This is a very long value, with spaces and newlines in it.\n\nand does not mean to convert\n\n    token: value1\n    token: value2\n\nto\n\n    token: value1 value2.\n\nUpdate the help text to resolve the above ambiguity. While we're add it,\nupdate the docs to use similar language as the change in the help text.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 4 ++--\n builtin/interpret-trailers.c             | 2 +-\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 2d49445b1c3..62ba2b1232e 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -155,8 +155,8 @@ OPTIONS\n \tvariables.\n \n --unfold::\n-\tRemove any whitespace-continuation in trailers, so that each\n-\ttrailer appears on a line by itself with its full content.\n+\tIf a trailer has a value that runs over multiple lines (aka \"folded\"),\n+\treformat the value into a single line.\n \n --parse::\n \tA convenience alias for `--only-trailers --only-input\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex f70c5df8d4b..832f86a770a 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -106,7 +106,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \n \t\tOPT_BOOL(0, \"only-trailers\", &opts.only_trailers, N_(\"output only the trailers\")),\n \t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply trailer.* configuration variables\")),\n-\t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n+\t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"reformat multiline trailer values as single-line values\")),\n \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"alias for --only-trailers --only-input --unfold\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n \t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n-- \ngitgitgadget\n\n"},{"id":"480499","messageId":"5cfff52da8ff586248ba394248e7b086ed792549.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 08/13] trailer --only-input: prefer \"configuration variables\" over \"rules\"","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:17:58Z","receivedAt":"2023-08-10T21:18:27Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nUse the phrase \"configuration variables\" instead of \"rules\" because\n\n(1) we already say \"configuration variables\" in multiple\n    places in the docs (where the word \"rules\" is only used for describing\n    \"--only-input\" behavior and for an unrelated case of mentioning how\n    the trailers do not follow \"rules for RFC 822 headers\"), and\n\n(2) this phrase is more specific than just \"rules\".\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 4 ++--\n builtin/interpret-trailers.c             | 2 +-\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex b5284c3d33f..0eea937c30e 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -149,8 +149,8 @@ OPTIONS\n \n --only-input::\n \tOutput only trailers that exist in the input; do not add any\n-\tfrom the command-line or by following configured `trailer.*`\n-\trules.\n+\tfrom the command-line or by applying `trailer.*` configuration\n+\tvariables.\n \n --unfold::\n \tRemove any whitespace-continuation in trailers, so that each\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex 5f3e1a38eee..f70c5df8d4b 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -105,7 +105,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\t\t     N_(\"action if trailer is missing\"), option_parse_if_missing),\n \n \t\tOPT_BOOL(0, \"only-trailers\", &opts.only_trailers, N_(\"output only the trailers\")),\n-\t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply config rules\")),\n+\t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply trailer.* configuration variables\")),\n \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"alias for --only-trailers --only-input --unfold\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n-- \ngitgitgadget\n\n"},{"id":"480500","messageId":"4db823ac3549c031b61b5a0ec0efd56b70d2a45c.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 11/13] trailer doc: emphasize the effect of configuration variables","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:18:01Z","receivedAt":"2023-08-10T21:18:28Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe sentence does not mention the effect of configuration variables at\nall, when they are actively used by default (unless --parse is\nspecified) to potentially add new trailers, without the user having to\nalways supply --trailer manually.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 62ba2b1232e..a288ff111cb 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -34,9 +34,12 @@ This command reads commit messages from either the\n If `--parse` is specified, the output consists of the parsed trailers\n coming from the input, without influencing them with any command line\n options or configuration variables.\n-Otherwise, this command applies the arguments passed using the\n-`--trailer` option, if any, to each input file. The result is emitted on the\n-standard output.\n+\n+Otherwise, this command applies `trailer.*` configuration variables\n+(which could potentially add new trailers, as well as reposition them),\n+as well as any command line arguments that can override configuration\n+variables (such as `--trailer=...` which could also add new trailers),\n+to each input file. The result is emitted on the standard output.\n \n This command can also operate on the output of linkgit:git-format-patch[1],\n which is more elaborate than a plain commit message. Namely, such output\n-- \ngitgitgadget\n\n"},{"id":"480501","messageId":"66087eaf5bd2abc416628cdcf166b8bd7e9cbf2e.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 12/13] trailer doc: separator within key suppresses default separator","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:18:02Z","receivedAt":"2023-08-10T21:18:34Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex a288ff111cb..25433e1a1ff 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -255,8 +255,8 @@ trailer.<token>.key::\n \tbut this can be changed using the `trailer.separators` config\n \tvariable.\n +\n-If there is a separator, then the key will be used instead of both the\n-<token> and the default separator when adding the trailer.\n+If there is a separator in the key, then it overrides the default\n+separator when adding the trailer.\n \n trailer.<token>.where::\n \tThis option takes the same values as the 'trailer.where'\n-- \ngitgitgadget\n\n"},{"id":"480502","messageId":"7b66cf29d295ae2420c9f5d1469e1f02d490e559.1691702283.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v2 13/13] trailer doc: <token> is a <key> or <keyAlias>, not both","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-08-10T21:18:03Z","receivedAt":"2023-08-10T21:18:36Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe `--trailer` option takes a \"<token>=<value>\" argument, for example\n\n    --trailer \"Acked-by=Bob\"\n\nAnd in this exampple it is understood that \"Acked-by\" is the <token>.\nHowever, the user can use a shorter \"ack\" string by defining\nconfiguration like\n\n    git config trailer.ack.key \"Acked-by\"\n\nHowever, in the docs we define the above configuration as\n\n    trailer.<token>.key\n\nso the <token> can mean either the longer \"Acked-by\" or the shorter\n\"ack\".\n\nSeparate the two meanings of <token> into <key> and <keyAlias>, and\nupdate the configuration syntax to say \"trailer.<keyAlias>.key\".\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 136 +++++++++++++----------\n 1 file changed, 76 insertions(+), 60 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 25433e1a1ff..418265f044d 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git interpret-trailers' [--in-place] [--trim-empty]\n-\t\t\t[(--trailer <token>[(=|:)<value>])...]\n+\t\t\t[(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n \t\t\t[--parse] [<file>...]\n \n DESCRIPTION\n@@ -53,22 +53,32 @@ are applied to each input and the way any existing trailer in\n the input is changed. They also make it possible to\n automatically add some trailers.\n \n-By default, a '<token>=<value>' or '<token>:<value>' argument given\n+By default, a '<key>=<value>' or '<key>:<value>' argument given\n using `--trailer` will be appended after the existing trailers only if\n-the last trailer has a different (<token>, <value>) pair (or if there\n-is no existing trailer). The <token> and <value> parts will be trimmed\n+the last trailer has a different (<key>, <value>) pair (or if there\n+is no existing trailer). The <key> and <value> parts will be trimmed\n to remove starting and trailing whitespace, and the resulting trimmed\n-<token> and <value> will appear in the output like this:\n+<key> and <value> will appear in the output like this:\n \n ------------------------------------------------\n-token: value\n+key: value\n ------------------------------------------------\n \n-This means that the trimmed <token> and <value> will be separated by\n-`': '` (one colon followed by one space). For convenience, the <token> can be a\n-shortened string key (e.g., \"sign\") instead of the full string which should\n-appear before the separator on the output (e.g., \"Signed-off-by\"). This can be\n-configured using the 'trailer.<token>.key' configuration variable.\n+This means that the trimmed <key> and <value> will be separated by\n+`': '` (one colon followed by one space).\n+\n+For convenience, a <keyAlias> can be configured to make using `--trailer`\n+shorter to type on the command line. This can be configured using the\n+'trailer.<keyAlias>.key' configuration variable. The <keyAlias> must be a prefix\n+of the full <key> string, although case sensitivity does not matter. For\n+example, if you have\n+\n+------------------------------------------------\n+trailer.sign.key \"Signed-off-by: \"\n+------------------------------------------------\n+\n+in your configuration, you only need to specify `--trailer=\"sign: foo\"`\n+on the command line instead of `--trailer=\"Signed-off-by: foo\"`.\n \n By default the new trailer will appear at the end of all the existing\n trailers. If there is no existing trailer, the new trailer will appear\n@@ -85,14 +95,14 @@ non-whitespace lines before a line that starts with '---' (followed by a\n space or the end of the line).\n \n When reading trailers, there can be no whitespace before or inside the\n-<token>, but any number of regular space and tab characters are allowed\n-between the <token> and the separator. There can be whitespaces before,\n+<key>, but any number of regular space and tab characters are allowed\n+between the <key> and the separator. There can be whitespaces before,\n inside or after the <value>. The <value> may be split over multiple lines\n with each subsequent line starting with at least one whitespace, like\n the \"folding\" in RFC 822. Example:\n \n ------------------------------------------------\n-token: This is a very long value, with spaces and\n+key: This is a very long value, with spaces and\n   newlines in it.\n ------------------------------------------------\n \n@@ -109,8 +119,8 @@ OPTIONS\n \tthe whole trailer will be removed from the output.\n \tThis applies to existing trailers as well as new trailers.\n \n---trailer <token>[(=|:)<value>]::\n-\tSpecify a (<token>, <value>) pair that should be applied as a\n+--trailer <key>[(=|:)<value>]::\n+\tSpecify a (<key>, <value>) pair that should be applied as a\n \ttrailer to the inputs. See the description of this\n \tcommand.\n \n@@ -118,7 +128,7 @@ OPTIONS\n --no-where::\n \tSpecify where all new trailers will be added.  A setting\n \tprovided with '--where' overrides the `trailer.where` and any\n-\tapplicable `trailer.<token>.where` configuration variables\n+\tapplicable `trailer.<keyAlias>.where` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n \teffect of any previous use of '--where', such that the relevant configuration\n@@ -128,9 +138,9 @@ OPTIONS\n --if-exists <action>::\n --no-if-exists::\n \tSpecify what action will be performed when there is already at\n-\tleast one trailer with the same <token> in the input.  A setting\n+\tleast one trailer with the same <key> in the input.  A setting\n \tprovided with '--if-exists' overrides the `trailer.ifExists` and any\n-\tapplicable `trailer.<token>.ifExists` configuration variables\n+\tapplicable `trailer.<keyAlias>.ifExists` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists, clear the\n \teffect of any previous use of '--if-exists, such that the relevant configuration\n@@ -140,9 +150,9 @@ OPTIONS\n --if-missing <action>::\n --no-if-missing::\n \tSpecify what action will be performed when there is no other\n-\ttrailer with the same <token> in the input.  A setting\n+\ttrailer with the same <key> in the input.  A setting\n \tprovided with '--if-missing' overrides the `trailer.ifMissing` and any\n-\tapplicable `trailer.<token>.ifMissing` configuration variables\n+\tapplicable `trailer.<keyAlias>.ifMissing` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing,\n \tclear the effect of any previous use of '--if-missing, such that the relevant\n@@ -187,11 +197,11 @@ used when another separator is not specified in the config for this\n trailer.\n +\n For example, if the value for this option is \"%=$\", then only lines\n-using the format '<token><sep><value>' with <sep> containing '%', '='\n+using the format '<key><sep><value>' with <sep> containing '%', '='\n or '$' and then spaces will be considered trailers. And '%' will be\n the default separator used, so by default trailers will appear like:\n-'<token>% <value>' (one percent sign and one space will appear between\n-the token and the value).\n+'<key>% <value>' (one percent sign and one space will appear between\n+the key and the value).\n \n trailer.where::\n \tThis option tells where a new trailer will be added.\n@@ -205,41 +215,41 @@ If it is `start`, then each new trailer will appear at the start,\n instead of the end, of the existing trailers.\n +\n If it is `after`, then each new trailer will appear just after the\n-last trailer with the same <token>.\n+last trailer with the same <key>.\n +\n If it is `before`, then each new trailer will appear just before the\n-first trailer with the same <token>.\n+first trailer with the same <key>.\n \n trailer.ifexists::\n \tThis option makes it possible to choose what action will be\n \tperformed when there is already at least one trailer with the\n-\tsame <token> in the input.\n+\tsame <key> in the input.\n +\n The valid values for this option are: `addIfDifferentNeighbor` (this\n is the default), `addIfDifferent`, `add`, `replace` or `doNothing`.\n +\n With `addIfDifferentNeighbor`, a new trailer will be added only if no\n-trailer with the same (<token>, <value>) pair is above or below the line\n+trailer with the same (<key>, <value>) pair is above or below the line\n where the new trailer will be added.\n +\n With `addIfDifferent`, a new trailer will be added only if no trailer\n-with the same (<token>, <value>) pair is already in the input.\n+with the same (<key>, <value>) pair is already in the input.\n +\n With `add`, a new trailer will be added, even if some trailers with\n-the same (<token>, <value>) pair are already in the input.\n+the same (<key>, <value>) pair are already in the input.\n +\n-With `replace`, an existing trailer with the same <token> will be\n+With `replace`, an existing trailer with the same <key> will be\n deleted and the new trailer will be added. The deleted trailer will be\n-the closest one (with the same <token>) to the place where the new one\n+the closest one (with the same <key>) to the place where the new one\n will be added.\n +\n With `doNothing`, nothing will be done; that is no new trailer will be\n-added if there is already one with the same <token> in the input.\n+added if there is already one with the same <key> in the input.\n \n trailer.ifmissing::\n \tThis option makes it possible to choose what action will be\n \tperformed when there is not yet any trailer with the same\n-\t<token> in the input.\n+\t<key> in the input.\n +\n The valid values for this option are: `add` (this is the default) and\n `doNothing`.\n@@ -248,34 +258,40 @@ With `add`, a new trailer will be added.\n +\n With `doNothing`, nothing will be done.\n \n-trailer.<token>.key::\n-\tThis `key` will be used instead of <token> in the trailer. At\n-\tthe end of this key, a separator can appear and then some\n-\tspace characters. By default the only valid separator is ':',\n-\tbut this can be changed using the `trailer.separators` config\n-\tvariable.\n+trailer.<keyAlias>.key::\n+\tDefines a <keyAlias> for the <key>. The <keyAlias> must be a\n+\tprefix (case does not matter) of the <key>. For example, in `git\n+\tconfig trailer.ack.key \"Acked-by\"` the \"Acked-by\" is the <key> and\n+\tthe \"ack\" is the <keyAlias>. This configuration allows the shorter\n+\t`--trailer \"ack:...\"` invocation on the command line using the \"ack\"\n+\t<keyAlias> instead of the longer `--trailer \"Acked-by:...\"`.\n++\n+At the end of the <key>, a separator can appear and then some\n+space characters. By default the only valid separator is ':',\n+but this can be changed using the `trailer.separators` config\n+variable.\n +\n If there is a separator in the key, then it overrides the default\n separator when adding the trailer.\n \n-trailer.<token>.where::\n+trailer.<keyAlias>.where::\n \tThis option takes the same values as the 'trailer.where'\n \tconfiguration variable and it overrides what is specified by\n-\tthat option for trailers with the specified <token>.\n+\tthat option for trailers with the specified <keyAlias>.\n \n-trailer.<token>.ifexists::\n+trailer.<keyAlias>.ifexists::\n \tThis option takes the same values as the 'trailer.ifexists'\n \tconfiguration variable and it overrides what is specified by\n-\tthat option for trailers with the specified <token>.\n+\tthat option for trailers with the specified <keyAlias>.\n \n-trailer.<token>.ifmissing::\n+trailer.<keyAlias>.ifmissing::\n \tThis option takes the same values as the 'trailer.ifmissing'\n \tconfiguration variable and it overrides what is specified by\n-\tthat option for trailers with the specified <token>.\n+\tthat option for trailers with the specified <keyAlias>.\n \n-trailer.<token>.command::\n-\tDeprecated in favor of 'trailer.<token>.cmd'.\n-\tThis option behaves in the same way as 'trailer.<token>.cmd', except\n+trailer.<keyAlias>.command::\n+\tDeprecated in favor of 'trailer.<keyAlias>.cmd'.\n+\tThis option behaves in the same way as 'trailer.<keyAlias>.cmd', except\n \tthat it doesn't pass anything as argument to the specified command.\n \tInstead the first occurrence of substring $ARG is replaced by the\n \t<value> that would be passed as argument.\n@@ -283,29 +299,29 @@ trailer.<token>.command::\n Note that $ARG in the user's command is\n only replaced once and that the original way of replacing $ARG is not safe.\n +\n-When both 'trailer.<token>.cmd' and 'trailer.<token>.command' are given\n-for the same <token>, 'trailer.<token>.cmd' is used and\n-'trailer.<token>.command' is ignored.\n+When both 'trailer.<keyAlias>.cmd' and 'trailer.<keyAlias>.command' are given\n+for the same <keyAlias>, 'trailer.<keyAlias>.cmd' is used and\n+'trailer.<keyAlias>.command' is ignored.\n \n-trailer.<token>.cmd::\n+trailer.<keyAlias>.cmd::\n \tThis option can be used to specify a shell command that will be called\n-\tonce to automatically add a trailer with the specified <token>, and then\n-\tcalled each time a '--trailer <token>=<value>' argument is specified to\n+\tonce to automatically add a trailer with the specified <keyAlias>, and then\n+\tcalled each time a '--trailer <keyAlias>=<value>' argument is specified to\n \tmodify the <value> of the trailer that this option would produce.\n +\n When the specified command is first called to add a trailer\n-with the specified <token>, the behavior is as if a special\n-'--trailer <token>=<value>' argument was added at the beginning\n+with the specified <keyAlias>, the behavior is as if a special\n+'--trailer <keyAlias>=<value>' argument was added at the beginning\n of the \"git interpret-trailers\" command, where <value>\n is taken to be the standard output of the command with any\n leading and trailing whitespace trimmed off.\n +\n-If some '--trailer <token>=<value>' arguments are also passed\n+If some '--trailer <keyAlias>=<value>' arguments are also passed\n on the command line, the command is called again once for each\n-of these arguments with the same <token>. And the <value> part\n+of these arguments with the same <keyAlias>. And the <value> part\n of these arguments, if any, will be passed to the command as its\n first argument. This way the command can produce a <value> computed\n-from the <value> passed in the '--trailer <token>=<value>' argument.\n+from the <value> passed in the '--trailer <keyAlias>=<value>' argument.\n \n EXAMPLES\n --------\n-- \ngitgitgadget\n"},{"id":"480523","messageId":"xmqq7cq2pd7o.fsf@gitster.g","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 00/13] Fixes to trailer test script, help text, and documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-08-11T01:41:47Z","receivedAt":"2023-08-11T01:41:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"t0450 dies like the attached, probably because the documentation was\nupdated to say \"<key> or <keyAlias>\" but a matching update to the\noutput of \"interpret-trailers -h\" command help is missing?\n\nA possible trivial fix to 13/13 will be queued on top as \"SQUASH???\"\npatch for now.\n\n builtin/interpret-trailers.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git c/builtin/interpret-trailers.c w/builtin/interpret-trailers.c\nindex 832f86a770..d2d78fd961 100644\n--- c/builtin/interpret-trailers.c\n+++ w/builtin/interpret-trailers.c\n@@ -14,7 +14,7 @@\n \n static const char * const git_interpret_trailers_usage[] = {\n \tN_(\"git interpret-trailers [--in-place] [--trim-empty]\\n\"\n-\t   \"                       [(--trailer <token>[(=|:)<value>])...]\\n\"\n+\t   \"                       [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\\n\"\n \t   \"                       [--parse] [<file>...]\"),\n \tNULL\n };\n\n\n\n\n\n--- txt 2023-08-10 22:31:54.328609532 +0000\n+++ help        2023-08-10 22:31:54.332609929 +0000\n@@ -1,3 +1,3 @@\n git interpret-trailers [--in-place] [--trim-empty]\n-                       [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n+                       [(--trailer <token>[(=|:)<value>])...]\n                        [--parse] [<file>...]\nnot ok 302 - interpret-trailers -h output and SYNOPSIS agree\n#\n#                       t2s=\"$(txt_to_synopsis \"$builtin\")\" &&\n#                       if test \"$builtin\" = \"merge-tree\"\n#                       then\n#                               test_when_finished \"rm -f t2s.new\" &&\n#                               sed -e 's/ (deprecated)$//g' <\"$t2s\" >t2s.new\n#                               t2s=t2s.new\n#                       fi &&\n#                       h2s=\"$(help_to_synopsis \"$builtin\")\" &&\n#\n#                       # The *.txt and -h use different spacing for the\n#                       # alignment of continued usage output, normalize it.\n#                       align_after_nl \"$builtin\" <\"$t2s\" >txt &&\n#                       align_after_nl \"$builtin\" <\"$h2s\" >help &&\n#                       test_cmp txt help\n#\n1\n"},{"id":"480560","messageId":"owlyh6p5fpi7.fsf@fine.c.googlers.com","threadId":"60067","inReplyTo":"xmqq7cq2pd7o.fsf@gitster.g","subject":"Re: [PATCH v2 00/13] Fixes to trailer test script, help text, and documentation","fromName":"Linus Arver","fromEmail":"linusa@google.com","sentAt":"2023-08-11T17:38:40Z","receivedAt":"2023-08-11T17:38:44Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> t0450 dies like the attached, probably because the documentation was\n> updated to say \"<key> or <keyAlias>\" but a matching update to the\n> output of \"interpret-trailers -h\" command help is missing?\n\nYes, sorry I missed this. I already have made the fix locally.\n\n> A possible trivial fix to 13/13 will be queued on top as \"SQUASH???\"\n> patch for now.\n\nThanks.\n"},{"id":"481530","messageId":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v2.git.1691702283.gitgitgadget@gmail.com","subject":"[PATCH v3 00/13] Fixes to trailer test script, help text, and documentation","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:19:56Z","receivedAt":"2023-09-07T22:20:15Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"This series contains various fixes to the trailer code. They pertain to\nfixes to the test script, the command line help text for the\ninterpret-trailers builtin, and the documentation.\n\nPatch 1 is the most important as it does cleanups in the tests where we used\n'git config' in a test case without cleaning up that state for the next\ntest. This makes the tests self-contained, making it easier to add new tests\nanywhere along the script, without worrying about previously-set implicit\nstate. These test cleanups exposed lots of cases where the test cases are\nmutating more configuration state than is necessary to test the specific\nbehavior in the test; however such extraneous configurations were not\ncleaned up to make these patches easier to review (again, we are not\nchanging any behavior and we are also not changing what the test cases\nthemselves purport to do).\n\nNote that Patch 1 was originally a 22-commit series, but was squashed\ntogether to make it easier to see the final diff for each test case. You can\nsee the 22-commit breakdown at\nhttps://github.com/listx/git/tree/backup-trailer-22-commit-breakdown\n\nPatch 3 adds some tests to check the behavior of '--no-if-exists' and\n'--no-if-missing', which weren't previously tested. It also adds\nsimilarly-themed test cases for '--no-where' which only had 1 test case for\nit.\n\nThe other patches aren't as important, but are included here because I think\nthey are too small to include in a separate series.\n\n\nUpdates in v3\n=============\n\n * Fix t0450 failure due to mismatch between the updated documentation which\n   uses \" or \" and the help text of the interpret-trailers command.\n\n\nUpdates in v2\n=============\n\n * Many additional patches to fix the help text and docs. No changes to any\n   of the patches touching the actual tests (that is, Patch 1 and 3 have\n   stayed the same, other than a rewording of the commit message for Patch\n   1).\n * Of these new patches, I think the last one (about <keyAlias>) is the most\n   important as it resolves a longtime ambiguity about what a <token> can\n   be.\n\nLinus Arver (13):\n  trailer tests: make test cases self-contained\n  trailer test description: this tests --where=after, not --where=before\n  trailer: add tests to check defaulting behavior with --no-* flags\n  trailer doc: narrow down scope of --where and related flags\n  trailer: trailer location is a place, not an action\n  trailer --no-divider help: describe usual \"---\" meaning\n  trailer --parse help: expose aliased options\n  trailer --only-input: prefer \"configuration variables\" over \"rules\"\n  trailer --parse docs: add explanation for its usefulness\n  trailer --unfold help: prefer \"reformat\" over \"join\"\n  trailer doc: emphasize the effect of configuration variables\n  trailer doc: separator within key suppresses default separator\n  trailer doc: <token> is a <key> or <keyAlias>, not both\n\n Documentation/git-interpret-trailers.txt | 183 ++++----\n builtin/interpret-trailers.c             |  12 +-\n t/t7513-interpret-trailers.sh            | 506 +++++++++++++++++++----\n 3 files changed, 545 insertions(+), 156 deletions(-)\n\n\nbase-commit: 1b0a5129563ebe720330fdc8f5c6843d27641137\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1564%2Flistx%2Ftrailer-fixes-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1564/listx/trailer-fixes-v3\nPull-Request: https://github.com/gitgitgadget/git/pull/1564\n\nRange-diff vs v2:\n\n  1:  1623dd000dd =  1:  1623dd000dd trailer tests: make test cases self-contained\n  2:  f680e76de84 =  2:  f680e76de84 trailer test description: this tests --where=after, not --where=before\n  3:  4b5c458ef43 =  3:  4b5c458ef43 trailer: add tests to check defaulting behavior with --no-* flags\n  4:  0df12c5c2dd =  4:  0df12c5c2dd trailer doc: narrow down scope of --where and related flags\n  5:  040766861e2 =  5:  040766861e2 trailer: trailer location is a place, not an action\n  6:  3e58b6f5ea2 =  6:  3e58b6f5ea2 trailer --no-divider help: describe usual \"---\" meaning\n  7:  d1780a0127a =  7:  d1780a0127a trailer --parse help: expose aliased options\n  8:  5cfff52da8f =  8:  5cfff52da8f trailer --only-input: prefer \"configuration variables\" over \"rules\"\n  9:  ef6b77016cd =  9:  ef6b77016cd trailer --parse docs: add explanation for its usefulness\n 10:  a08d78618ba = 10:  a08d78618ba trailer --unfold help: prefer \"reformat\" over \"join\"\n 11:  4db823ac354 = 11:  4db823ac354 trailer doc: emphasize the effect of configuration variables\n 12:  66087eaf5bd = 12:  66087eaf5bd trailer doc: separator within key suppresses default separator\n 13:  7b66cf29d29 ! 13:  0b9525db5a0 trailer doc: <token> is a <key> or <keyAlias>, not both\n     @@ Documentation/git-interpret-trailers.txt: trailer.<token>.command::\n       \n       EXAMPLES\n       --------\n     +\n     + ## builtin/interpret-trailers.c ##\n     +@@\n     + \n     + static const char * const git_interpret_trailers_usage[] = {\n     + \tN_(\"git interpret-trailers [--in-place] [--trim-empty]\\n\"\n     +-\t   \"                       [(--trailer <token>[(=|:)<value>])...]\\n\"\n     ++\t   \"                       [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\\n\"\n     + \t   \"                       [--parse] [<file>...]\"),\n     + \tNULL\n     + };\n\n-- \ngitgitgadget\n"},{"id":"481531","messageId":"f680e76de847cf88fc4e4d63844829c6b344a697.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 02/13] trailer test description: this tests --where=after, not --where=before","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:19:58Z","receivedAt":"2023-09-07T22:20:19Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n t/t7513-interpret-trailers.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex 5b31896070a..ed0fc04bd95 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -792,7 +792,7 @@ test_expect_success 'overriding configuration with \"--where after\"' '\n \ttest_cmp expected actual\n '\n \n-test_expect_success 'using \"where = before\" with \"--no-where\"' '\n+test_expect_success 'using \"--where after\" with \"--no-where\"' '\n \ttest_config trailer.ack.key \"Acked-by= \" &&\n \ttest_config trailer.ack.where \"before\" &&\n \ttest_config trailer.bug.key \"Bug #\" &&\n-- \ngitgitgadget\n\n"},{"id":"481532","messageId":"4b5c458ef436c2d208e6d6d0a1f99c65e9a11125.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 03/13] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:19:59Z","receivedAt":"2023-09-07T22:20:20Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nWhile the \"--no-where\" flag is tested, the \"--no-if-exists\" and\n\"--no-if-missing\" flags are not, so add tests for them. But also add\ntests for all \"--no-*\" flags to check their effects, both when (1) there\nare relevant configuration variables set, and (2) they are not set.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt |  14 ++-\n t/t7513-interpret-trailers.sh            | 130 +++++++++++++++++++++++\n 2 files changed, 140 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 55d89614661..91a4dbc9a72 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -114,8 +114,10 @@ OPTIONS\n \tSpecify where all new trailers will be added.  A setting\n \tprovided with '--where' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--where' or '--no-where'. Possible values are `after`, `before`,\n-\t`end` or `start`.\n+\t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n+\teffect of any previous use of '--where', such that the relevant configuration\n+\tvariables are no longer overridden. Possible values are `after`,\n+\t`before`, `end` or `start`.\n \n --if-exists <action>::\n --no-if-exists::\n@@ -123,7 +125,9 @@ OPTIONS\n \tleast one trailer with the same <token> in the input.  A setting\n \tprovided with '--if-exists' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--if-exists' or '--no-if-exists'. Possible actions are `addIfDifferent`,\n+\t'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists, clear the\n+\teffect of any previous use of '--if-exists, such that the relevant configuration\n+\tvariables are no longer overridden. Possible actions are `addIfDifferent`,\n \t`addIfDifferentNeighbor`, `add`, `replace` and `doNothing`.\n \n --if-missing <action>::\n@@ -132,7 +136,9 @@ OPTIONS\n \ttrailer with the same <token> in the input.  A setting\n \tprovided with '--if-missing' overrides all configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n-\t'--if-missing' or '--no-if-missing'. Possible actions are `doNothing`\n+\t'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing,\n+\tclear the effect of any previous use of '--if-missing, such that the relevant\n+\tconfiguration variables are no longer overridden. Possible actions are `doNothing`\n \tor `add`.\n \n --only-trailers::\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex ed0fc04bd95..832aff06167 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -812,6 +812,53 @@ test_expect_success 'using \"--where after\" with \"--no-where\"' '\n \ttest_cmp expected actual\n '\n \n+# Check whether using \"--no-where\" clears out only the \"--where after\", such\n+# that we still use the configuration in trailer.where (which is different from\n+# the hardcoded default (in WHERE_END) assuming the absence of .gitconfig).\n+# Here, the \"start\" setting of trailer.where is respected, so the new \"Acked-by\"\n+# and \"Bug\" trailers are placed at the beginning, and not at the end which is\n+# the harcoded default.\n+test_expect_success 'using \"--where after\" with \"--no-where\" defaults to configuration' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.where \"start\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tBug #42\n+\t\tAcked-by= Peff\n+\t\tFixes: Z\n+\t\tAcked-by= Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --where after --no-where --trailer \"ack: Peff\" \\\n+\t\t--trailer \"bug: 42\" complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# The \"--where after\" will only get respected for the trailer that came\n+# immediately after it. For the next trailer (Bug #42), we default to using the\n+# hardcoded WHERE_END because we don't have any \"trailer.where\" or\n+# \"trailer.bug.where\" configured.\n+test_expect_success 'using \"--no-where\" defaults to harcoded default if nothing configured' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tFixes: Z\n+\t\tAcked-by= Z\n+\t\tAcked-by= Peff\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tBug #42\n+\tEOF\n+\tgit interpret-trailers --where after --trailer \"ack: Peff\" --no-where \\\n+\t\t--trailer \"bug: 42\" complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'using \"where = after\"' '\n \ttest_config trailer.ack.key \"Acked-by= \" &&\n \ttest_config trailer.ack.where \"after\" &&\n@@ -1176,6 +1223,56 @@ test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n \ttest_cmp expected actual\n '\n \n+# \"trailer.ifexists\" is set to \"doNothing\", so using \"--no-if-exists\" defaults\n+# to this \"doNothing\" behavior. So the \"Fixes: 53\" trailer does not get added.\n+test_expect_success 'using \"--if-exists replace\" with \"--no-if-exists\" defaults to configuration' '\n+\ttest_config trailer.ifexists \"doNothing\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tFixes: Z\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --no-if-exists --trailer \"Fixes: 53\" \\\n+\t\t<complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# No \"ifexists\" configuration is set, so using \"--no-if-exists\" makes it default\n+# to addIfDifferentNeighbor. Because we do have a different neighbor \"Fixes: 53\"\n+# (because it got added by overriding with \"--if-exists replace\" earlier in the\n+# arguments list), we add \"Signed-off-by: addme\".\n+test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tFixes: 53\n+\t\tSigned-off-by: addme\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n+\t\t--trailer \"Signed-off-by: addme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# The second \"Fixes: 53\" trailer is discarded, because the \"--no-if-exists\" here\n+# makes us default to addIfDifferentNeighbor, and we already added the \"Fixes:\n+# 53\" trailer earlier in the argument list.\n+test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured (no addition)' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\tAcked-by: Z\n+\t\tReviewed-by: Z\n+\t\tSigned-off-by: Z\n+\t\tFixes: 53\n+\tEOF\n+\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n+\t\t--trailer \"Fixes: 53\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'using \"ifExists = replace\"' '\n \ttest_config trailer.fix.key \"Fixes: \" &&\n \ttest_config trailer.fix.ifExists \"replace\" &&\n@@ -1425,6 +1522,39 @@ test_expect_success 'using \"ifMissing = doNothing\"' '\n \ttest_cmp expected actual\n '\n \n+# Ignore the \"IgnoredTrailer\" because of \"--if-missing doNothing\", but also\n+# ignore the \"StillIgnoredTrailer\" because we set \"trailer.ifMissing\" to\n+# \"doNothing\" in configuration.\n+test_expect_success 'using \"--no-if-missing\" defaults to configuration' '\n+\ttest_config trailer.ifMissing \"doNothing\" &&\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\t\tFixes: Z\n+\t\t\tAcked-by: Z\n+\t\t\tReviewed-by: Z\n+\t\t\tSigned-off-by: Z\n+\tEOF\n+\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n+\t\t\t--trailer \"StillIgnoredTrailer: ignoreme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+# Add the \"AddedTrailer\" because the \"--no-if-missing\" clears the \"--if-missing\n+# doNothing\" from earlier in the argument list.\n+test_expect_success 'using \"--no-if-missing\" defaults to hardcoded default if nothing configured' '\n+\tcat complex_message_body >expected &&\n+\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n+\t\t\tFixes: Z\n+\t\t\tAcked-by: Z\n+\t\t\tReviewed-by: Z\n+\t\t\tSigned-off-by: Z\n+\t\t\tAddedTrailer: addme\n+\tEOF\n+\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n+\t\t\t--trailer \"AddedTrailer: addme\" <complex_message >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'default \"where\" is now \"after\"' '\n \tgit config trailer.where \"after\" &&\n \ttest_config trailer.ack.ifExists \"add\" &&\n-- \ngitgitgadget\n\n"},{"id":"481534","messageId":"1623dd000ddef40ffb6ca44cf7ce66d1c42b0d13.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 01/13] trailer tests: make test cases self-contained","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:19:57Z","receivedAt":"2023-09-07T22:20:22Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nBy using \"test_config\" instead of \"git config\", we avoid leaking\nconfiguration state across test cases. This in turn helps to make the\ntests more self-contained, by explicitly capturing the configuration\nsetup. It then makes it easier to add tests anywhere in this 1500+ line\nfile, without worrying about what implicit state was set in some prior\ntest case defined earlier up in the script.\n\nThis commit was created mechanically as follows: we changed the first\noccurrence of a particular \"git config trailer.*\" option, then ran the\ntests repeatedly to see which ones broke, adding in the extra\n\"test_config\" equivalents to make them pass again. In addition, in some\ntest cases we removed \"git config --unset ...\" lines because they were\nno longer necessary (as the --unset was being used to clean up leaked\nconfiguration state from earlier test cases).\n\nThe process described above was done repeatedly until there were no more\nunbridled \"git config\" invocations. Some \"git config\" invocations still\ndo exist in the script, but they were already cleaned up properly with\n\n    test_when_finished \"git config --remove-section ...\"\n\nso they were left alone.\n\nNote that these cleanups result in generally longer test case setups\nbecause the previously hidden state is now being exposed. Although we\ncould then clean up the test cases' \"expected\" values to be less\nverbose (the verbosity arising from the use of implicit state), we\nchoose not to do so here, to make sure that this cleanup does not change\nany meanings behind the test cases.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n t/t7513-interpret-trailers.sh | 374 +++++++++++++++++++++++++++-------\n 1 file changed, 300 insertions(+), 74 deletions(-)\n\ndiff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\nindex 97f10905d23..5b31896070a 100755\n--- a/t/t7513-interpret-trailers.sh\n+++ b/t/t7513-interpret-trailers.sh\n@@ -489,7 +489,7 @@ test_expect_success 'multiline field treated as atomic for neighbor check' '\n '\n \n test_expect_success 'with config setup' '\n-\tgit config trailer.ack.key \"Acked-by: \" &&\n+\ttest_config trailer.ack.key \"Acked-by: \" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tAcked-by: Peff\n@@ -503,8 +503,8 @@ test_expect_success 'with config setup' '\n '\n \n test_expect_success 'with config setup and \":=\" as separators' '\n-\tgit config trailer.separators \":=\" &&\n-\tgit config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tAcked-by= Peff\n@@ -518,7 +518,7 @@ test_expect_success 'with config setup and \":=\" as separators' '\n '\n \n test_expect_success 'with config setup and \"%\" as separators' '\n-\tgit config trailer.separators \"%\" &&\n+\ttest_config trailer.separators \"%\" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tbug% 42\n@@ -532,6 +532,7 @@ test_expect_success 'with config setup and \"%\" as separators' '\n '\n \n test_expect_success 'with \"%\" as separators and a message with trailers' '\n+\ttest_config trailer.separators \"%\" &&\n \tcat >special_message <<-\\EOF &&\n \t\tSpecial Message\n \n@@ -553,8 +554,8 @@ test_expect_success 'with \"%\" as separators and a message with trailers' '\n '\n \n test_expect_success 'with config setup and \":=#\" as separators' '\n-\tgit config trailer.separators \":=#\" &&\n-\tgit config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat >expected <<-\\EOF &&\n \n \t\tBug #42\n@@ -581,6 +582,8 @@ test_expect_success 'with basic patch' '\n '\n \n test_expect_success 'with commit complex message as argument' '\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat complex_message_body complex_message_trailers >complex_message &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n@@ -594,6 +597,8 @@ test_expect_success 'with commit complex message as argument' '\n '\n \n test_expect_success 'with 2 files arguments' '\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n \tcat basic_message >>expected &&\n \techo >>expected &&\n \tcat basic_patch >>expected &&\n@@ -677,6 +682,9 @@ test_expect_success 'with message that has an old style conflict block' '\n '\n \n test_expect_success 'with commit complex message and trailer args' '\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -692,6 +700,9 @@ test_expect_success 'with commit complex message and trailer args' '\n '\n \n test_expect_success 'with complex patch, args and --trim-empty' '\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n \tcat complex_message >complex_patch &&\n \tcat basic_patch >>complex_patch &&\n \tcat complex_message_body >expected &&\n@@ -746,7 +757,10 @@ test_expect_success POSIXPERM,SANITY \"in-place editing doesn't clobber original\n '\n \n test_expect_success 'using \"where = before\"' '\n-\tgit config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -762,7 +776,9 @@ test_expect_success 'using \"where = before\"' '\n '\n \n test_expect_success 'overriding configuration with \"--where after\"' '\n-\tgit config trailer.ack.where \"before\" &&\n+\ttest_config trailer.separators \":=\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -777,6 +793,11 @@ test_expect_success 'overriding configuration with \"--where after\"' '\n '\n \n test_expect_success 'using \"where = before\" with \"--no-where\"' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -792,7 +813,11 @@ test_expect_success 'using \"where = before\" with \"--no-where\"' '\n '\n \n test_expect_success 'using \"where = after\"' '\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -808,8 +833,11 @@ test_expect_success 'using \"where = after\"' '\n '\n \n test_expect_success 'using \"where = end\"' '\n-\tgit config trailer.review.key \"Reviewed-by\" &&\n-\tgit config trailer.review.where \"end\" &&\n+\ttest_config trailer.review.key \"Reviewed-by\" &&\n+\ttest_config trailer.review.where \"end\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -827,8 +855,11 @@ test_expect_success 'using \"where = end\"' '\n '\n \n test_expect_success 'using \"where = start\"' '\n-\tgit config trailer.review.key \"Reviewed-by\" &&\n-\tgit config trailer.review.where \"start\" &&\n+\ttest_config trailer.review.key \"Reviewed-by\" &&\n+\ttest_config trailer.review.where \"start\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tReviewed-by: Johannes\n@@ -846,8 +877,13 @@ test_expect_success 'using \"where = start\"' '\n '\n \n test_expect_success 'using \"where = before\" for a token in the middle of the message' '\n-\tgit config trailer.review.key \"Reviewed-by:\" &&\n-\tgit config trailer.review.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -864,6 +900,12 @@ test_expect_success 'using \"where = before\" for a token in the middle of the mes\n '\n \n test_expect_success 'using \"where = before\" and --trim-empty' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tcat >>expected <<-\\EOF &&\n \t\tBug #46\n@@ -878,6 +920,13 @@ test_expect_success 'using \"where = before\" and --trim-empty' '\n '\n \n test_expect_success 'the default is \"ifExists = addIfDifferentNeighbor\"' '\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -896,7 +945,13 @@ test_expect_success 'the default is \"ifExists = addIfDifferentNeighbor\"' '\n '\n \n test_expect_success 'default \"ifExists\" is now \"addIfDifferent\"' '\n-\tgit config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -914,8 +969,14 @@ test_expect_success 'default \"ifExists\" is now \"addIfDifferent\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -932,8 +993,14 @@ test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = before\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.ack.where \"before\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"before\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -950,8 +1017,14 @@ test_expect_success 'using \"ifExists = addIfDifferent\" with \"where = before\"' '\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -973,8 +1046,14 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" with \"where = end\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\"  with \"where = after\"' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -995,7 +1074,11 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\"  with \"where = af\n '\n \n test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" and --trim-empty' '\n-\tgit config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tcat >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1011,8 +1094,14 @@ test_expect_success 'using \"ifExists = addIfDifferentNeighbor\" and --trim-empty'\n '\n \n test_expect_success 'using \"ifExists = add\" with \"where = end\"' '\n-\tgit config trailer.ack.ifExists \"add\" &&\n-\tgit config trailer.ack.where \"end\" &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"end\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1036,8 +1125,14 @@ test_expect_success 'using \"ifExists = add\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifExists = add\" with \"where = after\"' '\n-\tgit config trailer.ack.ifExists \"add\" &&\n-\tgit config trailer.ack.where \"after\" &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1058,8 +1153,15 @@ test_expect_success 'using \"ifExists = add\" with \"where = after\"' '\n '\n \n test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n-\tgit config trailer.fix.key \"Fixes: \" &&\n-\tgit config trailer.fix.ifExists \"add\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1075,8 +1177,15 @@ test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n '\n \n test_expect_success 'using \"ifExists = replace\"' '\n-\tgit config trailer.fix.key \"Fixes: \" &&\n-\tgit config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1095,7 +1204,16 @@ test_expect_success 'using \"ifExists = replace\"' '\n '\n \n test_expect_success 'using \"ifExists = replace\" with \"where = after\"' '\n-\tgit config trailer.fix.where \"after\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1114,7 +1232,15 @@ test_expect_success 'using \"ifExists = replace\" with \"where = after\"' '\n '\n \n test_expect_success 'using \"ifExists = doNothing\"' '\n-\tgit config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1133,8 +1259,17 @@ test_expect_success 'using \"ifExists = doNothing\"' '\n '\n \n test_expect_success 'the default is \"ifMissing = add\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"before\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.where \"before\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1154,7 +1289,14 @@ test_expect_success 'the default is \"ifMissing = add\"' '\n '\n \n test_expect_success 'overriding configuration with \"--if-missing doNothing\"' '\n-\tgit config trailer.ifmissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifmissing \"add\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1173,7 +1315,13 @@ test_expect_success 'overriding configuration with \"--if-missing doNothing\"' '\n '\n \n test_expect_success 'when default \"ifMissing\" is \"doNothing\"' '\n-\tgit config trailer.ifmissing \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.ifmissing \"doNothing\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1187,14 +1335,21 @@ test_expect_success 'when default \"ifMissing\" is \"doNothing\"' '\n \t\t--trailer \"cc=Linus\" --trailer \"ack: Junio\" \\\n \t\t--trailer \"fix=22\" --trailer \"bug: 42\" --trailer \"ack: Peff\" \\\n \t\t<complex_message >actual &&\n-\ttest_cmp expected actual &&\n-\tgit config trailer.ifmissing \"add\"\n+\ttest_cmp expected actual\n '\n \n test_expect_success 'using \"ifMissing = add\" with \"where = end\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"end\" &&\n-\tgit config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.cc.where \"end\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1214,9 +1369,17 @@ test_expect_success 'using \"ifMissing = add\" with \"where = end\"' '\n '\n \n test_expect_success 'using \"ifMissing = add\" with \"where = before\"' '\n-\tgit config trailer.cc.key \"Cc: \" &&\n-\tgit config trailer.cc.where \"before\" &&\n-\tgit config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.key \"Cc: \" &&\n+\ttest_config trailer.cc.ifMissing \"add\" &&\n+\ttest_config trailer.cc.where \"before\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tCc: Linus\n@@ -1236,7 +1399,15 @@ test_expect_success 'using \"ifMissing = add\" with \"where = before\"' '\n '\n \n test_expect_success 'using \"ifMissing = doNothing\"' '\n-\tgit config trailer.cc.ifMissing \"doNothing\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.cc.ifMissing \"doNothing\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1256,7 +1427,15 @@ test_expect_success 'using \"ifMissing = doNothing\"' '\n \n test_expect_success 'default \"where\" is now \"after\"' '\n \tgit config trailer.where \"after\" &&\n-\tgit config --unset trailer.ack.where &&\n+\ttest_config trailer.ack.ifExists \"add\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.ack.where \"after\" &&\n+\ttest_config trailer.bug.key \"Bug #\" &&\n+\ttest_config trailer.bug.where \"before\" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=#\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tBug #42\n@@ -1280,10 +1459,15 @@ test_expect_success 'default \"where\" is now \"after\"' '\n '\n \n test_expect_success 'with simple command' '\n-\tgit config trailer.sign.key \"Signed-off-by: \" &&\n-\tgit config trailer.sign.where \"after\" &&\n-\tgit config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.sign.command \"echo \\\"A U Thor <author@example.com>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"A U Thor <author@example.com>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.sign.where \"after\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1298,8 +1482,14 @@ test_expect_success 'with simple command' '\n '\n \n test_expect_success 'with command using committer information' '\n-\tgit config trailer.sign.ifExists \"addIfDifferent\" &&\n-\tgit config trailer.sign.command \"echo \\\"\\$GIT_COMMITTER_NAME <\\$GIT_COMMITTER_EMAIL>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_COMMITTER_NAME <\\$GIT_COMMITTER_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferent\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1314,10 +1504,15 @@ test_expect_success 'with command using committer information' '\n '\n \n test_expect_success 'with command using author information' '\n-\tgit config trailer.sign.key \"Signed-off-by: \" &&\n-\tgit config trailer.sign.where \"after\" &&\n-\tgit config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n-\tgit config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.ifExists \"doNothing\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.sign.ifExists \"addIfDifferentNeighbor\" &&\n+\ttest_config trailer.sign.where \"after\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n \t\tFixes: Z\n@@ -1338,12 +1533,19 @@ test_expect_success 'setup a commit' '\n '\n \n test_expect_success 'cmd takes precedence over command' '\n-\ttest_when_finished \"git config --unset trailer.fix.cmd\" &&\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.cmd \"test -n \\\"\\$1\\\" && git log -1 --oneline --format=\\\"%h (%aN)\\\" \\\n-\t--abbrev-commit --abbrev=14 \\\"\\$1\\\" || true\" &&\n-\tgit config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" \\\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" \\\n \t\t--abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.fix.cmd \"test -n \\\"\\$1\\\" && git log -1 --oneline --format=\\\"%h (%aN)\\\" \\\n+\t--abbrev-commit --abbrev=14 \\\"\\$1\\\" || true\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tFIXED=$(git log -1 --oneline --format=\"%h (%aN)\" --abbrev-commit --abbrev=14 HEAD) &&\n \tcat complex_message_body >expected2 &&\n \tsed -e \"s/ Z\\$/ /\" >>expected2 <<-EOF &&\n@@ -1359,8 +1561,16 @@ test_expect_success 'cmd takes precedence over command' '\n '\n \n test_expect_success 'with command using $ARG' '\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" --abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"git log -1 --oneline --format=\\\"%h (%s)\\\" --abbrev-commit --abbrev=14 \\$ARG\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tFIXED=$(git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 HEAD) &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-EOF &&\n@@ -1376,8 +1586,16 @@ test_expect_success 'with command using $ARG' '\n '\n \n test_expect_success 'with failing command using $ARG' '\n-\tgit config trailer.fix.ifExists \"replace\" &&\n-\tgit config trailer.fix.command \"false \\$ARG\" &&\n+\ttest_config trailer.ack.key \"Acked-by= \" &&\n+\ttest_config trailer.fix.command \"false \\$ARG\" &&\n+\ttest_config trailer.fix.key \"Fixes: \" &&\n+\ttest_config trailer.fix.ifExists \"replace\" &&\n+\ttest_config trailer.fix.where \"after\" &&\n+\ttest_config trailer.review.key \"Reviewed-by:\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n+\ttest_config trailer.separators \":=\" &&\n \tcat complex_message_body >expected &&\n \tsed -e \"s/ Z\\$/ /\" >>expected <<-EOF &&\n \t\tFixes: Z\n@@ -1392,7 +1610,9 @@ test_expect_success 'with failing command using $ARG' '\n '\n \n test_expect_success 'with empty tokens' '\n-\tgit config --unset trailer.fix.command &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.sign.key \"Signed-off-by: \" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\tSigned-off-by: A U Thor <author@example.com>\n@@ -1403,7 +1623,8 @@ test_expect_success 'with empty tokens' '\n '\n \n test_expect_success 'with command but no key' '\n-\tgit config --unset trailer.sign.key &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\tsign: A U Thor <author@example.com>\n@@ -1414,7 +1635,9 @@ test_expect_success 'with command but no key' '\n '\n \n test_expect_success 'with no command and no key' '\n-\tgit config --unset trailer.review.key &&\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-EOF &&\n \n \t\treview: Junio\n@@ -1426,6 +1649,8 @@ test_expect_success 'with no command and no key' '\n '\n \n test_expect_success 'with cut line' '\n+\ttest_config trailer.review.where \"before\" &&\n+\ttest_config trailer.sign.command \"echo \\\"\\$GIT_AUTHOR_NAME <\\$GIT_AUTHOR_EMAIL>\\\"\" &&\n \tcat >expected <<-\\EOF &&\n \t\tmy subject\n \n@@ -1443,7 +1668,8 @@ test_expect_success 'with cut line' '\n '\n \n test_expect_success 'only trailers' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.ifexists \"addIfDifferent\" &&\n \tcat >expected <<-\\EOF &&\n \t\texisting: existing-value\n \t\tsign: config-value\n@@ -1462,7 +1688,7 @@ test_expect_success 'only trailers' '\n '\n \n test_expect_success 'only-trailers omits non-trailer in middle of block' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n \tcat >expected <<-\\EOF &&\n \t\tSigned-off-by: nobody <nobody@nowhere>\n \t\tSigned-off-by: somebody <somebody@somewhere>\n@@ -1482,7 +1708,7 @@ test_expect_success 'only-trailers omits non-trailer in middle of block' '\n '\n \n test_expect_success 'only input' '\n-\tgit config trailer.sign.command \"echo config-value\" &&\n+\ttest_config trailer.sign.command \"echo config-value\" &&\n \tcat >expected <<-\\EOF &&\n \t\texisting: existing-value\n \tEOF\n-- \ngitgitgadget\n\n"},{"id":"481533","messageId":"0df12c5c2dda5799074f0dcea696df0a63ca1145.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 04/13] trailer doc: narrow down scope of --where and related flags","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:00Z","receivedAt":"2023-09-07T22:20:23Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe wording \"all configuration variables\" is misleading (the same could\nbe said to the descriptions of the \"--[no-]if-exists\" and the\n\"--[no-]if-missing\" options).  Specifying --where=value overrides only\nthe trailer.where variable and applicable trailer.<token>.where\nvariables, and --no-where stops the overriding of these variables.\nDitto for the other two with their relevant configuration variables.\n\nReported-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 91a4dbc9a72..72f5bdb652f 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -112,7 +112,8 @@ OPTIONS\n --where <placement>::\n --no-where::\n \tSpecify where all new trailers will be added.  A setting\n-\tprovided with '--where' overrides all configuration variables\n+\tprovided with '--where' overrides the `trailer.where` and any\n+\tapplicable `trailer.<token>.where` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n \teffect of any previous use of '--where', such that the relevant configuration\n@@ -123,7 +124,8 @@ OPTIONS\n --no-if-exists::\n \tSpecify what action will be performed when there is already at\n \tleast one trailer with the same <token> in the input.  A setting\n-\tprovided with '--if-exists' overrides all configuration variables\n+\tprovided with '--if-exists' overrides the `trailer.ifExists` and any\n+\tapplicable `trailer.<token>.ifExists` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists, clear the\n \teffect of any previous use of '--if-exists, such that the relevant configuration\n@@ -134,7 +136,8 @@ OPTIONS\n --no-if-missing::\n \tSpecify what action will be performed when there is no other\n \ttrailer with the same <token> in the input.  A setting\n-\tprovided with '--if-missing' overrides all configuration variables\n+\tprovided with '--if-missing' overrides the `trailer.ifMissing` and any\n+\tapplicable `trailer.<token>.ifMissing` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing,\n \tclear the effect of any previous use of '--if-missing, such that the relevant\n-- \ngitgitgadget\n\n"},{"id":"481535","messageId":"3e58b6f5ea264a2c42ffbd008405b46626e0f864.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 06/13] trailer --no-divider help: describe usual \"---\" meaning","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:02Z","receivedAt":"2023-09-07T22:20:24Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nIt's unclear what treating something \"specially\" means.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n builtin/interpret-trailers.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex cf4f703c4e2..a7623dbfb2e 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -109,7 +109,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"set parsing options\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n-\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat --- specially\")),\n+\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n \t\tOPT_CALLBACK(0, \"trailer\", &trailers, N_(\"trailer\"),\n \t\t\t\tN_(\"trailer(s) to add\"), option_parse_trailer),\n \t\tOPT_END()\n-- \ngitgitgadget\n\n"},{"id":"481536","messageId":"040766861e21afe5f686299560677e429be11844.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 05/13] trailer: trailer location is a place, not an action","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:01Z","receivedAt":"2023-09-07T22:20:25Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nFix the help text to say \"placement\" instead of \"action\" because the\nvalues are placements, not actions.\n\nWhile we're at it, tweak the documentation to say \"placements\" instead\nof \"values\", similar to how the existing language for \"--if-exists\" uses\nthe word \"action\" to describe both the syntax (with the phrase\n\"--if-exists <action>\") and the possible values (with the phrase\n\"possible actions\").\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 2 +-\n builtin/interpret-trailers.c             | 2 +-\n 2 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 72f5bdb652f..b5284c3d33f 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -117,7 +117,7 @@ OPTIONS\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n \teffect of any previous use of '--where', such that the relevant configuration\n-\tvariables are no longer overridden. Possible values are `after`,\n+\tvariables are no longer overridden. Possible placements are `after`,\n \t`before`, `end` or `start`.\n \n --if-exists <action>::\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex c5e83452654..cf4f703c4e2 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -97,7 +97,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"in-place\", &opts.in_place, N_(\"edit files in place\")),\n \t\tOPT_BOOL(0, \"trim-empty\", &opts.trim_empty, N_(\"trim empty trailers\")),\n \n-\t\tOPT_CALLBACK(0, \"where\", NULL, N_(\"action\"),\n+\t\tOPT_CALLBACK(0, \"where\", NULL, N_(\"placement\"),\n \t\t\t     N_(\"where to place the new trailer\"), option_parse_where),\n \t\tOPT_CALLBACK(0, \"if-exists\", NULL, N_(\"action\"),\n \t\t\t     N_(\"action if trailer already exists\"), option_parse_if_exists),\n-- \ngitgitgadget\n\n"},{"id":"481537","messageId":"5cfff52da8ff586248ba394248e7b086ed792549.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 08/13] trailer --only-input: prefer \"configuration variables\" over \"rules\"","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:04Z","receivedAt":"2023-09-07T22:20:30Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nUse the phrase \"configuration variables\" instead of \"rules\" because\n\n(1) we already say \"configuration variables\" in multiple\n    places in the docs (where the word \"rules\" is only used for describing\n    \"--only-input\" behavior and for an unrelated case of mentioning how\n    the trailers do not follow \"rules for RFC 822 headers\"), and\n\n(2) this phrase is more specific than just \"rules\".\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 4 ++--\n builtin/interpret-trailers.c             | 2 +-\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex b5284c3d33f..0eea937c30e 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -149,8 +149,8 @@ OPTIONS\n \n --only-input::\n \tOutput only trailers that exist in the input; do not add any\n-\tfrom the command-line or by following configured `trailer.*`\n-\trules.\n+\tfrom the command-line or by applying `trailer.*` configuration\n+\tvariables.\n \n --unfold::\n \tRemove any whitespace-continuation in trailers, so that each\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex 5f3e1a38eee..f70c5df8d4b 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -105,7 +105,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\t\t     N_(\"action if trailer is missing\"), option_parse_if_missing),\n \n \t\tOPT_BOOL(0, \"only-trailers\", &opts.only_trailers, N_(\"output only the trailers\")),\n-\t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply config rules\")),\n+\t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply trailer.* configuration variables\")),\n \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"alias for --only-trailers --only-input --unfold\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n-- \ngitgitgadget\n\n"},{"id":"481538","messageId":"a08d78618bac70c4bc72fa5c88fae08d9ed3ce52.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 10/13] trailer --unfold help: prefer \"reformat\" over \"join\"","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:06Z","receivedAt":"2023-09-07T22:20:32Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe phrase \"join whitespace-continued values\" requires some additional\ncontext. For example, \"whitespace\" means newlines (not just space\ncharacters), and \"join\" means to join only the multiple lines together\nfor a single trailer (and not that we are joining multiple trailers\ntogether). That is, \"join\" means to convert\n\n    token: This is a very long value, with spaces and\n      newlines in it.\n\nto\n\n    token: This is a very long value, with spaces and newlines in it.\n\nand does not mean to convert\n\n    token: value1\n    token: value2\n\nto\n\n    token: value1 value2.\n\nUpdate the help text to resolve the above ambiguity. While we're add it,\nupdate the docs to use similar language as the change in the help text.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 4 ++--\n builtin/interpret-trailers.c             | 2 +-\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 2d49445b1c3..62ba2b1232e 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -155,8 +155,8 @@ OPTIONS\n \tvariables.\n \n --unfold::\n-\tRemove any whitespace-continuation in trailers, so that each\n-\ttrailer appears on a line by itself with its full content.\n+\tIf a trailer has a value that runs over multiple lines (aka \"folded\"),\n+\treformat the value into a single line.\n \n --parse::\n \tA convenience alias for `--only-trailers --only-input\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex f70c5df8d4b..832f86a770a 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -106,7 +106,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \n \t\tOPT_BOOL(0, \"only-trailers\", &opts.only_trailers, N_(\"output only the trailers\")),\n \t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply trailer.* configuration variables\")),\n-\t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n+\t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"reformat multiline trailer values as single-line values\")),\n \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"alias for --only-trailers --only-input --unfold\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n \t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n-- \ngitgitgadget\n\n"},{"id":"481539","messageId":"ef6b77016cd50c438fb58d79ffb10f748ddc5244.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 09/13] trailer --parse docs: add explanation for its usefulness","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:05Z","receivedAt":"2023-09-07T22:20:34Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nFor users who are skimming the docs to go straight to the individual\nbreakdown of each flag, it may not be clear why --parse is a convenience\nalias (without them also looking at the other options that --parse turns\non). To save them the trouble of looking at the other options (and\ncomputing what that would mean), describe a summary of the overall\neffect.\n\nSimilarly update the area when we first mention --parse near the top of\nthe doc.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 9 +++++++--\n 1 file changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 0eea937c30e..2d49445b1c3 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -31,7 +31,9 @@ the last two lines starting with \"Signed-off-by\" are trailers.\n \n This command reads commit messages from either the\n <file> arguments or the standard input if no <file> is specified.\n-If `--parse` is specified, the output consists of the parsed trailers.\n+If `--parse` is specified, the output consists of the parsed trailers\n+coming from the input, without influencing them with any command line\n+options or configuration variables.\n Otherwise, this command applies the arguments passed using the\n `--trailer` option, if any, to each input file. The result is emitted on the\n standard output.\n@@ -158,7 +160,10 @@ OPTIONS\n \n --parse::\n \tA convenience alias for `--only-trailers --only-input\n-\t--unfold`.\n+\t--unfold`. This makes it easier to only see the trailers coming from the\n+\tinput without influencing them with any command line options or\n+\tconfiguration variables, while also making the output machine-friendly with\n+\t--unfold.\n \n --no-divider::\n \tDo not treat `---` as the end of the commit message. Use this\n-- \ngitgitgadget\n\n"},{"id":"481540","messageId":"d1780a0127a749902d60249b531869ee9cd1a5f6.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 07/13] trailer --parse help: expose aliased options","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:03Z","receivedAt":"2023-09-07T22:20:35Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe existing description \"set parsing options\" is vague, because\narguably _all_ of the options for interpret-trailers have to do with\nparsing to some degree.\n\nExplain what this flag does to match what is in the docs, namely how\nit is an alias for \"--only-trailers --only-input --unfold\".\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n builtin/interpret-trailers.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex a7623dbfb2e..5f3e1a38eee 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -107,7 +107,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"only-trailers\", &opts.only_trailers, N_(\"output only the trailers\")),\n \t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply config rules\")),\n \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n-\t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"set parsing options\"),\n+\t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"alias for --only-trailers --only-input --unfold\"),\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n \t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n \t\tOPT_CALLBACK(0, \"trailer\", &trailers, N_(\"trailer\"),\n-- \ngitgitgadget\n\n"},{"id":"481541","messageId":"66087eaf5bd2abc416628cdcf166b8bd7e9cbf2e.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 12/13] trailer doc: separator within key suppresses default separator","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:08Z","receivedAt":"2023-09-07T22:20:37Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex a288ff111cb..25433e1a1ff 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -255,8 +255,8 @@ trailer.<token>.key::\n \tbut this can be changed using the `trailer.separators` config\n \tvariable.\n +\n-If there is a separator, then the key will be used instead of both the\n-<token> and the default separator when adding the trailer.\n+If there is a separator in the key, then it overrides the default\n+separator when adding the trailer.\n \n trailer.<token>.where::\n \tThis option takes the same values as the 'trailer.where'\n-- \ngitgitgadget\n\n"},{"id":"481542","messageId":"4db823ac3549c031b61b5a0ec0efd56b70d2a45c.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 11/13] trailer doc: emphasize the effect of configuration variables","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:07Z","receivedAt":"2023-09-07T22:20:38Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe sentence does not mention the effect of configuration variables at\nall, when they are actively used by default (unless --parse is\nspecified) to potentially add new trailers, without the user having to\nalways supply --trailer manually.\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 62ba2b1232e..a288ff111cb 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -34,9 +34,12 @@ This command reads commit messages from either the\n If `--parse` is specified, the output consists of the parsed trailers\n coming from the input, without influencing them with any command line\n options or configuration variables.\n-Otherwise, this command applies the arguments passed using the\n-`--trailer` option, if any, to each input file. The result is emitted on the\n-standard output.\n+\n+Otherwise, this command applies `trailer.*` configuration variables\n+(which could potentially add new trailers, as well as reposition them),\n+as well as any command line arguments that can override configuration\n+variables (such as `--trailer=...` which could also add new trailers),\n+to each input file. The result is emitted on the standard output.\n \n This command can also operate on the output of linkgit:git-format-patch[1],\n which is more elaborate than a plain commit message. Namely, such output\n-- \ngitgitgadget\n\n"},{"id":"481543","messageId":"0b9525db5a0787fdc71834abad9151aa03acc497.1694125210.git.gitgitgadget@gmail.com","threadId":"60067","inReplyTo":"pull.1564.v3.git.1694125209.gitgitgadget@gmail.com","subject":"[PATCH v3 13/13] trailer doc: <token> is a <key> or <keyAlias>, not both","fromName":"Linus Arver via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-09-07T22:20:09Z","receivedAt":"2023-09-07T22:20:39Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"From: Linus Arver <linusa@google.com>\n\nThe `--trailer` option takes a \"<token>=<value>\" argument, for example\n\n    --trailer \"Acked-by=Bob\"\n\nAnd in this exampple it is understood that \"Acked-by\" is the <token>.\nHowever, the user can use a shorter \"ack\" string by defining\nconfiguration like\n\n    git config trailer.ack.key \"Acked-by\"\n\nHowever, in the docs we define the above configuration as\n\n    trailer.<token>.key\n\nso the <token> can mean either the longer \"Acked-by\" or the shorter\n\"ack\".\n\nSeparate the two meanings of <token> into <key> and <keyAlias>, and\nupdate the configuration syntax to say \"trailer.<keyAlias>.key\".\n\nSigned-off-by: Linus Arver <linusa@google.com>\n---\n Documentation/git-interpret-trailers.txt | 136 +++++++++++++----------\n builtin/interpret-trailers.c             |   2 +-\n 2 files changed, 77 insertions(+), 61 deletions(-)\n\ndiff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\nindex 25433e1a1ff..418265f044d 100644\n--- a/Documentation/git-interpret-trailers.txt\n+++ b/Documentation/git-interpret-trailers.txt\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git interpret-trailers' [--in-place] [--trim-empty]\n-\t\t\t[(--trailer <token>[(=|:)<value>])...]\n+\t\t\t[(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n \t\t\t[--parse] [<file>...]\n \n DESCRIPTION\n@@ -53,22 +53,32 @@ are applied to each input and the way any existing trailer in\n the input is changed. They also make it possible to\n automatically add some trailers.\n \n-By default, a '<token>=<value>' or '<token>:<value>' argument given\n+By default, a '<key>=<value>' or '<key>:<value>' argument given\n using `--trailer` will be appended after the existing trailers only if\n-the last trailer has a different (<token>, <value>) pair (or if there\n-is no existing trailer). The <token> and <value> parts will be trimmed\n+the last trailer has a different (<key>, <value>) pair (or if there\n+is no existing trailer). The <key> and <value> parts will be trimmed\n to remove starting and trailing whitespace, and the resulting trimmed\n-<token> and <value> will appear in the output like this:\n+<key> and <value> will appear in the output like this:\n \n ------------------------------------------------\n-token: value\n+key: value\n ------------------------------------------------\n \n-This means that the trimmed <token> and <value> will be separated by\n-`': '` (one colon followed by one space). For convenience, the <token> can be a\n-shortened string key (e.g., \"sign\") instead of the full string which should\n-appear before the separator on the output (e.g., \"Signed-off-by\"). This can be\n-configured using the 'trailer.<token>.key' configuration variable.\n+This means that the trimmed <key> and <value> will be separated by\n+`': '` (one colon followed by one space).\n+\n+For convenience, a <keyAlias> can be configured to make using `--trailer`\n+shorter to type on the command line. This can be configured using the\n+'trailer.<keyAlias>.key' configuration variable. The <keyAlias> must be a prefix\n+of the full <key> string, although case sensitivity does not matter. For\n+example, if you have\n+\n+------------------------------------------------\n+trailer.sign.key \"Signed-off-by: \"\n+------------------------------------------------\n+\n+in your configuration, you only need to specify `--trailer=\"sign: foo\"`\n+on the command line instead of `--trailer=\"Signed-off-by: foo\"`.\n \n By default the new trailer will appear at the end of all the existing\n trailers. If there is no existing trailer, the new trailer will appear\n@@ -85,14 +95,14 @@ non-whitespace lines before a line that starts with '---' (followed by a\n space or the end of the line).\n \n When reading trailers, there can be no whitespace before or inside the\n-<token>, but any number of regular space and tab characters are allowed\n-between the <token> and the separator. There can be whitespaces before,\n+<key>, but any number of regular space and tab characters are allowed\n+between the <key> and the separator. There can be whitespaces before,\n inside or after the <value>. The <value> may be split over multiple lines\n with each subsequent line starting with at least one whitespace, like\n the \"folding\" in RFC 822. Example:\n \n ------------------------------------------------\n-token: This is a very long value, with spaces and\n+key: This is a very long value, with spaces and\n   newlines in it.\n ------------------------------------------------\n \n@@ -109,8 +119,8 @@ OPTIONS\n \tthe whole trailer will be removed from the output.\n \tThis applies to existing trailers as well as new trailers.\n \n---trailer <token>[(=|:)<value>]::\n-\tSpecify a (<token>, <value>) pair that should be applied as a\n+--trailer <key>[(=|:)<value>]::\n+\tSpecify a (<key>, <value>) pair that should be applied as a\n \ttrailer to the inputs. See the description of this\n \tcommand.\n \n@@ -118,7 +128,7 @@ OPTIONS\n --no-where::\n \tSpecify where all new trailers will be added.  A setting\n \tprovided with '--where' overrides the `trailer.where` and any\n-\tapplicable `trailer.<token>.where` configuration variables\n+\tapplicable `trailer.<keyAlias>.where` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n \teffect of any previous use of '--where', such that the relevant configuration\n@@ -128,9 +138,9 @@ OPTIONS\n --if-exists <action>::\n --no-if-exists::\n \tSpecify what action will be performed when there is already at\n-\tleast one trailer with the same <token> in the input.  A setting\n+\tleast one trailer with the same <key> in the input.  A setting\n \tprovided with '--if-exists' overrides the `trailer.ifExists` and any\n-\tapplicable `trailer.<token>.ifExists` configuration variables\n+\tapplicable `trailer.<keyAlias>.ifExists` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists, clear the\n \teffect of any previous use of '--if-exists, such that the relevant configuration\n@@ -140,9 +150,9 @@ OPTIONS\n --if-missing <action>::\n --no-if-missing::\n \tSpecify what action will be performed when there is no other\n-\ttrailer with the same <token> in the input.  A setting\n+\ttrailer with the same <key> in the input.  A setting\n \tprovided with '--if-missing' overrides the `trailer.ifMissing` and any\n-\tapplicable `trailer.<token>.ifMissing` configuration variables\n+\tapplicable `trailer.<keyAlias>.ifMissing` configuration variables\n \tand applies to all '--trailer' options until the next occurrence of\n \t'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing,\n \tclear the effect of any previous use of '--if-missing, such that the relevant\n@@ -187,11 +197,11 @@ used when another separator is not specified in the config for this\n trailer.\n +\n For example, if the value for this option is \"%=$\", then only lines\n-using the format '<token><sep><value>' with <sep> containing '%', '='\n+using the format '<key><sep><value>' with <sep> containing '%', '='\n or '$' and then spaces will be considered trailers. And '%' will be\n the default separator used, so by default trailers will appear like:\n-'<token>% <value>' (one percent sign and one space will appear between\n-the token and the value).\n+'<key>% <value>' (one percent sign and one space will appear between\n+the key and the value).\n \n trailer.where::\n \tThis option tells where a new trailer will be added.\n@@ -205,41 +215,41 @@ If it is `start`, then each new trailer will appear at the start,\n instead of the end, of the existing trailers.\n +\n If it is `after`, then each new trailer will appear just after the\n-last trailer with the same <token>.\n+last trailer with the same <key>.\n +\n If it is `before`, then each new trailer will appear just before the\n-first trailer with the same <token>.\n+first trailer with the same <key>.\n \n trailer.ifexists::\n \tThis option makes it possible to choose what action will be\n \tperformed when there is already at least one trailer with the\n-\tsame <token> in the input.\n+\tsame <key> in the input.\n +\n The valid values for this option are: `addIfDifferentNeighbor` (this\n is the default), `addIfDifferent`, `add`, `replace` or `doNothing`.\n +\n With `addIfDifferentNeighbor`, a new trailer will be added only if no\n-trailer with the same (<token>, <value>) pair is above or below the line\n+trailer with the same (<key>, <value>) pair is above or below the line\n where the new trailer will be added.\n +\n With `addIfDifferent`, a new trailer will be added only if no trailer\n-with the same (<token>, <value>) pair is already in the input.\n+with the same (<key>, <value>) pair is already in the input.\n +\n With `add`, a new trailer will be added, even if some trailers with\n-the same (<token>, <value>) pair are already in the input.\n+the same (<key>, <value>) pair are already in the input.\n +\n-With `replace`, an existing trailer with the same <token> will be\n+With `replace`, an existing trailer with the same <key> will be\n deleted and the new trailer will be added. The deleted trailer will be\n-the closest one (with the same <token>) to the place where the new one\n+the closest one (with the same <key>) to the place where the new one\n will be added.\n +\n With `doNothing`, nothing will be done; that is no new trailer will be\n-added if there is already one with the same <token> in the input.\n+added if there is already one with the same <key> in the input.\n \n trailer.ifmissing::\n \tThis option makes it possible to choose what action will be\n \tperformed when there is not yet any trailer with the same\n-\t<token> in the input.\n+\t<key> in the input.\n +\n The valid values for this option are: `add` (this is the default) and\n `doNothing`.\n@@ -248,34 +258,40 @@ With `add`, a new trailer will be added.\n +\n With `doNothing`, nothing will be done.\n \n-trailer.<token>.key::\n-\tThis `key` will be used instead of <token> in the trailer. At\n-\tthe end of this key, a separator can appear and then some\n-\tspace characters. By default the only valid separator is ':',\n-\tbut this can be changed using the `trailer.separators` config\n-\tvariable.\n+trailer.<keyAlias>.key::\n+\tDefines a <keyAlias> for the <key>. The <keyAlias> must be a\n+\tprefix (case does not matter) of the <key>. For example, in `git\n+\tconfig trailer.ack.key \"Acked-by\"` the \"Acked-by\" is the <key> and\n+\tthe \"ack\" is the <keyAlias>. This configuration allows the shorter\n+\t`--trailer \"ack:...\"` invocation on the command line using the \"ack\"\n+\t<keyAlias> instead of the longer `--trailer \"Acked-by:...\"`.\n++\n+At the end of the <key>, a separator can appear and then some\n+space characters. By default the only valid separator is ':',\n+but this can be changed using the `trailer.separators` config\n+variable.\n +\n If there is a separator in the key, then it overrides the default\n separator when adding the trailer.\n \n-trailer.<token>.where::\n+trailer.<keyAlias>.where::\n \tThis option takes the same values as the 'trailer.where'\n \tconfiguration variable and it overrides what is specified by\n-\tthat option for trailers with the specified <token>.\n+\tthat option for trailers with the specified <keyAlias>.\n \n-trailer.<token>.ifexists::\n+trailer.<keyAlias>.ifexists::\n \tThis option takes the same values as the 'trailer.ifexists'\n \tconfiguration variable and it overrides what is specified by\n-\tthat option for trailers with the specified <token>.\n+\tthat option for trailers with the specified <keyAlias>.\n \n-trailer.<token>.ifmissing::\n+trailer.<keyAlias>.ifmissing::\n \tThis option takes the same values as the 'trailer.ifmissing'\n \tconfiguration variable and it overrides what is specified by\n-\tthat option for trailers with the specified <token>.\n+\tthat option for trailers with the specified <keyAlias>.\n \n-trailer.<token>.command::\n-\tDeprecated in favor of 'trailer.<token>.cmd'.\n-\tThis option behaves in the same way as 'trailer.<token>.cmd', except\n+trailer.<keyAlias>.command::\n+\tDeprecated in favor of 'trailer.<keyAlias>.cmd'.\n+\tThis option behaves in the same way as 'trailer.<keyAlias>.cmd', except\n \tthat it doesn't pass anything as argument to the specified command.\n \tInstead the first occurrence of substring $ARG is replaced by the\n \t<value> that would be passed as argument.\n@@ -283,29 +299,29 @@ trailer.<token>.command::\n Note that $ARG in the user's command is\n only replaced once and that the original way of replacing $ARG is not safe.\n +\n-When both 'trailer.<token>.cmd' and 'trailer.<token>.command' are given\n-for the same <token>, 'trailer.<token>.cmd' is used and\n-'trailer.<token>.command' is ignored.\n+When both 'trailer.<keyAlias>.cmd' and 'trailer.<keyAlias>.command' are given\n+for the same <keyAlias>, 'trailer.<keyAlias>.cmd' is used and\n+'trailer.<keyAlias>.command' is ignored.\n \n-trailer.<token>.cmd::\n+trailer.<keyAlias>.cmd::\n \tThis option can be used to specify a shell command that will be called\n-\tonce to automatically add a trailer with the specified <token>, and then\n-\tcalled each time a '--trailer <token>=<value>' argument is specified to\n+\tonce to automatically add a trailer with the specified <keyAlias>, and then\n+\tcalled each time a '--trailer <keyAlias>=<value>' argument is specified to\n \tmodify the <value> of the trailer that this option would produce.\n +\n When the specified command is first called to add a trailer\n-with the specified <token>, the behavior is as if a special\n-'--trailer <token>=<value>' argument was added at the beginning\n+with the specified <keyAlias>, the behavior is as if a special\n+'--trailer <keyAlias>=<value>' argument was added at the beginning\n of the \"git interpret-trailers\" command, where <value>\n is taken to be the standard output of the command with any\n leading and trailing whitespace trimmed off.\n +\n-If some '--trailer <token>=<value>' arguments are also passed\n+If some '--trailer <keyAlias>=<value>' arguments are also passed\n on the command line, the command is called again once for each\n-of these arguments with the same <token>. And the <value> part\n+of these arguments with the same <keyAlias>. And the <value> part\n of these arguments, if any, will be passed to the command as its\n first argument. This way the command can produce a <value> computed\n-from the <value> passed in the '--trailer <token>=<value>' argument.\n+from the <value> passed in the '--trailer <keyAlias>=<value>' argument.\n \n EXAMPLES\n --------\ndiff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\nindex 832f86a770a..d2d78fd961f 100644\n--- a/builtin/interpret-trailers.c\n+++ b/builtin/interpret-trailers.c\n@@ -14,7 +14,7 @@\n \n static const char * const git_interpret_trailers_usage[] = {\n \tN_(\"git interpret-trailers [--in-place] [--trim-empty]\\n\"\n-\t   \"                       [(--trailer <token>[(=|:)<value>])...]\\n\"\n+\t   \"                       [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\\n\"\n \t   \"                       [--parse] [<file>...]\"),\n \tNULL\n };\n-- \ngitgitgadget\n"},{"id":"481577","messageId":"xmqqfs3os574.fsf@gitster.g","threadId":"60067","inReplyTo":"4b5c458ef436c2d208e6d6d0a1f99c65e9a11125.1694125210.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 03/13] trailer: add tests to check defaulting behavior with --no-* flags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-09-08T21:52:47Z","receivedAt":"2023-09-08T21:52:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Linus Arver <linusa@google.com>\n>\n> While the \"--no-where\" flag is tested, the \"--no-if-exists\" and\n> \"--no-if-missing\" flags are not, so add tests for them. But also add\n> tests for all \"--no-*\" flags to check their effects, both when (1) there\n> are relevant configuration variables set, and (2) they are not set.\n>\n> Signed-off-by: Linus Arver <linusa@google.com>\n> ---\n>  Documentation/git-interpret-trailers.txt |  14 ++-\n>  t/t7513-interpret-trailers.sh            | 130 +++++++++++++++++++++++\n>  2 files changed, 140 insertions(+), 4 deletions(-)\n\nThe commentary before each test_expect_success makes it quite a\npleasant read.\n\n> diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh\n> index ed0fc04bd95..832aff06167 100755\n> --- a/t/t7513-interpret-trailers.sh\n> +++ b/t/t7513-interpret-trailers.sh\n> @@ -812,6 +812,53 @@ test_expect_success 'using \"--where after\" with \"--no-where\"' '\n>  \ttest_cmp expected actual\n>  '\n>  \n> +# Check whether using \"--no-where\" clears out only the \"--where after\", such\n> +# that we still use the configuration in trailer.where (which is different from\n> +# the hardcoded default (in WHERE_END) assuming the absence of .gitconfig).\n> +# Here, the \"start\" setting of trailer.where is respected, so the new \"Acked-by\"\n> +# and \"Bug\" trailers are placed at the beginning, and not at the end which is\n> +# the harcoded default.\n> +test_expect_success 'using \"--where after\" with \"--no-where\" defaults to configuration' '\n> +\ttest_config trailer.ack.key \"Acked-by= \" &&\n> +\ttest_config trailer.bug.key \"Bug #\" &&\n> +\ttest_config trailer.separators \":=#\" &&\n> +\ttest_config trailer.where \"start\" &&\n> +\tcat complex_message_body >expected &&\n> +\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n> +\t\tBug #42\n> +\t\tAcked-by= Peff\n> +\t\tFixes: Z\n> +\t\tAcked-by= Z\n> +\t\tReviewed-by: Z\n> +\t\tSigned-off-by: Z\n> +\tEOF\n> +\tgit interpret-trailers --where after --no-where --trailer \"ack: Peff\" \\\n> +\t\t--trailer \"bug: 42\" complex_message >actual &&\n> +\ttest_cmp expected actual\n> +'\n> +\n> +# The \"--where after\" will only get respected for the trailer that came\n> +# immediately after it. For the next trailer (Bug #42), we default to using the\n> +# hardcoded WHERE_END because we don't have any \"trailer.where\" or\n> +# \"trailer.bug.where\" configured.\n> +test_expect_success 'using \"--no-where\" defaults to harcoded default if nothing configured' '\n> +\ttest_config trailer.ack.key \"Acked-by= \" &&\n> +\ttest_config trailer.bug.key \"Bug #\" &&\n> +\ttest_config trailer.separators \":=#\" &&\n> +\tcat complex_message_body >expected &&\n> +\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n> +\t\tFixes: Z\n> +\t\tAcked-by= Z\n> +\t\tAcked-by= Peff\n> +\t\tReviewed-by: Z\n> +\t\tSigned-off-by: Z\n> +\t\tBug #42\n> +\tEOF\n> +\tgit interpret-trailers --where after --trailer \"ack: Peff\" --no-where \\\n> +\t\t--trailer \"bug: 42\" complex_message >actual &&\n> +\ttest_cmp expected actual\n> +'\n> +\n>  test_expect_success 'using \"where = after\"' '\n>  \ttest_config trailer.ack.key \"Acked-by= \" &&\n>  \ttest_config trailer.ack.where \"after\" &&\n> @@ -1176,6 +1223,56 @@ test_expect_success 'overriding configuration with \"--if-exists replace\"' '\n>  \ttest_cmp expected actual\n>  '\n>  \n> +# \"trailer.ifexists\" is set to \"doNothing\", so using \"--no-if-exists\" defaults\n> +# to this \"doNothing\" behavior. So the \"Fixes: 53\" trailer does not get added.\n> +test_expect_success 'using \"--if-exists replace\" with \"--no-if-exists\" defaults to configuration' '\n> +\ttest_config trailer.ifexists \"doNothing\" &&\n> +\tcat complex_message_body >expected &&\n> +\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n> +\t\tFixes: Z\n> +\t\tAcked-by: Z\n> +\t\tReviewed-by: Z\n> +\t\tSigned-off-by: Z\n> +\tEOF\n> +\tgit interpret-trailers --if-exists replace --no-if-exists --trailer \"Fixes: 53\" \\\n> +\t\t<complex_message >actual &&\n> +\ttest_cmp expected actual\n> +'\n> +\n> +# No \"ifexists\" configuration is set, so using \"--no-if-exists\" makes it default\n> +# to addIfDifferentNeighbor. Because we do have a different neighbor \"Fixes: 53\"\n> +# (because it got added by overriding with \"--if-exists replace\" earlier in the\n> +# arguments list), we add \"Signed-off-by: addme\".\n> +test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured' '\n> +\tcat complex_message_body >expected &&\n> +\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n> +\t\tAcked-by: Z\n> +\t\tReviewed-by: Z\n> +\t\tSigned-off-by: Z\n> +\t\tFixes: 53\n> +\t\tSigned-off-by: addme\n> +\tEOF\n> +\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n> +\t\t--trailer \"Signed-off-by: addme\" <complex_message >actual &&\n> +\ttest_cmp expected actual\n> +'\n> +\n> +# The second \"Fixes: 53\" trailer is discarded, because the \"--no-if-exists\" here\n> +# makes us default to addIfDifferentNeighbor, and we already added the \"Fixes:\n> +# 53\" trailer earlier in the argument list.\n> +test_expect_success 'using \"--no-if-exists\" defaults to hardcoded default if nothing configured (no addition)' '\n> +\tcat complex_message_body >expected &&\n> +\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n> +\t\tAcked-by: Z\n> +\t\tReviewed-by: Z\n> +\t\tSigned-off-by: Z\n> +\t\tFixes: 53\n> +\tEOF\n> +\tgit interpret-trailers --if-exists replace --trailer \"Fixes: 53\" --no-if-exists \\\n> +\t\t--trailer \"Fixes: 53\" <complex_message >actual &&\n> +\ttest_cmp expected actual\n> +'\n> +\n>  test_expect_success 'using \"ifExists = replace\"' '\n>  \ttest_config trailer.fix.key \"Fixes: \" &&\n>  \ttest_config trailer.fix.ifExists \"replace\" &&\n> @@ -1425,6 +1522,39 @@ test_expect_success 'using \"ifMissing = doNothing\"' '\n>  \ttest_cmp expected actual\n>  '\n>  \n> +# Ignore the \"IgnoredTrailer\" because of \"--if-missing doNothing\", but also\n> +# ignore the \"StillIgnoredTrailer\" because we set \"trailer.ifMissing\" to\n> +# \"doNothing\" in configuration.\n> +test_expect_success 'using \"--no-if-missing\" defaults to configuration' '\n> +\ttest_config trailer.ifMissing \"doNothing\" &&\n> +\tcat complex_message_body >expected &&\n> +\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n> +\t\t\tFixes: Z\n> +\t\t\tAcked-by: Z\n> +\t\t\tReviewed-by: Z\n> +\t\t\tSigned-off-by: Z\n> +\tEOF\n> +\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n> +\t\t\t--trailer \"StillIgnoredTrailer: ignoreme\" <complex_message >actual &&\n> +\ttest_cmp expected actual\n> +'\n> +\n> +# Add the \"AddedTrailer\" because the \"--no-if-missing\" clears the \"--if-missing\n> +# doNothing\" from earlier in the argument list.\n> +test_expect_success 'using \"--no-if-missing\" defaults to hardcoded default if nothing configured' '\n> +\tcat complex_message_body >expected &&\n> +\tsed -e \"s/ Z\\$/ /\" >>expected <<-\\EOF &&\n> +\t\t\tFixes: Z\n> +\t\t\tAcked-by: Z\n> +\t\t\tReviewed-by: Z\n> +\t\t\tSigned-off-by: Z\n> +\t\t\tAddedTrailer: addme\n> +\tEOF\n> +\tgit interpret-trailers --if-missing doNothing --trailer \"IgnoredTrailer: ignoreme\" --no-if-missing \\\n> +\t\t\t--trailer \"AddedTrailer: addme\" <complex_message >actual &&\n> +\ttest_cmp expected actual\n> +'\n> +\n>  test_expect_success 'default \"where\" is now \"after\"' '\n>  \tgit config trailer.where \"after\" &&\n>  \ttest_config trailer.ack.ifExists \"add\" &&\n"},{"id":"481578","messageId":"xmqqbkecs55h.fsf@gitster.g","threadId":"60067","inReplyTo":"3e58b6f5ea264a2c42ffbd008405b46626e0f864.1694125210.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 06/13] trailer --no-divider help: describe usual \"---\" meaning","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-09-08T21:53:46Z","receivedAt":"2023-09-08T21:53:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Linus Arver <linusa@google.com>\n>\n> It's unclear what treating something \"specially\" means.\n\nGood.\n\n>\n> Signed-off-by: Linus Arver <linusa@google.com>\n> ---\n>  builtin/interpret-trailers.c | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n>\n> diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\n> index cf4f703c4e2..a7623dbfb2e 100644\n> --- a/builtin/interpret-trailers.c\n> +++ b/builtin/interpret-trailers.c\n> @@ -109,7 +109,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n>  \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n>  \t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"set parsing options\"),\n>  \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n> -\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat --- specially\")),\n> +\t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n>  \t\tOPT_CALLBACK(0, \"trailer\", &trailers, N_(\"trailer\"),\n>  \t\t\t\tN_(\"trailer(s) to add\"), option_parse_trailer),\n>  \t\tOPT_END()\n"},{"id":"481579","messageId":"xmqq7cp0s4z4.fsf@gitster.g","threadId":"60067","inReplyTo":"ef6b77016cd50c438fb58d79ffb10f748ddc5244.1694125210.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 09/13] trailer --parse docs: add explanation for its usefulness","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-09-08T21:57:35Z","receivedAt":"2023-09-08T21:57:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n>  --parse::\n>  \tA convenience alias for `--only-trailers --only-input\n> -\t--unfold`.\n> +\t--unfold`. This makes it easier to only see the trailers coming from the\n> +\tinput without influencing them with any command line options or\n> +\tconfiguration variables, while also making the output machine-friendly with\n> +\t--unfold.\n\nNicely explained.  Without a concise explanation like this, it is\nhard to see what the value of the \"convenience\" alias actually is.\n"},{"id":"482038","messageId":"20230919221337.2177936-1-jonathantanmy@google.com","threadId":"60067","inReplyTo":"040766861e21afe5f686299560677e429be11844.1694125210.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 05/13] trailer: trailer location is a place, not an action","fromName":"Jonathan Tan","fromEmail":"jonathantanmy@google.com","sentAt":"2023-09-19T22:13:37Z","receivedAt":"2023-09-19T22:14:29Z","isPatch":true,"sender":{"key":"jonathantanmy@fastmail.com","avatar":null},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> From: Linus Arver <linusa@google.com>\n> \n> Fix the help text to say \"placement\" instead of \"action\" because the\n> values are placements, not actions.\n> \n> While we're at it, tweak the documentation to say \"placements\" instead\n> of \"values\", similar to how the existing language for \"--if-exists\" uses\n> the word \"action\" to describe both the syntax (with the phrase\n> \"--if-exists <action>\") and the possible values (with the phrase\n> \"possible actions\").\n> \n> Signed-off-by: Linus Arver <linusa@google.com>\n> ---\n>  Documentation/git-interpret-trailers.txt | 2 +-\n>  builtin/interpret-trailers.c             | 2 +-\n>  2 files changed, 2 insertions(+), 2 deletions(-)\n> \n> diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\n> index 72f5bdb652f..b5284c3d33f 100644\n> --- a/Documentation/git-interpret-trailers.txt\n> +++ b/Documentation/git-interpret-trailers.txt\n> @@ -117,7 +117,7 @@ OPTIONS\n>  \tand applies to all '--trailer' options until the next occurrence of\n>  \t'--where' or '--no-where'. Upon encountering '--no-where', clear the\n>  \teffect of any previous use of '--where', such that the relevant configuration\n> -\tvariables are no longer overridden. Possible values are `after`,\n> +\tvariables are no longer overridden. Possible placements are `after`,\n>  \t`before`, `end` or `start`.\n>  \n>  --if-exists <action>::\n\nNot shown in the diff as printed in this email, but this option is\nindeed documented with \"<placement>\". Up to and including this patch\nmakes sense.\n \n"},{"id":"482040","messageId":"20230919221655.2178777-1-jonathantanmy@google.com","threadId":"60067","inReplyTo":"d1780a0127a749902d60249b531869ee9cd1a5f6.1694125210.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 07/13] trailer --parse help: expose aliased options","fromName":"Jonathan Tan","fromEmail":"jonathantanmy@google.com","sentAt":"2023-09-19T22:16:54Z","receivedAt":"2023-09-19T22:17:02Z","isPatch":true,"sender":{"key":"jonathantanmy@fastmail.com","avatar":null},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c\n> index a7623dbfb2e..5f3e1a38eee 100644\n> --- a/builtin/interpret-trailers.c\n> +++ b/builtin/interpret-trailers.c\n> @@ -107,7 +107,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)\n>  \t\tOPT_BOOL(0, \"only-trailers\", &opts.only_trailers, N_(\"output only the trailers\")),\n>  \t\tOPT_BOOL(0, \"only-input\", &opts.only_input, N_(\"do not apply config rules\")),\n>  \t\tOPT_BOOL(0, \"unfold\", &opts.unfold, N_(\"join whitespace-continued values\")),\n> -\t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"set parsing options\"),\n> +\t\tOPT_CALLBACK_F(0, \"parse\", &opts, NULL, N_(\"alias for --only-trailers --only-input --unfold\"),\n>  \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),\n>  \t\tOPT_BOOL(0, \"no-divider\", &opts.no_divider, N_(\"do not treat \\\"---\\\" as the end of input\")),\n>  \t\tOPT_CALLBACK(0, \"trailer\", &trailers, N_(\"trailer\"),\n\nIndeed, parse_opt_parse() sets the 3 options described in the commit\nmessage. Looks good.\n"},{"id":"482042","messageId":"20230919225926.2189091-1-jonathantanmy@google.com","threadId":"60067","inReplyTo":"0b9525db5a0787fdc71834abad9151aa03acc497.1694125210.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 13/13] trailer doc: <token> is a <key> or <keyAlias>, not both","fromName":"Jonathan Tan","fromEmail":"jonathantanmy@google.com","sentAt":"2023-09-19T22:59:26Z","receivedAt":"2023-09-19T22:59:31Z","isPatch":true,"sender":{"key":"jonathantanmy@fastmail.com","avatar":null},"body":"\"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> @@ -248,34 +258,40 @@ With `add`, a new trailer will be added.\n>  +\n>  With `doNothing`, nothing will be done.\n>  \n> -trailer.<token>.key::\n> -\tThis `key` will be used instead of <token> in the trailer. At\n> -\tthe end of this key, a separator can appear and then some\n> -\tspace characters. By default the only valid separator is ':',\n> -\tbut this can be changed using the `trailer.separators` config\n> -\tvariable.\n> +trailer.<keyAlias>.key::\n> +\tDefines a <keyAlias> for the <key>. The <keyAlias> must be a\n> +\tprefix (case does not matter) of the <key>. For example, in `git\n> +\tconfig trailer.ack.key \"Acked-by\"` the \"Acked-by\" is the <key> and\n> +\tthe \"ack\" is the <keyAlias>. This configuration allows the shorter\n> +\t`--trailer \"ack:...\"` invocation on the command line using the \"ack\"\n> +\t<keyAlias> instead of the longer `--trailer \"Acked-by:...\"`.\n> ++\n> +At the end of the <key>, a separator can appear and then some\n> +space characters. By default the only valid separator is ':',\n> +but this can be changed using the `trailer.separators` config\n> +variable.\n\nI think all the other patches will be a great help to the user, but I'm\non the fence about this one. Someone who knows these trailer components\nby their old names might be confused upon seeing tne new ones, so I'm\ninclined to minimize such changes. I do think that the new names make\nmore sense, though.\n\nThe documentation doesn't seem to say what happens when trailer.ack.cmd\nand trailer.Acked-by.cmd (replace \"cmd\" with whatever) are defined, but\nthat was true previously too (and knowing this does not really enable\nthe user to be able to do something they previously couldn't, so this\nis fine).\n"},{"id":"482048","messageId":"owlyy1h1ibm3.fsf@fine.c.googlers.com","threadId":"60067","inReplyTo":"20230919225926.2189091-1-jonathantanmy@google.com","subject":"Re: [PATCH v3 13/13] trailer doc: <token> is a <key> or <keyAlias>, not both","fromName":"Linus Arver","fromEmail":"linusa@google.com","sentAt":"2023-09-20T06:48:20Z","receivedAt":"2023-09-20T06:48:28Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"Jonathan Tan <jonathantanmy@google.com> writes:\n\n> \"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>> @@ -248,34 +258,40 @@ With `add`, a new trailer will be added.\n>>  +\n>>  With `doNothing`, nothing will be done.\n>>  \n>> -trailer.<token>.key::\n>> -\tThis `key` will be used instead of <token> in the trailer. At\n>> -\tthe end of this key, a separator can appear and then some\n>> -\tspace characters. By default the only valid separator is ':',\n>> -\tbut this can be changed using the `trailer.separators` config\n>> -\tvariable.\n>> +trailer.<keyAlias>.key::\n>> +\tDefines a <keyAlias> for the <key>. The <keyAlias> must be a\n>> +\tprefix (case does not matter) of the <key>. For example, in `git\n>> +\tconfig trailer.ack.key \"Acked-by\"` the \"Acked-by\" is the <key> and\n>> +\tthe \"ack\" is the <keyAlias>. This configuration allows the shorter\n>> +\t`--trailer \"ack:...\"` invocation on the command line using the \"ack\"\n>> +\t<keyAlias> instead of the longer `--trailer \"Acked-by:...\"`.\n>> ++\n>> +At the end of the <key>, a separator can appear and then some\n>> +space characters. By default the only valid separator is ':',\n>> +but this can be changed using the `trailer.separators` config\n>> +variable.\n>\n> I think all the other patches will be a great help to the user, but I'm\n> on the fence about this one.\n\nAck. I'm OK with dropping this patch (I assume I don't need to reroll\nthis series for that?).\n\n> Someone who knows these trailer components\n> by their old names might be confused upon seeing tne new ones, so I'm\n> inclined to minimize such changes.\n\nTrue, I had some inclination to do the same kind of change but for the\ntrailer.c code also (that code uses the \"token\" language also,\nfurthering the ambiguity, sadly) but wanted to just do the user-facing\npart first because I thought the users shouldn't need to know about the\ninternals anyway.\n\nIf I did revise this patch to include the same changes in trailer.c and\nnot just the docs, would you be more willing to support the (new) patch?\nI'm mainly curious about what will make you more comfortable to accept\nthis change.\n\n> I do think that the new names make\n> more sense, though.\n\nThanks!\n\n> The documentation doesn't seem to say what happens when trailer.ack.cmd\n> and trailer.Acked-by.cmd (replace \"cmd\" with whatever) are defined, but\n> that was true previously too (and knowing this does not really enable\n> the user to be able to do something they previously couldn't, so this\n> is fine).\n\nAh interesting point. I'll try to remember this when I revisit this\npatch again in the (near?) future.\n"},{"id":"482068","messageId":"xmqq8r90dh2v.fsf@gitster.g","threadId":"60067","inReplyTo":"20230919225926.2189091-1-jonathantanmy@google.com","subject":"Re: [PATCH v3 13/13] trailer doc: <token> is a <key> or <keyAlias>, not both","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-09-20T15:01:28Z","receivedAt":"2023-09-20T15:01:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Tan <jonathantanmy@google.com> writes:\n\n> \"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>> @@ -248,34 +258,40 @@ With `add`, a new trailer will be added.\n>>  +\n>>  With `doNothing`, nothing will be done.\n>>  \n>> -trailer.<token>.key::\n>> -\tThis `key` will be used instead of <token> in the trailer. At\n>> -\tthe end of this key, a separator can appear and then some\n>> -\tspace characters. By default the only valid separator is ':',\n>> -\tbut this can be changed using the `trailer.separators` config\n>> -\tvariable.\n>> +trailer.<keyAlias>.key::\n>> +\tDefines a <keyAlias> for the <key>. The <keyAlias> must be a\n>> +\tprefix (case does not matter) of the <key>. For example, in `git\n>> +\tconfig trailer.ack.key \"Acked-by\"` the \"Acked-by\" is the <key> and\n>> +\tthe \"ack\" is the <keyAlias>. This configuration allows the shorter\n>> +\t`--trailer \"ack:...\"` invocation on the command line using the \"ack\"\n>> +\t<keyAlias> instead of the longer `--trailer \"Acked-by:...\"`.\n>> ++\n>> +At the end of the <key>, a separator can appear and then some\n>> +space characters. By default the only valid separator is ':',\n>> +but this can be changed using the `trailer.separators` config\n>> +variable.\n>\n> I think all the other patches will be a great help to the user, but I'm\n> on the fence about this one. Someone who knows these trailer components\n> by their old names might be confused upon seeing tne new ones, so I'm\n> inclined to minimize such changes. I do think that the new names make\n> more sense, though.\n\nAs long as the new names describe the world order better than the\nold description, I do not mind rephrasing the documentation, and you\nseem to find the more descriptive <keyAlias> easier to understand\ncompared to the non-descriptive <token>.  Adding a concrete example\n(ack vs acked-by) is also a good change.\n\n"},{"id":"482162","messageId":"owly5y42t67e.fsf@fine.c.googlers.com","threadId":"60067","inReplyTo":"xmqq8r90dh2v.fsf@gitster.g","subject":"Re: [PATCH v3 13/13] trailer doc: <token> is a <key> or <keyAlias>, not both","fromName":"Linus Arver","fromEmail":"linusa@google.com","sentAt":"2023-09-22T18:26:29Z","receivedAt":"2023-09-22T18:26:34Z","isPatch":true,"sender":{"key":"linus@ucla.edu","avatar":null},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Jonathan Tan <jonathantanmy@google.com> writes:\n>\n>> \"Linus Arver via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>>> @@ -248,34 +258,40 @@ With `add`, a new trailer will be added.\n>>>  +\n>>>  With `doNothing`, nothing will be done.\n>>>  \n>>> -trailer.<token>.key::\n>>> -\tThis `key` will be used instead of <token> in the trailer. At\n>>> -\tthe end of this key, a separator can appear and then some\n>>> -\tspace characters. By default the only valid separator is ':',\n>>> -\tbut this can be changed using the `trailer.separators` config\n>>> -\tvariable.\n>>> +trailer.<keyAlias>.key::\n>>> +\tDefines a <keyAlias> for the <key>. The <keyAlias> must be a\n>>> +\tprefix (case does not matter) of the <key>. For example, in `git\n>>> +\tconfig trailer.ack.key \"Acked-by\"` the \"Acked-by\" is the <key> and\n>>> +\tthe \"ack\" is the <keyAlias>. This configuration allows the shorter\n>>> +\t`--trailer \"ack:...\"` invocation on the command line using the \"ack\"\n>>> +\t<keyAlias> instead of the longer `--trailer \"Acked-by:...\"`.\n>>> ++\n>>> +At the end of the <key>, a separator can appear and then some\n>>> +space characters. By default the only valid separator is ':',\n>>> +but this can be changed using the `trailer.separators` config\n>>> +variable.\n>>\n>> I think all the other patches will be a great help to the user, but I'm\n>> on the fence about this one. Someone who knows these trailer components\n>> by their old names might be confused upon seeing tne new ones, so I'm\n>> inclined to minimize such changes. I do think that the new names make\n>> more sense, though.\n>\n> As long as the new names describe the world order better than the\n> old description, I do not mind rephrasing the documentation, and you\n> seem to find the more descriptive <keyAlias> easier to understand\n> compared to the non-descriptive <token>.  Adding a concrete example\n> (ack vs acked-by) is also a good change.\n\nSGTM (i.e., I am OK to keep this patch as is). So I will not re-roll.\n\nIn the future I will be cleaning up more of the trailer system to make\nuse of the disinction between the key vs keyAlias where appropriate.\n\nThanks!\n"},{"id":"484692","messageId":"20231110063318.54745-1-tenglong.tl@alibaba-inc.com","threadId":"60067","inReplyTo":"0b9525db5a0787fdc71834abad9151aa03acc497.1694125210.git.gitgitgadget@gmail.com","subject":"[PATCH v3 13/13] trailer doc: <token> is a <key> or <keyAlias>, not both","fromName":"Teng Long","fromEmail":"dyroneteng@gmail.com","sentAt":"2023-11-10T06:33:18Z","receivedAt":"2023-11-10T06:33:33Z","isPatch":true,"sender":{"key":"dyroneteng@gmail.com","avatar":"https://avatars.githubusercontent.com/u/7803958?v=4"},"body":"Linus Arver <linusa@google.com> writes:\n\n> diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt\n> index 25433e1a1ff..418265f044d 100644\n> --- a/Documentation/git-interpret-trailers.txt\n> +++ b/Documentation/git-interpret-trailers.txt\n> @@ -9,7 +9,7 @@ SYNOPSIS\n>  --------\n>  [verse]\n>  'git interpret-trailers' [--in-place] [--trim-empty]\n> -\t\t\t[(--trailer <token>[(=|:)<value>])...]\n> +\t\t\t[(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n\nMaybe use 'key-alias' instead of 'keyAlias'? After checking the naming in some\nother documents, it seems that they are basically in the former format, not\ncamel case format.\n\nThanks.\n"}]}