From: ZheNing Hu <adlternative@xxxxxxxxx> When we use subprocess to run a shell-script, if we have any args, git will add extra $@ to the end of the shell-script, This can pass positional parameters correctly, But if we just want to use some of these passed parameters, git will still add an extra "$@", which contains all positional parameters we passed. This does not meet our expectations. E.g. our shell-script is: "echo \"\$1\"" and pass $1 "abc", git will change our script to: "echo \"\$1\" \"$@\"" The positional parameters we entered will be printed repeatedly. So let add a new `shell_no_implicit_args` to `struct child_process`, which can suppress the joining of $@ if `shell_no_implicit_args` is set to 1, this will allow us to use only few of positional args in multi-parameter shell script, instead of using all of them. Signed-off-by: ZheNing Hu <adlternative@xxxxxxxxx> --- run-command.c | 8 ++++---- run-command.h | 1 + trailer.c | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/run-command.c b/run-command.c index be6bc128cd9d..a2cf6177f522 100644 --- a/run-command.c +++ b/run-command.c @@ -264,7 +264,7 @@ int sane_execvp(const char *file, char * const argv[]) return -1; } -static const char **prepare_shell_cmd(struct strvec *out, const char **argv) +static const char **prepare_shell_cmd(struct strvec *out, const char **argv, int shell_no_implicit_args) { if (!argv[0]) BUG("shell command is empty"); @@ -281,7 +281,7 @@ static const char **prepare_shell_cmd(struct strvec *out, const char **argv) * If we have no extra arguments, we do not even need to * bother with the "$@" magic. */ - if (!argv[1]) + if (!argv[1] || shell_no_implicit_args) strvec_push(out, argv[0]); else strvec_pushf(out, "%s \"$@\"", argv[0]); @@ -416,7 +416,7 @@ static int prepare_cmd(struct strvec *out, const struct child_process *cmd) if (cmd->git_cmd) { prepare_git_cmd(out, cmd->argv); } else if (cmd->use_shell) { - prepare_shell_cmd(out, cmd->argv); + prepare_shell_cmd(out, cmd->argv, cmd->shell_no_implicit_args); } else { strvec_pushv(out, cmd->argv); } @@ -929,7 +929,7 @@ int start_command(struct child_process *cmd) if (cmd->git_cmd) cmd->argv = prepare_git_cmd(&nargv, cmd->argv); else if (cmd->use_shell) - cmd->argv = prepare_shell_cmd(&nargv, cmd->argv); + cmd->argv = prepare_shell_cmd(&nargv, cmd->argv, cmd->shell_no_implicit_args); cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, (char**) cmd->env, cmd->dir, fhin, fhout, fherr); diff --git a/run-command.h b/run-command.h index d08414a92e73..9597c987c5bb 100644 --- a/run-command.h +++ b/run-command.h @@ -133,6 +133,7 @@ struct child_process { * argv[1], etc, do not need to be shell-quoted. */ unsigned use_shell:1; + unsigned shell_no_implicit_args:1; unsigned stdout_to_stderr:1; unsigned clean_on_exit:1; diff --git a/trailer.c b/trailer.c index be4e9726421c..35dd0f4c8512 100644 --- a/trailer.c +++ b/trailer.c @@ -231,6 +231,7 @@ static char *apply_command(const char *command, const char *arg) cp.env = local_repo_env; cp.no_stdin = 1; cp.use_shell = 1; + cp.shell_no_implicit_args = 1; if (capture_command(&cp, &buf, 1024)) { error(_("running trailer command '%s' failed"), cmd.buf); -- gitgitgadget