Merge branch 'lt/run'

* lt/run:
  Check for IO errors after running a command
  Clean up internal command handling
This commit is contained in:
Junio C Hamano 2007-06-30 11:22:08 -07:00
commit 39741ab1c5

71
git.c
View File

@ -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);