diff options
author | Junio C Hamano <gitster@pobox.com> | 2007-06-30 11:22:08 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2007-06-30 11:22:08 -0700 |
commit | 39741ab1c54c6e7411b983f2a64d5813bc5b4059 (patch) | |
tree | 6bd2af7da39695e7807475274c64b8cfad17ec38 | |
parent | 90c88a698e8bf36ff5812a177f8b6c2f878f229c (diff) | |
parent | 0f157315a1020fce76fe2c5a703e40684b9b1699 (diff) | |
download | git-39741ab1c54c6e7411b983f2a64d5813bc5b4059.tar.gz git-39741ab1c54c6e7411b983f2a64d5813bc5b4059.tar.xz |
Merge branch 'lt/run'
* lt/run:
Check for IO errors after running a command
Clean up internal command handling
-rw-r--r-- | git.c | 71 |
1 files changed, 49 insertions, 22 deletions
@@ -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); |