[RFC] Add "write-index" hook

Subsystems: the rest

2 messages, 1 author, 2016-06-15 · open the first message on its own page

[RFC] Add "write-index" hook

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:42:15

This is a less hacky way to prevent index access than what I suggested
earlier. It has the additional benefit that you can control access to
the index writing now.

Oh, and the code to run hooks (which die() on errors) has been refactored.

Signed-off-by: Johannes Schindelin <redacted>

---

	While the use of this hook is questionable, I actually like the
	refactoring of the hooks, since it makes it so much easier
	to add new ones.

 index.c        |    7 ++++++
 receive-pack.c |   61 ++------------------------------------------------------
 run-command.c  |   49 +++++++++++++++++++++++++++++++++++++++++++++
 run-command.h  |    2 ++
 4 files changed, 60 insertions(+), 59 deletions(-)

d567efd0ccfb60ae03a81f02f819283767d69011
diff --git a/index.c b/index.c
index ad0eafe..3f6ca1e 100644
--- a/index.c
+++ b/index.c
@@ -3,6 +3,7 @@
  */
 #include <signal.h>
 #include "cache.h"
+#include "run-command.h"
 
 static struct cache_file *cache_file_list;
 
@@ -20,9 +21,15 @@ static void remove_lock_file_on_signal(i
 	remove_lock_file();
 }
 
+static char write_index_hook[] = "hooks/write-index";
+
 int hold_index_file_for_update(struct cache_file *cf, const char *path)
 {
 	int fd;
+
+	if (run_hook(write_index_hook))
+		return error("hook declined to write index\n");
+
 	sprintf(cf->lockfile, "%s.lock", path);
 	fd = open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0666);
 	if (fd >=0 && !cf->next) {
diff --git a/receive-pack.c b/receive-pack.c
index cbe37e7..d52d793 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -59,36 +59,6 @@ static int verify_old_ref(const char *na
 
 static char update_hook[] = "hooks/update";
 
-static int run_update_hook(const char *refname,
-			   char *old_hex, char *new_hex)
-{
-	int code;
-
-	if (access(update_hook, X_OK) < 0)
-		return 0;
-	code = run_command(update_hook, refname, old_hex, new_hex, NULL);
-	switch (code) {
-	case 0:
-		return 0;
-	case -ERR_RUN_COMMAND_FORK:
-		die("hook fork failed");
-	case -ERR_RUN_COMMAND_EXEC:
-		die("hook execute failed");
-	case -ERR_RUN_COMMAND_WAITPID:
-		die("waitpid failed");
-	case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
-		die("waitpid is confused");
-	case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-		fprintf(stderr, "%s died of signal", update_hook);
-		return -1;
-	case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
-		die("%s died strangely", update_hook);
-	default:
-		error("%s exited with error code %d", update_hook, -code);
-		return -code;
-	}
-}
-
 static int update(const char *name,
 		  unsigned char *old_sha1, unsigned char *new_sha1)
 {
@@ -133,7 +103,7 @@ static int update(const char *name,
 		unlink(lock_name);
 		return error("%s changed during push", name);
 	}
-	if (run_update_hook(name, old_hex, new_hex)) {
+	if (run_hook(update_hook, name, old_hex, new_hex)) {
 		unlink(lock_name);
 		return error("hook declined to update %s\n", name);
 	}
@@ -149,33 +119,6 @@ static int update(const char *name,
 
 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_opt(argc, argv, RUN_COMMAND_NO_STDIO);
-}
-
 /*
  * This gets called after(if) we've successfully
  * unpacked the data payload.
@@ -189,7 +132,7 @@ static void execute_commands(void)
 				       cmd->old_sha1, cmd->new_sha1);
 		cmd = cmd->next;
 	}
-	run_update_post_hook(commands);
+	run_hook(update_post_hook, commands);
 }
 
 static void read_head_info(void)
diff --git a/run-command.c b/run-command.c
index 8bf5922..95455ef 100644
--- a/run-command.c
+++ b/run-command.c
@@ -67,3 +67,52 @@ int run_command(const char *cmd, ...)
 		return error("too many args to run %s", cmd);
 	return run_command_v_opt(argc, argv, 0);
 }
+
+int run_hook(const char* hook, ...)
+{
+	int argc;
+	char *argv[MAX_RUN_COMMAND_ARGS];
+	const char *arg;
+	va_list param;
+	int code;
+
+	if (access(hook, X_OK) < 0)
+		return 0;
+
+	va_start(param, hook);
+	argv[0] = (char*) hook;
+	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", hook);
+
+	code = run_command_v_opt(argc, argv, 0);
+
+	switch (code) {
+	case 0:
+		return 0;
+	case -ERR_RUN_COMMAND_FORK:
+		die("hook fork failed");
+	case -ERR_RUN_COMMAND_EXEC:
+		die("hook execute failed");
+	case -ERR_RUN_COMMAND_WAITPID:
+		die("waitpid failed");
+	case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
+		die("waitpid is confused");
+	case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
+		fprintf(stderr, "%s died of signal", hook);
+		return -1;
+	case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
+		die("%s died strangely", hook);
+	default:
+		error("%s exited with error code %d", hook, -code);
+		return -code;
+	}
+}
+
+
diff --git a/run-command.h b/run-command.h
index 2469eea..604176f 100644
--- a/run-command.h
+++ b/run-command.h
@@ -16,5 +16,7 @@ enum {
 int run_command_v_opt(int argc, char **argv, int opt);
 int run_command_v(int argc, char **argv);
 int run_command(const char *cmd, ...);
+/* unlike run_command(), run_hook die()s on errors */
+int run_hook(const char *hook, ...);
 
 #endif
-- 
1.0.0

Re: [RFC] Add "write-index" hook

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:42:15

Hi,

there is an obvious bug in this patch: both calls to run_hook() have to 
have a final NULL argument.

Ciao,
Dscho

P.S.: The reason I did not find this earlier was that I had hooks 
installed, but they were not executable, and thus did not get executed. 
D'oh!
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help