Merge branch 'jk/run-command-use-shell'
* jk/run-command-use-shell: t4030, t4031: work around bogus MSYS bash path conversion diff: run external diff helper with shell textconv: use shell to run helper editor: use run_command's shell feature run-command: optimize out useless shell calls run-command: convert simple callsites to use_shell t0021: use $SHELL_PATH for the filter script run-command: add "use shell" option
This commit is contained in:
commit
4fa088209c
@ -249,10 +249,11 @@ static int filter_buffer(int fd, void *data)
|
||||
struct child_process child_process;
|
||||
struct filter_params *params = (struct filter_params *)data;
|
||||
int write_err, status;
|
||||
const char *argv[] = { "sh", "-c", params->cmd, NULL };
|
||||
const char *argv[] = { params->cmd, NULL };
|
||||
|
||||
memset(&child_process, 0, sizeof(child_process));
|
||||
child_process.argv = argv;
|
||||
child_process.use_shell = 1;
|
||||
child_process.in = -1;
|
||||
child_process.out = fd;
|
||||
|
||||
|
3
diff.c
3
diff.c
@ -2294,7 +2294,7 @@ static void run_external_diff(const char *pgm,
|
||||
}
|
||||
*arg = NULL;
|
||||
fflush(NULL);
|
||||
retval = run_command_v_opt(spawn_arg, 0);
|
||||
retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL);
|
||||
remove_tempfile();
|
||||
if (retval) {
|
||||
fprintf(stderr, "external diff died, stopping at %s.\n", name);
|
||||
@ -3818,6 +3818,7 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
|
||||
*arg = NULL;
|
||||
|
||||
memset(&child, 0, sizeof(child));
|
||||
child.use_shell = 1;
|
||||
child.argv = argv;
|
||||
child.out = -1;
|
||||
if (start_command(&child) != 0 ||
|
||||
|
21
editor.c
21
editor.c
@ -36,26 +36,9 @@ int launch_editor(const char *path, struct strbuf *buffer, const char *const *en
|
||||
return error("Terminal is dumb, but EDITOR unset");
|
||||
|
||||
if (strcmp(editor, ":")) {
|
||||
size_t len = strlen(editor);
|
||||
int i = 0;
|
||||
int failed;
|
||||
const char *args[6];
|
||||
struct strbuf arg0 = STRBUF_INIT;
|
||||
const char *args[] = { editor, path, NULL };
|
||||
|
||||
if (strcspn(editor, "|&;<>()$`\\\"' \t\n*?[#~=%") != len) {
|
||||
/* there are specials */
|
||||
strbuf_addf(&arg0, "%s \"$@\"", editor);
|
||||
args[i++] = "sh";
|
||||
args[i++] = "-c";
|
||||
args[i++] = arg0.buf;
|
||||
}
|
||||
args[i++] = editor;
|
||||
args[i++] = path;
|
||||
args[i] = NULL;
|
||||
|
||||
failed = run_command_v_opt_cd_env(args, 0, NULL, env);
|
||||
strbuf_release(&arg0);
|
||||
if (failed)
|
||||
if (run_command_v_opt_cd_env(args, RUN_USING_SHELL, NULL, env))
|
||||
return error("There was a problem with the editor '%s'.",
|
||||
editor);
|
||||
}
|
||||
|
@ -965,17 +965,13 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
|
||||
/* open connection to IMAP server */
|
||||
|
||||
if (srvc->tunnel) {
|
||||
const char *argv[4];
|
||||
const char *argv[] = { srvc->tunnel, NULL };
|
||||
struct child_process tunnel = {0};
|
||||
|
||||
imap_info("Starting tunnel '%s'... ", srvc->tunnel);
|
||||
|
||||
argv[0] = "sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = srvc->tunnel;
|
||||
argv[3] = NULL;
|
||||
|
||||
tunnel.argv = argv;
|
||||
tunnel.use_shell = 1;
|
||||
tunnel.in = -1;
|
||||
tunnel.out = -1;
|
||||
if (start_command(&tunnel))
|
||||
|
@ -175,7 +175,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
|
||||
{ "B", temp[2] },
|
||||
{ NULL }
|
||||
};
|
||||
const char *args[] = { "sh", "-c", NULL, NULL };
|
||||
const char *args[] = { NULL, NULL };
|
||||
int status, fd, i;
|
||||
struct stat st;
|
||||
|
||||
@ -190,8 +190,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
|
||||
|
||||
strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
|
||||
|
||||
args[2] = cmd.buf;
|
||||
status = run_command_v_opt(args, 0);
|
||||
args[0] = cmd.buf;
|
||||
status = run_command_v_opt(args, RUN_USING_SHELL);
|
||||
fd = open(temp[1], O_RDONLY);
|
||||
if (fd < 0)
|
||||
goto bad;
|
||||
|
5
pager.c
5
pager.c
@ -28,7 +28,7 @@ static void pager_preexec(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
|
||||
static const char *pager_argv[] = { NULL, NULL };
|
||||
static struct child_process pager_process;
|
||||
|
||||
static void wait_for_pager(void)
|
||||
@ -81,7 +81,8 @@ void setup_pager(void)
|
||||
spawned_pager = 1; /* means we are emitting to terminal */
|
||||
|
||||
/* spawn the pager */
|
||||
pager_argv[2] = pager;
|
||||
pager_argv[0] = pager;
|
||||
pager_process.use_shell = 1;
|
||||
pager_process.argv = pager_argv;
|
||||
pager_process.in = -1;
|
||||
if (!getenv("LESS")) {
|
||||
|
@ -15,6 +15,50 @@ static inline void dup_devnull(int to)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static const char **prepare_shell_cmd(const char **argv)
|
||||
{
|
||||
int argc, nargc = 0;
|
||||
const char **nargv;
|
||||
|
||||
for (argc = 0; argv[argc]; argc++)
|
||||
; /* just counting */
|
||||
/* +1 for NULL, +3 for "sh -c" plus extra $0 */
|
||||
nargv = xmalloc(sizeof(*nargv) * (argc + 1 + 3));
|
||||
|
||||
if (argc < 1)
|
||||
die("BUG: shell command is empty");
|
||||
|
||||
if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
|
||||
nargv[nargc++] = "sh";
|
||||
nargv[nargc++] = "-c";
|
||||
|
||||
if (argc < 2)
|
||||
nargv[nargc++] = argv[0];
|
||||
else {
|
||||
struct strbuf arg0 = STRBUF_INIT;
|
||||
strbuf_addf(&arg0, "%s \"$@\"", argv[0]);
|
||||
nargv[nargc++] = strbuf_detach(&arg0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (argc = 0; argv[argc]; argc++)
|
||||
nargv[nargc++] = argv[argc];
|
||||
nargv[nargc] = NULL;
|
||||
|
||||
return nargv;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
static int execv_shell_cmd(const char **argv)
|
||||
{
|
||||
const char **nargv = prepare_shell_cmd(argv);
|
||||
trace_argv_printf(nargv, "trace: exec:");
|
||||
execvp(nargv[0], (char **)nargv);
|
||||
free(nargv);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int start_command(struct child_process *cmd)
|
||||
{
|
||||
int need_in, need_out, need_err;
|
||||
@ -123,6 +167,8 @@ fail_pipe:
|
||||
cmd->preexec_cb();
|
||||
if (cmd->git_cmd) {
|
||||
execv_git_cmd(cmd->argv);
|
||||
} else if (cmd->use_shell) {
|
||||
execv_shell_cmd(cmd->argv);
|
||||
} else {
|
||||
execvp(cmd->argv[0], (char *const*) cmd->argv);
|
||||
}
|
||||
@ -179,6 +225,8 @@ fail_pipe:
|
||||
|
||||
if (cmd->git_cmd) {
|
||||
cmd->argv = prepare_git_cmd(cmd->argv);
|
||||
} else if (cmd->use_shell) {
|
||||
cmd->argv = prepare_shell_cmd(cmd->argv);
|
||||
}
|
||||
|
||||
cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
|
||||
@ -297,6 +345,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,
|
||||
cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
|
||||
cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
|
||||
cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
|
||||
cmd->use_shell = opt & RUN_USING_SHELL ? 1 : 0;
|
||||
}
|
||||
|
||||
int run_command_v_opt(const char **argv, int opt)
|
||||
|
@ -33,6 +33,7 @@ struct child_process {
|
||||
unsigned git_cmd:1; /* if this is to be git sub-command */
|
||||
unsigned silent_exec_failure:1;
|
||||
unsigned stdout_to_stderr:1;
|
||||
unsigned use_shell:1;
|
||||
void (*preexec_cb)(void);
|
||||
};
|
||||
|
||||
@ -46,6 +47,7 @@ extern int run_hook(const char *index_file, const char *name, ...);
|
||||
#define RUN_GIT_CMD 2 /*If this is to be git sub-command */
|
||||
#define RUN_COMMAND_STDOUT_TO_STDERR 4
|
||||
#define RUN_SILENT_EXEC_FAILURE 8
|
||||
#define RUN_USING_SHELL 16
|
||||
int run_command_v_opt(const char **argv, int opt);
|
||||
|
||||
/*
|
||||
|
@ -4,7 +4,8 @@ test_description='blob conversion via gitattributes'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
cat <<\EOF >rot13.sh
|
||||
cat <<EOF >rot13.sh
|
||||
#!$SHELL_PATH
|
||||
tr \
|
||||
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
|
||||
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
|
||||
|
@ -48,7 +48,7 @@ test_expect_success 'file is considered binary by plumbing' '
|
||||
|
||||
test_expect_success 'setup textconv filters' '
|
||||
echo file diff=foo >.gitattributes &&
|
||||
git config diff.foo.textconv "$PWD"/hexdump &&
|
||||
git config diff.foo.textconv "\"$(pwd)\""/hexdump &&
|
||||
git config diff.fail.textconv false
|
||||
'
|
||||
|
||||
|
@ -54,7 +54,7 @@ chmod +x dump
|
||||
|
||||
test_expect_success 'setup textconv' '
|
||||
echo file diff=foo >.gitattributes &&
|
||||
git config diff.foo.textconv "$PWD"/dump
|
||||
git config diff.foo.textconv "\"$(pwd)\""/dump
|
||||
'
|
||||
|
||||
test_expect_success 'rewrite diff respects textconv' '
|
||||
|
Loading…
Reference in New Issue
Block a user