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/
This commit is contained in:
commit
1487eb68f7
21
git.c
21
git.c
@ -2,6 +2,7 @@
|
|||||||
#include "exec_cmd.h"
|
#include "exec_cmd.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
|
#include "run-command.h"
|
||||||
|
|
||||||
const char git_usage_string[] =
|
const char git_usage_string[] =
|
||||||
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
|
"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 {
|
|||||||
int option;
|
int option;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int run_command(struct cmd_struct *p, int argc, const char **argv)
|
static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -384,7 +385,7 @@ static void handle_internal_command(int argc, const char **argv)
|
|||||||
struct cmd_struct *p = commands+i;
|
struct cmd_struct *p = commands+i;
|
||||||
if (strcmp(p->cmd, cmd))
|
if (strcmp(p->cmd, cmd))
|
||||||
continue;
|
continue;
|
||||||
exit(run_command(p, argc, argv));
|
exit(run_builtin(p, argc, argv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +393,7 @@ static void execv_dashed_external(const char **argv)
|
|||||||
{
|
{
|
||||||
struct strbuf cmd = STRBUF_INIT;
|
struct strbuf cmd = STRBUF_INIT;
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
|
int status;
|
||||||
|
|
||||||
strbuf_addf(&cmd, "git-%s", argv[0]);
|
strbuf_addf(&cmd, "git-%s", argv[0]);
|
||||||
|
|
||||||
@ -406,10 +408,17 @@ static void execv_dashed_external(const char **argv)
|
|||||||
|
|
||||||
trace_argv_printf(argv, "trace: exec:");
|
trace_argv_printf(argv, "trace: exec:");
|
||||||
|
|
||||||
/* execvp() can only ever return if it fails */
|
/*
|
||||||
execvp(cmd.buf, (char **)argv);
|
* if we fail because the command is not found, it is
|
||||||
|
* OK to return. Otherwise, we just pass along the status code.
|
||||||
trace_printf("trace: exec failed: %s\n", strerror(errno));
|
*/
|
||||||
|
status = run_command_v_opt(argv, 0);
|
||||||
|
if (status != -ERR_RUN_COMMAND_EXEC) {
|
||||||
|
if (IS_RUN_COMMAND_ERR(status))
|
||||||
|
die("unable to run '%s'", argv[0]);
|
||||||
|
exit(-status);
|
||||||
|
}
|
||||||
|
errno = ENOENT; /* as if we called execvp */
|
||||||
|
|
||||||
argv[0] = tmp;
|
argv[0] = tmp;
|
||||||
|
|
||||||
|
@ -118,7 +118,9 @@ int start_command(struct child_process *cmd)
|
|||||||
} else {
|
} else {
|
||||||
execvp(cmd->argv[0], (char *const*) cmd->argv);
|
execvp(cmd->argv[0], (char *const*) cmd->argv);
|
||||||
}
|
}
|
||||||
die("exec %s failed.", cmd->argv[0]);
|
trace_printf("trace: exec '%s' failed: %s\n", cmd->argv[0],
|
||||||
|
strerror(errno));
|
||||||
|
exit(127);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
|
int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
|
||||||
@ -187,6 +189,7 @@ int start_command(struct child_process *cmd)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cmd->pid < 0) {
|
if (cmd->pid < 0) {
|
||||||
|
int err = errno;
|
||||||
if (need_in)
|
if (need_in)
|
||||||
close_pair(fdin);
|
close_pair(fdin);
|
||||||
else if (cmd->in)
|
else if (cmd->in)
|
||||||
@ -197,7 +200,9 @@ int start_command(struct child_process *cmd)
|
|||||||
close(cmd->out);
|
close(cmd->out);
|
||||||
if (need_err)
|
if (need_err)
|
||||||
close_pair(fderr);
|
close_pair(fderr);
|
||||||
return -ERR_RUN_COMMAND_FORK;
|
return err == ENOENT ?
|
||||||
|
-ERR_RUN_COMMAND_EXEC :
|
||||||
|
-ERR_RUN_COMMAND_FORK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_in)
|
if (need_in)
|
||||||
@ -236,9 +241,14 @@ static int wait_or_whine(pid_t pid)
|
|||||||
if (!WIFEXITED(status))
|
if (!WIFEXITED(status))
|
||||||
return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
|
return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
|
||||||
code = WEXITSTATUS(status);
|
code = WEXITSTATUS(status);
|
||||||
if (code)
|
switch (code) {
|
||||||
|
case 127:
|
||||||
|
return -ERR_RUN_COMMAND_EXEC;
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
return -code;
|
return -code;
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ enum {
|
|||||||
ERR_RUN_COMMAND_WAITPID_SIGNAL,
|
ERR_RUN_COMMAND_WAITPID_SIGNAL,
|
||||||
ERR_RUN_COMMAND_WAITPID_NOEXIT,
|
ERR_RUN_COMMAND_WAITPID_NOEXIT,
|
||||||
};
|
};
|
||||||
|
#define IS_RUN_COMMAND_ERR(x) ((x) <= -ERR_RUN_COMMAND_FORK)
|
||||||
|
|
||||||
struct child_process {
|
struct child_process {
|
||||||
const char **argv;
|
const char **argv;
|
||||||
|
Loading…
Reference in New Issue
Block a user