Skip to content

Commit 4fa0882

Browse files
committed
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
2 parents fa232d4 + 6396258 commit 4fa0882

11 files changed

+69
-35
lines changed

convert.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,11 @@ static int filter_buffer(int fd, void *data)
249249
struct child_process child_process;
250250
struct filter_params *params = (struct filter_params *)data;
251251
int write_err, status;
252-
const char *argv[] = { "sh", "-c", params->cmd, NULL };
252+
const char *argv[] = { params->cmd, NULL };
253253

254254
memset(&child_process, 0, sizeof(child_process));
255255
child_process.argv = argv;
256+
child_process.use_shell = 1;
256257
child_process.in = -1;
257258
child_process.out = fd;
258259

diff.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2294,7 +2294,7 @@ static void run_external_diff(const char *pgm,
22942294
}
22952295
*arg = NULL;
22962296
fflush(NULL);
2297-
retval = run_command_v_opt(spawn_arg, 0);
2297+
retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL);
22982298
remove_tempfile();
22992299
if (retval) {
23002300
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,
38183818
*arg = NULL;
38193819

38203820
memset(&child, 0, sizeof(child));
3821+
child.use_shell = 1;
38213822
child.argv = argv;
38223823
child.out = -1;
38233824
if (start_command(&child) != 0 ||

editor.c

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,9 @@ int launch_editor(const char *path, struct strbuf *buffer, const char *const *en
3636
return error("Terminal is dumb, but EDITOR unset");
3737

3838
if (strcmp(editor, ":")) {
39-
size_t len = strlen(editor);
40-
int i = 0;
41-
int failed;
42-
const char *args[6];
43-
struct strbuf arg0 = STRBUF_INIT;
39+
const char *args[] = { editor, path, NULL };
4440

45-
if (strcspn(editor, "|&;<>()$`\\\"' \t\n*?[#~=%") != len) {
46-
/* there are specials */
47-
strbuf_addf(&arg0, "%s \"$@\"", editor);
48-
args[i++] = "sh";
49-
args[i++] = "-c";
50-
args[i++] = arg0.buf;
51-
}
52-
args[i++] = editor;
53-
args[i++] = path;
54-
args[i] = NULL;
55-
56-
failed = run_command_v_opt_cd_env(args, 0, NULL, env);
57-
strbuf_release(&arg0);
58-
if (failed)
41+
if (run_command_v_opt_cd_env(args, RUN_USING_SHELL, NULL, env))
5942
return error("There was a problem with the editor '%s'.",
6043
editor);
6144
}

imap-send.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -965,17 +965,13 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
965965
/* open connection to IMAP server */
966966

967967
if (srvc->tunnel) {
968-
const char *argv[4];
968+
const char *argv[] = { srvc->tunnel, NULL };
969969
struct child_process tunnel = {0};
970970

971971
imap_info("Starting tunnel '%s'... ", srvc->tunnel);
972972

973-
argv[0] = "sh";
974-
argv[1] = "-c";
975-
argv[2] = srvc->tunnel;
976-
argv[3] = NULL;
977-
978973
tunnel.argv = argv;
974+
tunnel.use_shell = 1;
979975
tunnel.in = -1;
980976
tunnel.out = -1;
981977
if (start_command(&tunnel))

ll-merge.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
175175
{ "B", temp[2] },
176176
{ NULL }
177177
};
178-
const char *args[] = { "sh", "-c", NULL, NULL };
178+
const char *args[] = { NULL, NULL };
179179
int status, fd, i;
180180
struct stat st;
181181

@@ -190,8 +190,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
190190

191191
strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
192192

193-
args[2] = cmd.buf;
194-
status = run_command_v_opt(args, 0);
193+
args[0] = cmd.buf;
194+
status = run_command_v_opt(args, RUN_USING_SHELL);
195195
fd = open(temp[1], O_RDONLY);
196196
if (fd < 0)
197197
goto bad;

pager.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static void pager_preexec(void)
2828
}
2929
#endif
3030

31-
static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
31+
static const char *pager_argv[] = { NULL, NULL };
3232
static struct child_process pager_process;
3333

3434
static void wait_for_pager(void)
@@ -81,7 +81,8 @@ void setup_pager(void)
8181
spawned_pager = 1; /* means we are emitting to terminal */
8282

8383
/* spawn the pager */
84-
pager_argv[2] = pager;
84+
pager_argv[0] = pager;
85+
pager_process.use_shell = 1;
8586
pager_process.argv = pager_argv;
8687
pager_process.in = -1;
8788
if (!getenv("LESS")) {

run-command.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,50 @@ static inline void dup_devnull(int to)
1515
close(fd);
1616
}
1717

18+
static const char **prepare_shell_cmd(const char **argv)
19+
{
20+
int argc, nargc = 0;
21+
const char **nargv;
22+
23+
for (argc = 0; argv[argc]; argc++)
24+
; /* just counting */
25+
/* +1 for NULL, +3 for "sh -c" plus extra $0 */
26+
nargv = xmalloc(sizeof(*nargv) * (argc + 1 + 3));
27+
28+
if (argc < 1)
29+
die("BUG: shell command is empty");
30+
31+
if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
32+
nargv[nargc++] = "sh";
33+
nargv[nargc++] = "-c";
34+
35+
if (argc < 2)
36+
nargv[nargc++] = argv[0];
37+
else {
38+
struct strbuf arg0 = STRBUF_INIT;
39+
strbuf_addf(&arg0, "%s \"$@\"", argv[0]);
40+
nargv[nargc++] = strbuf_detach(&arg0, NULL);
41+
}
42+
}
43+
44+
for (argc = 0; argv[argc]; argc++)
45+
nargv[nargc++] = argv[argc];
46+
nargv[nargc] = NULL;
47+
48+
return nargv;
49+
}
50+
51+
#ifndef WIN32
52+
static int execv_shell_cmd(const char **argv)
53+
{
54+
const char **nargv = prepare_shell_cmd(argv);
55+
trace_argv_printf(nargv, "trace: exec:");
56+
execvp(nargv[0], (char **)nargv);
57+
free(nargv);
58+
return -1;
59+
}
60+
#endif
61+
1862
int start_command(struct child_process *cmd)
1963
{
2064
int need_in, need_out, need_err;
@@ -123,6 +167,8 @@ int start_command(struct child_process *cmd)
123167
cmd->preexec_cb();
124168
if (cmd->git_cmd) {
125169
execv_git_cmd(cmd->argv);
170+
} else if (cmd->use_shell) {
171+
execv_shell_cmd(cmd->argv);
126172
} else {
127173
execvp(cmd->argv[0], (char *const*) cmd->argv);
128174
}
@@ -179,6 +225,8 @@ int start_command(struct child_process *cmd)
179225

180226
if (cmd->git_cmd) {
181227
cmd->argv = prepare_git_cmd(cmd->argv);
228+
} else if (cmd->use_shell) {
229+
cmd->argv = prepare_shell_cmd(cmd->argv);
182230
}
183231

184232
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,
297345
cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
298346
cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
299347
cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
348+
cmd->use_shell = opt & RUN_USING_SHELL ? 1 : 0;
300349
}
301350

302351
int run_command_v_opt(const char **argv, int opt)

run-command.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct child_process {
3333
unsigned git_cmd:1; /* if this is to be git sub-command */
3434
unsigned silent_exec_failure:1;
3535
unsigned stdout_to_stderr:1;
36+
unsigned use_shell:1;
3637
void (*preexec_cb)(void);
3738
};
3839

@@ -46,6 +47,7 @@ extern int run_hook(const char *index_file, const char *name, ...);
4647
#define RUN_GIT_CMD 2 /*If this is to be git sub-command */
4748
#define RUN_COMMAND_STDOUT_TO_STDERR 4
4849
#define RUN_SILENT_EXEC_FAILURE 8
50+
#define RUN_USING_SHELL 16
4951
int run_command_v_opt(const char **argv, int opt);
5052

5153
/*

t/t0021-conversion.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ test_description='blob conversion via gitattributes'
44

55
. ./test-lib.sh
66

7-
cat <<\EOF >rot13.sh
7+
cat <<EOF >rot13.sh
8+
#!$SHELL_PATH
89
tr \
910
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
1011
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'

t/t4030-diff-textconv.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ test_expect_success 'file is considered binary by plumbing' '
4848

4949
test_expect_success 'setup textconv filters' '
5050
echo file diff=foo >.gitattributes &&
51-
git config diff.foo.textconv "$PWD"/hexdump &&
51+
git config diff.foo.textconv "\"$(pwd)\""/hexdump &&
5252
git config diff.fail.textconv false
5353
'
5454

0 commit comments

Comments
 (0)