mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
Merge branch 'lt/run'
* lt/run: Check for IO errors after running a command Clean up internal command handling
This commit is contained in:
commit
39741ab1c5
71
git.c
71
git.c
|
@ -216,14 +216,53 @@ const char git_version_string[] = GIT_VERSION;
|
|||
*/
|
||||
#define NOT_BARE (1<<2)
|
||||
|
||||
static void handle_internal_command(int argc, const char **argv, char **envp)
|
||||
struct cmd_struct {
|
||||
const char *cmd;
|
||||
int (*fn)(int, const char **, const char *);
|
||||
int option;
|
||||
};
|
||||
|
||||
static int run_command(struct cmd_struct *p, int argc, const char **argv)
|
||||
{
|
||||
int status;
|
||||
struct stat st;
|
||||
const char *prefix;
|
||||
|
||||
prefix = NULL;
|
||||
if (p->option & RUN_SETUP)
|
||||
prefix = setup_git_directory();
|
||||
if (p->option & USE_PAGER)
|
||||
setup_pager();
|
||||
if (p->option & NOT_BARE) {
|
||||
if (is_bare_repository() || is_inside_git_dir())
|
||||
die("%s must be run in a work tree", p->cmd);
|
||||
}
|
||||
trace_argv_printf(argv, argc, "trace: built-in: git");
|
||||
|
||||
status = p->fn(argc, argv, prefix);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Somebody closed stdout? */
|
||||
if (fstat(fileno(stdout), &st))
|
||||
return 0;
|
||||
/* Ignore write errors for pipes and sockets.. */
|
||||
if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
|
||||
return 0;
|
||||
|
||||
/* Check for ENOSPC and EIO errors.. */
|
||||
if (ferror(stdout))
|
||||
die("write failure on standard output");
|
||||
if (fflush(stdout) || fclose(stdout))
|
||||
die("write failure on standard output: %s", strerror(errno));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_internal_command(int argc, const char **argv)
|
||||
{
|
||||
const char *cmd = argv[0];
|
||||
static struct cmd_struct {
|
||||
const char *cmd;
|
||||
int (*fn)(int, const char **, const char *);
|
||||
int option;
|
||||
} commands[] = {
|
||||
static struct cmd_struct commands[] = {
|
||||
{ "add", cmd_add, RUN_SETUP | NOT_BARE },
|
||||
{ "annotate", cmd_annotate, RUN_SETUP | USE_PAGER },
|
||||
{ "apply", cmd_apply },
|
||||
|
@ -307,25 +346,13 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(commands); i++) {
|
||||
struct cmd_struct *p = commands+i;
|
||||
const char *prefix;
|
||||
if (strcmp(p->cmd, cmd))
|
||||
continue;
|
||||
|
||||
prefix = NULL;
|
||||
if (p->option & RUN_SETUP)
|
||||
prefix = setup_git_directory();
|
||||
if (p->option & USE_PAGER)
|
||||
setup_pager();
|
||||
if ((p->option & NOT_BARE) &&
|
||||
(is_bare_repository() || is_inside_git_dir()))
|
||||
die("%s must be run in a work tree", cmd);
|
||||
trace_argv_printf(argv, argc, "trace: built-in: git");
|
||||
|
||||
exit(p->fn(argc, argv, prefix));
|
||||
exit(run_command(p, argc, argv));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv, char **envp)
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const char *cmd = argv[0] ? argv[0] : "git-help";
|
||||
char *slash = strrchr(cmd, '/');
|
||||
|
@ -358,7 +385,7 @@ int main(int argc, const char **argv, char **envp)
|
|||
if (!prefixcmp(cmd, "git-")) {
|
||||
cmd += 4;
|
||||
argv[0] = cmd;
|
||||
handle_internal_command(argc, argv, envp);
|
||||
handle_internal_command(argc, argv);
|
||||
die("cannot handle %s internally", cmd);
|
||||
}
|
||||
|
||||
|
@ -390,7 +417,7 @@ int main(int argc, const char **argv, char **envp)
|
|||
|
||||
while (1) {
|
||||
/* See if it's an internal command */
|
||||
handle_internal_command(argc, argv, envp);
|
||||
handle_internal_command(argc, argv);
|
||||
|
||||
/* .. then try the external ones */
|
||||
execv_git_cmd(argv);
|
||||
|
|
Loading…
Reference in a new issue