summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 0bc3cdf)
raw | patch | inline | side by side (parent: 0bc3cdf)
author | Junio C Hamano <junkio@cox.net> | |
Tue, 2 Aug 2005 21:24:22 +0000 (14:24 -0700) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Wed, 3 Aug 2005 05:51:09 +0000 (22:51 -0700) |
The earlier one conflated update and post-update hooks for no
good reason. Correct that ugly hack. Now post-update hooks
will take the list of successfully updated refs.
Signed-off-by: Junio C Hamano <junkio@cox.net>
good reason. Correct that ugly hack. Now post-update hooks
will take the list of successfully updated refs.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Documentation/git-receive-pack.txt | patch | blob | history | |
receive-pack.c | patch | blob | history | |
run-command.c | patch | blob | history | |
run-command.h | patch | blob | history |
index 7f95e44046ce2a28053bdddaec8d730257c873a0..2f1a1f8ebb4ef8655f791bfb31ba6f032d3d9236 100644 (file)
disallow updating the named ref. Otherwise it should exit with
zero.
-The same hook is also called with an empty string as refname and
-no other arguments just before git-receive-pack exits. This can
-be used to implement repository wide cleanup task if needed.
-The exit code from this hook invocation is ignored; the only
-thing left for git-receive-pack to do at that point is to exit
-itself anyway.
-
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
- case "$#,$1" in
- 1,) # help packed repository pulled via dumb protocol.
- git-update-server-info
- ;;
- *) # mail out commit update information.
- if expr "$2" : '0*$' >/dev/null
- then
- echo "Created now ref."
+ # mail out commit update information.
+ if expr "$2" : '0*$' >/dev/null
+ then
+ echo "Created a new ref, with the following commits:"
git-rev-list --pretty "$2"
- else
- echo "New commits"
+ else
+ echo "New commits:"
git-rev-list --pretty "$3" "^$2"
- fi |
- mail -s "Changes to ref $1" commit-list@mydomain
- esac
+ fi |
+ mail -s "Changes to ref $1" commit-list@mydomain
exit 0
+Another hook $GIT_DIR/hooks/post-update, if exists and
+executable, is called with the list of refs that have been
+updated. This can be used to implement repository wide cleanup
+task if needed. The exit code from this hook invocation is
+ignored; the only thing left for git-receive-pack to do at that
+point is to exit itself anyway. This hook can be used, for
+example, to run "git-update-server-info" if the repository is
+packed and is served via a dumb transport.
+
+ #!/bin/sh
+ exec git-update-server-info
+
OPTIONS
-------
<directory>::
diff --git a/receive-pack.c b/receive-pack.c
index 314b0d7c6b76662c2ea41a834d2801a457f26446..8d6faaaa9c995f5552549557176a48303a0820ac 100644 (file)
--- a/receive-pack.c
+++ b/receive-pack.c
struct command {
struct command *next;
+ unsigned char updated;
unsigned char old_sha1[20];
unsigned char new_sha1[20];
char ref_name[0];
}
}
-static void update(const char *name, unsigned char *old_sha1, unsigned char *new_sha1)
+static int update(const char *name,
+ unsigned char *old_sha1, unsigned char *new_sha1)
{
char new_hex[60], *old_hex, *lock_name;
int newfd, namelen, written;
@@ -101,11 +103,13 @@ static void update(const char *name, unsigned char *old_sha1, unsigned char *new
strcpy(new_hex, sha1_to_hex(new_sha1));
old_hex = sha1_to_hex(old_sha1);
if (!has_sha1_file(new_sha1))
- die("unpack should have generated %s, but I can't find it!", new_hex);
+ return error("unpack should have generated %s, "
+ "but I can't find it!", new_hex);
newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
if (newfd < 0)
- die("unable to create %s (%s)", lock_name, strerror(errno));
+ return error("unable to create %s (%s)",
+ lock_name, strerror(errno));
/* Write the ref with an ending '\n' */
new_hex[40] = '\n';
@@ -117,24 +121,54 @@ static void update(const char *name, unsigned char *old_sha1, unsigned char *new
close(newfd);
if (written != 41) {
unlink(lock_name);
- die("unable to write %s", lock_name);
+ return error("unable to write %s", lock_name);
}
if (verify_old_ref(name, old_hex) < 0) {
unlink(lock_name);
- die("%s changed during push", name);
+ return error("%s changed during push", name);
}
if (run_update_hook(name, old_hex, new_hex)) {
unlink(lock_name);
- fprintf(stderr, "hook declined to update %s\n", name);
+ return error("hook declined to update %s\n", name);
}
else if (rename(lock_name, name) < 0) {
unlink(lock_name);
- die("unable to replace %s", name);
+ return error("unable to replace %s", name);
}
- else
+ else {
fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
+ return 0;
+ }
}
+static char update_post_hook[] = "hooks/post-update";
+
+static void run_update_post_hook(struct command *cmd)
+{
+ struct command *cmd_p;
+ int argc;
+ char **argv;
+
+ if (access(update_post_hook, X_OK) < 0)
+ return;
+ for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
+ if (!cmd_p->updated)
+ continue;
+ argc++;
+ }
+ argv = xmalloc(sizeof(*argv) * (1 + argc));
+ argv[0] = update_post_hook;
+
+ for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
+ if (!cmd_p->updated)
+ continue;
+ argv[argc] = xmalloc(strlen(cmd_p->ref_name) + 1);
+ strcpy(argv[argc], cmd_p->ref_name);
+ argc++;
+ }
+ argv[argc] = NULL;
+ run_command_v(argc, argv);
+}
/*
* This gets called after(if) we've successfully
struct command *cmd = commands;
while (cmd) {
- update(cmd->ref_name, cmd->old_sha1, cmd->new_sha1);
+ cmd->updated = !update(cmd->ref_name,
+ cmd->old_sha1, cmd->new_sha1);
cmd = cmd->next;
}
- run_update_hook("", NULL, NULL);
+ run_update_post_hook(commands);
}
static void read_head_info(void)
diff --git a/run-command.c b/run-command.c
index 5117f627c86de68ed9f3da36e9e0c7b41a6e4691..5787a5095548c6530a4d987705a3189ed57356c4 100644 (file)
--- a/run-command.c
+++ b/run-command.c
#include "run-command.h"
#include <sys/wait.h>
-static int run_external_command(int argc, const char **argv)
+int run_command_v(int argc, char **argv)
{
pid_t pid = fork();
return -ERR_RUN_COMMAND_FORK;
if (!pid) {
execvp(argv[0], (char *const*) argv);
- return -ERR_RUN_COMMAND_EXEC;
+ die("exec %s failed.", argv[0]);
}
for (;;) {
int status, code;
int run_command(const char *cmd, ...)
{
int argc;
- const char *argv[MAX_RUN_COMMAND_ARGS];
+ 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;
+ argv[0] = (char*) cmd;
argc = 1;
while (argc < MAX_RUN_COMMAND_ARGS) {
arg = argv[argc++] = va_arg(param, char *);
va_end(param);
if (MAX_RUN_COMMAND_ARGS <= argc)
return error("too many args to run %s", cmd);
- return run_external_command(argc, argv);
+ return run_command_v(argc, argv);
}
diff --git a/run-command.h b/run-command.h
index 4f646139e5386d6f34d6cd777473876e17ab8d66..5ee0972241030d2f6d87a465c4726e6cc3ab803a 100644 (file)
--- a/run-command.h
+++ b/run-command.h
ERR_RUN_COMMAND_WAITPID_NOEXIT,
};
+int run_command_v(int argc, char **argv);
int run_command(const char *cmd, ...);
#endif