close(fd[1]);
}
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
static inline void dup_devnull(int to)
{
int fd = open("/dev/null", O_RDWR);
die("BUG: shell command is empty");
if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
nargv[nargc++] = SHELL_PATH;
#else
nargv[nargc++] = "sh";
return nargv;
}
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
static int execv_shell_cmd(const char **argv)
{
const char **nargv = prepare_shell_cmd(argv);
}
#endif
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
static int child_err = 2;
static int child_notifier = -1;
{
int need_in, need_out, need_err;
int fdin[2], fdout[2], fderr[2];
- int failed_errno = failed_errno;
+ int failed_errno;
+ char *str;
/*
* In case of errors we must keep the promise to close FDs
failed_errno = errno;
if (cmd->out > 0)
close(cmd->out);
+ str = "standard input";
goto fail_pipe;
}
cmd->in = fdin[1];
close_pair(fdin);
else if (cmd->in)
close(cmd->in);
+ str = "standard output";
goto fail_pipe;
}
cmd->out = fdout[0];
close_pair(fdout);
else if (cmd->out)
close(cmd->out);
+ str = "standard error";
fail_pipe:
- error("cannot create pipe for %s: %s",
- cmd->argv[0], strerror(failed_errno));
+ error("cannot create %s pipe for %s: %s",
+ str, cmd->argv[0], strerror(failed_errno));
errno = failed_errno;
return -1;
}
trace_argv_printf(cmd->argv, "trace: run_command:");
fflush(NULL);
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
{
int notify_pipe[2];
if (pipe(notify_pipe))
notify_pipe[0] = notify_pipe[1] = -1;
cmd->pid = fork();
+ failed_errno = errno;
if (!cmd->pid) {
/*
* Redirect the channel to write syscall error messages to
}
if (cmd->pid < 0)
error("cannot fork() for %s: %s", cmd->argv[0],
- strerror(failed_errno = errno));
+ strerror(errno));
else if (cmd->clean_on_exit)
mark_child_for_cleanup(cmd->pid);
static pthread_t main_thread;
static int main_thread_set;
static pthread_key_t async_key;
+static pthread_key_t async_die_counter;
static void *run_thread(void *data)
{
exit(128);
}
+
+static int async_die_is_recursing(void)
+{
+ void *ret = pthread_getspecific(async_die_counter);
+ pthread_setspecific(async_die_counter, (void *)1);
+ return ret != NULL;
+}
+
#endif
int start_async(struct async *async)
main_thread_set = 1;
main_thread = pthread_self();
pthread_key_create(&async_key, NULL);
+ pthread_key_create(&async_die_counter, NULL);
set_die_routine(die_async);
+ set_die_is_recursing_routine(async_die_is_recursing);
}
if (proc_in >= 0)
#endif
}
+char *find_hook(const char *name)
+{
+ char *path = git_path("hooks/%s", name);
+ if (access(path, X_OK) < 0)
+ path = NULL;
+
+ return path;
+}
+
int run_hook(const char *index_file, const char *name, ...)
{
struct child_process hook;
va_list args;
int ret;
- if (access(git_path("hooks/%s", name), X_OK) < 0)
+ p = find_hook(name);
+ if (!p)
return 0;
+ argv_array_push(&argv, p);
+
va_start(args, name);
- argv_array_push(&argv, git_path("hooks/%s", name));
while ((p = va_arg(args, const char *)))
argv_array_push(&argv, p);
va_end(args);