Skip to content

Commit 1487eb6

Browse files
committed
Merge branch 'jk/maint-cleanup-after-exec-failure'
* jk/maint-cleanup-after-exec-failure: git: use run_command() to execute dashed externals run_command(): help callers distinguish errors run_command(): handle missing command errors more gracefully git: s/run_command/run_builtin/
2 parents 2ea3c17 + d8e96fd commit 1487eb6

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

git.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "exec_cmd.h"
33
#include "cache.h"
44
#include "quote.h"
5+
#include "run-command.h"
56

67
const char git_usage_string[] =
78
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
@@ -219,7 +220,7 @@ struct cmd_struct {
219220
int option;
220221
};
221222

222-
static int run_command(struct cmd_struct *p, int argc, const char **argv)
223+
static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
223224
{
224225
int status;
225226
struct stat st;
@@ -384,14 +385,15 @@ static void handle_internal_command(int argc, const char **argv)
384385
struct cmd_struct *p = commands+i;
385386
if (strcmp(p->cmd, cmd))
386387
continue;
387-
exit(run_command(p, argc, argv));
388+
exit(run_builtin(p, argc, argv));
388389
}
389390
}
390391

391392
static void execv_dashed_external(const char **argv)
392393
{
393394
struct strbuf cmd = STRBUF_INIT;
394395
const char *tmp;
396+
int status;
395397

396398
strbuf_addf(&cmd, "git-%s", argv[0]);
397399

@@ -406,10 +408,17 @@ static void execv_dashed_external(const char **argv)
406408

407409
trace_argv_printf(argv, "trace: exec:");
408410

409-
/* execvp() can only ever return if it fails */
410-
execvp(cmd.buf, (char **)argv);
411-
412-
trace_printf("trace: exec failed: %s\n", strerror(errno));
411+
/*
412+
* if we fail because the command is not found, it is
413+
* OK to return. Otherwise, we just pass along the status code.
414+
*/
415+
status = run_command_v_opt(argv, 0);
416+
if (status != -ERR_RUN_COMMAND_EXEC) {
417+
if (IS_RUN_COMMAND_ERR(status))
418+
die("unable to run '%s'", argv[0]);
419+
exit(-status);
420+
}
421+
errno = ENOENT; /* as if we called execvp */
413422

414423
argv[0] = tmp;
415424

run-command.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ int start_command(struct child_process *cmd)
118118
} else {
119119
execvp(cmd->argv[0], (char *const*) cmd->argv);
120120
}
121-
die("exec %s failed.", cmd->argv[0]);
121+
trace_printf("trace: exec '%s' failed: %s\n", cmd->argv[0],
122+
strerror(errno));
123+
exit(127);
122124
}
123125
#else
124126
int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
@@ -187,6 +189,7 @@ int start_command(struct child_process *cmd)
187189
#endif
188190

189191
if (cmd->pid < 0) {
192+
int err = errno;
190193
if (need_in)
191194
close_pair(fdin);
192195
else if (cmd->in)
@@ -197,7 +200,9 @@ int start_command(struct child_process *cmd)
197200
close(cmd->out);
198201
if (need_err)
199202
close_pair(fderr);
200-
return -ERR_RUN_COMMAND_FORK;
203+
return err == ENOENT ?
204+
-ERR_RUN_COMMAND_EXEC :
205+
-ERR_RUN_COMMAND_FORK;
201206
}
202207

203208
if (need_in)
@@ -236,9 +241,14 @@ static int wait_or_whine(pid_t pid)
236241
if (!WIFEXITED(status))
237242
return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
238243
code = WEXITSTATUS(status);
239-
if (code)
244+
switch (code) {
245+
case 127:
246+
return -ERR_RUN_COMMAND_EXEC;
247+
case 0:
248+
return 0;
249+
default:
240250
return -code;
241-
return 0;
251+
}
242252
}
243253
}
244254

run-command.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ enum {
1010
ERR_RUN_COMMAND_WAITPID_SIGNAL,
1111
ERR_RUN_COMMAND_WAITPID_NOEXIT,
1212
};
13+
#define IS_RUN_COMMAND_ERR(x) ((x) <= -ERR_RUN_COMMAND_FORK)
1314

1415
struct child_process {
1516
const char **argv;

0 commit comments

Comments
 (0)