In https://lore.kernel.org/git/xmqqv99i4ck2.fsf@gitster.g/ Junio and Christian talked about the problem of using strbuf_replace() to replace $ARG: 1. if the user's script has more than one $ARG, only the first one will be replaced, which is incorrected. 2. $ARG is textually replaced without shell syntax, which may result a broken command when $ARG include some unmatching single quote, very unsafe. Now pass trailer value as $1 to the trailer command with another trailer.<token>.cmd config, to solve these above two problems, We are now writing documents that are more readable and correct than before. ZheNing Hu (2): [GSOC] docs: correct descript of trailer.<token>.command [GSOC] trailer: add new .cmd config option Documentation/git-interpret-trailers.txt | 90 ++++++++++++++++++++---- t/t7513-interpret-trailers.sh | 84 ++++++++++++++++++++++ trailer.c | 37 +++++++--- 3 files changed, 187 insertions(+), 24 deletions(-) base-commit: 142430338477d9d1bb25be66267225fb58498d92 Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-913%2Fadlternative%2Ftrailer-pass-ARG-env-v8 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-913/adlternative/trailer-pass-ARG-env-v8 Pull-Request: https://github.com/gitgitgadget/git/pull/913 Range-diff vs v7: -: ------------ > 1: 505903811df8 [GSOC] docs: correct descript of trailer.<token>.command 1: 1e9a6572ac6f ! 2: 3dc8983a4702 [GSOC] trailer: add new trailer.<token>.cmd config option @@ Metadata Author: ZheNing Hu <adlternative@xxxxxxxxx> ## Commit message ## - [GSOC] trailer: add new trailer.<token>.cmd config option + [GSOC] trailer: add new .cmd config option The `trailer.<token>.command` configuration variable specifies a command (run via the shell, so it does not have @@ Commit message * Because $ARG is textually replaced without regard to the shell language syntax, even '$ARG' (inside a single-quote pair), which a user would expect to stay intact, would be - replaced, and worse, if the value had an unmatching single + replaced, and worse, if the value had an unmatched single quote (imagine a name like "O'Connor", substituted into NAME='$ARG' to make it NAME='O'Connor'), it would result in a broken command that is not syntactically correct (or @@ Commit message Introduce a new `trailer.<token>.cmd` configuration that takes higher precedence to deprecate and eventually remove - `trailer.<token>.command`, which passes the value as a - parameter to the command. Instead of "$ARG", the users will + `trailer.<token>.command`, which passes the value as an + argument to the command. Instead of "$ARG", users can refer to the value as positional argument, $1, in their scripts. @@ Documentation/git-interpret-trailers.txt: trailer.<token>.command:: specified <token>. + -When this option is specified, the behavior is as if a special --'<token>=<value>' argument were added at the beginning of the command --line, where <value> is taken to be the standard output of the --specified command with any leading and trailing whitespace trimmed --off. +-'--trailer <token>=<value>' argument was added at the beginning of +-the "git interpret-trailers" command, where <value> is taken to be the +-standard output of the specified command with any leading and trailing +-whitespace trimmed off. +When this option is specified, the first occurrence of substring $ARG is +replaced with the value given to the `interpret-trailer` command for the -+same token. This option behaves in a similar way as ".cmd", however, it -+passes the value through $ARG. - + --If the command contains the `$ARG` string, this string will be --replaced with the <value> part of an existing trailer with the same --<token>, if any, before the command is launched. -+".command" has been deprecated due to the $ARG in the user's command can -+only be replaced once and the original way of replacing $ARG was not safe. -+Now the preferred option is using "trailer.<token>.cmd", which use position -+argument to pass the value. ++same token. It passes the value through `$ARG`, otherwise this option behaves ++in the same way as 'trailer.<token>.cmd'. ++ -+When both .cmd and .command are given for the same <token>, -+.cmd is used and .command is ignored. ++The 'trailer.<token>.command' option has been deprecated due to the fact ++that $ARG in the user's command can only be replaced once and that the ++original way of replacing $ARG was not safe. Now the preferred option is ++'trailer.<token>.cmd', which uses a positional argument to pass the value. + + +-The first occurrence of substring `$ARG` will be replaced with the +-<value> part of an existing trailer with the same <token>, if any, +-before the command is launched. ++When both 'trailer.<token>.cmd' and 'trailer.<token>.command' are given ++for the same <token>, 'trailer.<token>.cmd' is used and ++'trailer.<token>.command' is ignored. + +trailer.<token>.cmd:: + The command specified by this configuration variable is run @@ Documentation/git-interpret-trailers.txt: trailer.<token>.command:: + from the command is then used as the value for the <token> + in the resulting trailer. ++ -+When this option is specified, the behavior is as if a '<token>=<value>' -+argument were added at the beginning of the "git interpret-trailers" -+command, the command specified by this configuration variable will be -+called with an empty string as the argument. ++When this option is specified, the behavior is as if a ++'--trailer <token>=<value>' argument was added at the beginning of ++the "git interpret-trailers" command, the command specified by this ++configuration variable will be called with an empty string as the ++argument. + - If some '<token>=<value>' arguments are also passed on the command --line, when a 'trailer.<token>.command' is configured, the command will --also be executed for each of these arguments. And the <value> part of --these arguments, if any, will be used to replace the `$ARG` string in --the command. -+line, when a 'trailer.<token>.cmd' is configured, the command is run -+once for each `--trailer <token>=<value>` on the command line with the -+same <token>. And the <value> part of these arguments, if any, will be -+passed to the command as its first argument. +-If some '<token>=<value>' arguments are also passed on the command +-line, when a 'trailer.<token>.command' is configured, the command is run +-once for each these arguments with the same <token>. And the <value> +-part of these arguments, if any, will be used to replace the first `$ARG` +-string in the command. ++If some '--trailer <token>=<value>' arguments are also passed on the ++command line, when a 'trailer.<token>.cmd' is configured, the command ++is run once for each `--trailer <token>=<value>` on the command line ++with the same <token>. And the <value> part of these arguments, if any, ++will be passed to the command as its first argument. EXAMPLES -------- @@ t/t7513-interpret-trailers.sh: test_expect_success 'setup a commit' ' + test_when_finished "git config --unset trailer.fix.cmd" && + git config trailer.fix.ifExists "replace" && + git config trailer.fix.cmd "test -n \"\$1\" && git log -1 --oneline --format=\"%h (%aN)\" \ -+ --abbrev-commit --abbrev=14 \"\$1\" || true" && ++ --abbrev-commit --abbrev=14 \"\$1\" || true" && + git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" \ + --abbrev-commit --abbrev=14 \$ARG" && + FIXED=$(git log -1 --oneline --format="%h (%aN)" --abbrev-commit --abbrev=14 HEAD) && @@ t/t7513-interpret-trailers.sh: test_expect_success 'setup a commit' ' + test_expect_success 'with command using $ARG' ' git config trailer.fix.ifExists "replace" && -- git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG" && -+ git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" \ -+ --abbrev-commit --abbrev=14 \$ARG" && - FIXED=$(git log -1 --oneline --format="%h (%s)" --abbrev-commit --abbrev=14 HEAD) && - cat complex_message_body >expected && - sed -e "s/ Z\$/ /" >>expected <<-EOF && + git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG" && ## trailer.c ## @@ trailer.c: struct conf_info { -- gitgitgadget