From b1bf95bba26c8de1581f401dcab1f743bad7fc1d Mon Sep 17 00:00:00 2001 From: Josef Weidendorfer Date: Sun, 31 Jul 2005 21:17:43 +0200 Subject: [PATCH] Added hook in git-receive-pack Just before updating a ref, $GIT_DIR/hooks/update refname old-sha1 new-sha1 is called if executable. The hook can decline the ref to be updated by exiting with a non-zero status, or allow it to be updated by exiting with a zero status. The mechanism also allows e.g sending of a mail with pushed commits on the remote repository. Documentation update with an example hook is included. jc: The credits of the basic idea and initial implementation go to Josef, but I ended up rewriting major parts of his patch, so bugs are all mine. Also I changed the semantics for the hook from his original version (which were post-update hook) so that the hook can optionally decline to update the ref, and also can be used to implement the overall cleanups. The latter was primarily to implement a suggestion from Linus that calling update-server-info should be made optional. Signed-off-by: Junio C Hamano --- run-command.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 run-command.c (limited to 'run-command.c') diff --git a/run-command.c b/run-command.c new file mode 100644 index 0000000000..5117f627c8 --- /dev/null +++ b/run-command.c @@ -0,0 +1,60 @@ +#include "cache.h" +#include "run-command.h" +#include + +static int run_external_command(int argc, const char **argv) +{ + pid_t pid = fork(); + + if (pid < 0) + return -ERR_RUN_COMMAND_FORK; + if (!pid) { + execvp(argv[0], (char *const*) argv); + return -ERR_RUN_COMMAND_EXEC; + } + for (;;) { + int status, code; + int retval = waitpid(pid, &status, 0); + + if (retval < 0) { + if (errno == EINTR) + continue; + error("waitpid failed (%s)", strerror(retval)); + return -ERR_RUN_COMMAND_WAITPID; + } + if (retval != pid) + return -ERR_RUN_COMMAND_WAITPID_WRONG_PID; + if (WIFSIGNALED(status)) + return -ERR_RUN_COMMAND_WAITPID_SIGNAL; + + if (!WIFEXITED(status)) + return -ERR_RUN_COMMAND_WAITPID_NOEXIT; + code = WEXITSTATUS(status); + if (code) + return -code; + return 0; + } +} + +int run_command(const char *cmd, ...) +{ + int argc; + const char *argv[MAX_RUN_COMMAND_ARGS]; + const char *arg; + va_list param; + + fprintf(stderr, "run-command %s (%d)\n", cmd, ERR_RUN_COMMAND_EXEC); + + va_start(param, cmd); + argv[0] = cmd; + argc = 1; + while (argc < MAX_RUN_COMMAND_ARGS) { + arg = argv[argc++] = va_arg(param, char *); + if (!arg) + break; + } + va_end(param); + if (MAX_RUN_COMMAND_ARGS <= argc) + return error("too many args to run %s", cmd); + return run_external_command(argc, argv); +} -- cgit v1.2.1