git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/4] run_hook(): enhance the interface to pass arbitrary environment

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 11, 2012, 11:15 UTC
Message-ID
<7vlin7xub7.fsf_-_@alter.siamese.dyndns.org>
In-Reply-To
<7vwr6rxul6.fsf_-_@alter.siamese.dyndns.org>

Originally "run_hook()" that used to live in builtin/commit.c had a perfectly appropriate API and name for a private function to spawn a hook from "git commit" command. The only necessary tweak in the context was to optionally specify which file to use as the index file.

But then we stupidly moved this private API to run-command.c without making the interface suitable for general consumption, and there is no way to tweak environment variables other than GIT_INDEX_FILE when running a hook.

Correct this mistake by adding run_hook_e() that takes an array of environment variables.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * This is the third patch of the more complex of the two approaches.
   Instead of the simpler "setenv()" one, the final one tries to
   limit the environment change only to the hook scripts, without
   affecting the "git commit" process itself. It probably should not
   make much difference in the short run, but later when we want to
   distinguish where the authorship came from, it may be easier to
   tell with this approach as it does not contaminate the environment
   of "git commit" itself with what we obtained from "--author" option.
   Also this is independently a useful refactoring.
 run-command.c |   49 ++++++++++++++++++++++++++++++++++++-------------
 run-command.h |    1 +
 2 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/run-command.c b/run-command.c
index 1db8abf..a51d8e5 100644
--- a/run-command.c
+++ b/run-command.c
@@ -672,36 +672,59 @@ int finish_async(struct async *async)
 #endif
 }
 
-int run_hook(const char *index_file, const char *name, ...)
+static int run_hook_le(const char *const *env,
+		       const char *name,
+		       va_list args)
 {
 	struct child_process hook;
 	struct argv_array argv = ARGV_ARRAY_INIT;
-	const char *p, *env[2];
-	char index[PATH_MAX];
-	va_list args;
+	const char *p;
 	int ret;
 
 	if (access(git_path("hooks/%s", name), X_OK) < 0)
 		return 0;
 
-	va_start(args, name);
 	argv_array_push(&argv, git_path("hooks/%s", name));
 	while ((p = va_arg(args, const char *)))
 		argv_array_push(&argv, p);
-	va_end(args);
 
 	memset(&hook, 0, sizeof(hook));
 	hook.argv = argv.argv;
 	hook.no_stdin = 1;
 	hook.stdout_to_stderr = 1;
-	if (index_file) {
-		snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
-		env[0] = index;
-		env[1] = NULL;
-		hook.env = env;
-	}
-
+	hook.env = env;
 	ret = run_command(&hook);
 	argv_array_clear(&argv);
 	return ret;
 }
+
+int run_hook(const char *index_file, const char *name, ...)
+{
+	const char *const *env = NULL, *env_buf[2];
+	struct strbuf index_buf = STRBUF_INIT;
+	int status;
+	va_list args;
+
+	va_start(args, name);
+	if (index_file) {
+		strbuf_addf(&index_buf, "GIT_INDEX_FILE=%s", index_file);
+		env_buf[0] = index_buf.buf;
+		env_buf[1] = NULL;
+		env = env_buf;
+	}
+	status = run_hook_le(env, name, args);
+	va_end(args);
+	strbuf_release(&index_buf);
+	return status;
+}
+
+int run_hook_e(const char *const *env, const char *name, ...)
+{
+	int status;
+	va_list args;
+
+	va_start(args, name);
+	status = run_hook_le(env, name, args);
+	va_end(args);
+	return status;
+}
diff --git a/run-command.h b/run-command.h
index 44f7d2b..87207b9 100644
--- a/run-command.h
+++ b/run-command.h
@@ -47,6 +47,7 @@ int finish_command(struct child_process *);
 int run_command(struct child_process *);
 
 extern int run_hook(const char *index_file, const char *name, ...);
+extern int run_hook_e(const char *const *, const char *name, ...);
 
 #define RUN_COMMAND_NO_STDIN 1
 #define RUN_GIT_CMD	     2	/*If this is to be git sub-command */
-- 
1.7.10.rc0.33.g8866af
Previous: Jeff KingNext: Junio C Hamano
Message 12 of 13 in “Stop a git commit by a specific author using pre-commit hook”
  1. Adrian CornishMar 9, 2012
  2. Neal KreitzingerMar 10, 2012
  3. Junio C HamanoMar 10, 2012
  4. Neal KreitzingerMar 10, 2012
  5. Junio C HamanoMar 11, 2012
  6. 3/4 test: does pre-commit-hook learn authorship?Junio C Hamano, Mar 11, 2012
  7. Johannes SixtMar 11, 2012
  8. Junio C HamanoMar 11, 2012
  9. 3/4 ident.c: add split_ident_line() to parse formatted ident lineJunio C Hamano, Mar 11, 2012
  10. 3/3 commit: pass author/committer info to hooksJunio C Hamano, Mar 11, 2012
  11. Jeff KingMar 12, 2012
  12. 3/4 run_hook(): enhance the interface to pass arbitrary environmentJunio C Hamano, Mar 11, 2012
  13. 4/4 commit: pass author/committer info to hooksJunio C Hamano, Mar 11, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.