Added hook in git-receive-pack After successful update of a ref,
$GIT_DIR/hooks/update refname old-sha1 new-sha2 is called if present. This allows e.g sending of a mail with pushed commits on the remote repository. Documentation update with example hook included. Signed-off-by: Josef Weidendorfer <[EMAIL PROTECTED]> ------------------------------------------------ diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.txt @@ -20,10 +20,25 @@ This command is usually not invoked dire The UI for the protocol is on the 'git-send-pack' side, and the program pair is meant to be used to push updates to remote repository. For pull operations, see 'git-fetch-pack' and 'git-clone-pack'. +The command allows for creation and fast forwarding of sha1 refs +(heads/tags) on the local end. After each successful update, the +following external hook script is called if it is present: + + $GIT_DIR/hooks/update refname sha1-old sha1-new + +It is assured that sha1-old is an ancestor of sha1-new (otherwise, +the update would have not been allowed). refname is relative to +$GIT_DIR; e.g. for the master head this is "refs/heads/master". +Using this hook, it is easy to generate mails on updates to +the local repository. This example script sends a mail with +the commits pushed to the repository: + + #!/bin/sh + git-rev-list --pretty "$3" "^$2" | + mail -r $USER -s "New commits on $1" [EMAIL PROTECTED] OPTIONS ------- <directory>:: The repository to sync into. diff --git a/receive-pack.c b/receive-pack.c --- a/receive-pack.c +++ b/receive-pack.c @@ -53,10 +53,53 @@ static int verify_old_ref(const char *na if (memcmp(buffer, hex_contents, 40)) return -1; return 0; } +static const char *update_hook = "hooks/update"; + +static void updatehook(const char *name, unsigned char *old_sha1, unsigned char *new_sha1) +{ + if (access(update_hook, X_OK) < 0) return; + fprintf(stderr, "executing update hook for %s\n", name); + + pid_t pid = fork(); + + if (pid < 0) + die("hook fork failed"); + if (!pid) { + execlp(update_hook, update_hook, name, old_sha1, new_sha1, NULL); + die("hook execute failed"); + } + + for (;;) { + int status, code; + int retval = waitpid(pid, &status, 0); + + if (retval < 0) { + if (errno == EINTR) + continue; + die("waitpid failed (%s)", strerror(retval)); + } + if (retval != pid) + die("waitpid is confused"); + if (WIFSIGNALED(status)) { + fprintf(stderr, "%s died of signal %d", + update_hook, WTERMSIG(status)); + return; + } + if (!WIFEXITED(status)) + die("%s died out of really strange complications", + update_hook); + code = WEXITSTATUS(status); + if (code) + fprintf(stderr, "%s exited with error code %d", + update_hook, code); + return; + } +} + static void update(const char *name, unsigned char *old_sha1, unsigned char *new_sha1) { char new_hex[60], *old_hex, *lock_name; int newfd, namelen, written; @@ -93,10 +136,12 @@ static void update(const char *name, uns if (rename(lock_name, name) < 0) { unlink(lock_name); die("unable to replace %s", name); } fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex); + + updatehook(name, old_hex, new_hex); } /* * This gets called after(if) we've successfully - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html