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

Reply via email to