]> git.ipfire.org Git - thirdparty/git.git/commitdiff
hooks: convert worktree 'post-checkout' hook to hook library
authorEmily Shaffer <emilyshaffer@google.com>
Wed, 22 Dec 2021 03:59:36 +0000 (04:59 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 7 Jan 2022 23:19:34 +0000 (15:19 -0800)
Move the running of the 'post-checkout' hook away from run-command.h
to the new hook.h library in builtin/worktree.c. For this special case
we need a change to the hook API to teach it to run the hook from a
given directory.

We cannot skip the "absolute_path" flag and just check if "dir" is
specified as we'd then fail to find our hook in the new dir we'd
chdir() to. We currently don't have a use-case for running a hook not
in our "base" repository at a given absolute path, so let's have "dir"
imply absolute_path(find_hook(hook_name)).

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Acked-by: Emily Shaffer <emilyshaffer@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/worktree.c
hook.c
hook.h

index a396cfdc64e4a48f0f56ef2db6a359de43c3017a..6f03afad9740e75a9255cfe7535bdf8211638fab 100644 (file)
@@ -382,21 +382,17 @@ done:
         * is_junk is cleared, but do return appropriate code when hook fails.
         */
        if (!ret && opts->checkout) {
-               const char *hook = find_hook("post-checkout");
-               if (hook) {
-                       const char *env[] = { "GIT_DIR", "GIT_WORK_TREE", NULL };
-                       struct child_process cp = CHILD_PROCESS_INIT;
-                       cp.no_stdin = 1;
-                       cp.stdout_to_stderr = 1;
-                       cp.dir = path;
-                       strvec_pushv(&cp.env_array, env);
-                       cp.trace2_hook_name = "post-checkout";
-                       strvec_pushl(&cp.args, absolute_path(hook),
-                                    oid_to_hex(null_oid()),
-                                    oid_to_hex(&commit->object.oid),
-                                    "1", NULL);
-                       ret = run_command(&cp);
-               }
+               struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
+
+               strvec_pushl(&opt.env, "GIT_DIR", "GIT_WORK_TREE", NULL);
+               strvec_pushl(&opt.args,
+                            oid_to_hex(null_oid()),
+                            oid_to_hex(&commit->object.oid),
+                            "1",
+                            NULL);
+               opt.dir = path;
+
+               ret = run_hooks_opt("post-checkout", &opt);
        }
 
        strvec_clear(&child_env);
diff --git a/hook.c b/hook.c
index 1ad123422b26f640661e2cf076fd55c0c358316f..69a215b2c3c2c3b95a799a56325de9111873b39e 100644 (file)
--- a/hook.c
+++ b/hook.c
@@ -57,6 +57,7 @@ static int pick_next_hook(struct child_process *cp,
        strvec_pushv(&cp->env_array, hook_cb->options->env.v);
        cp->stdout_to_stderr = 1;
        cp->trace2_hook_name = hook_cb->hook_name;
+       cp->dir = hook_cb->options->dir;
 
        strvec_push(&cp->args, hook_path);
        strvec_pushv(&cp->args, hook_cb->options->args.v);
@@ -109,6 +110,7 @@ static void run_hooks_opt_clear(struct run_hooks_opt *options)
 
 int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)
 {
+       struct strbuf abs_path = STRBUF_INIT;
        struct hook_cb_data cb_data = {
                .rc = 0,
                .hook_name = hook_name,
@@ -130,6 +132,11 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)
        }
 
        cb_data.hook_path = hook_path;
+       if (options->dir) {
+               strbuf_add_absolute_path(&abs_path, hook_path);
+               cb_data.hook_path = abs_path.buf;
+       }
+
        run_processes_parallel_tr2(jobs,
                                   pick_next_hook,
                                   notify_start_failure,
@@ -139,6 +146,7 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)
                                   hook_name);
        ret = cb_data.rc;
 cleanup:
+       strbuf_release(&abs_path);
        run_hooks_opt_clear(options);
        return ret;
 }
diff --git a/hook.h b/hook.h
index 54528395953bca8410bde2dac81d9796d8395f97..18d90aedf14066eeac2fc93144d02ea8a6545207 100644 (file)
--- a/hook.h
+++ b/hook.h
@@ -12,6 +12,12 @@ struct run_hooks_opt
 
        /* Emit an error if the hook is missing */
        unsigned int error_if_missing:1;
+
+       /**
+        * An optional initial working directory for the hook,
+        * translates to "struct child_process"'s "dir" member.
+        */
+       const char *dir;
 };
 
 #define RUN_HOOKS_OPT_INIT { \