@@ -248,6 +248,25 @@ void run_hooks_opt_init(struct run_hooks_opt *o)
o->run_hookdir = configured_hookdir_opt();
}
+int hook_exists(const char *hookname, enum hookdir_opt should_run_hookdir)
+{
+ const char *value = NULL; /* throwaway */
+ struct strbuf hook_key = STRBUF_INIT;
+ int could_run_hookdir;
+
+ if (should_run_hookdir == HOOKDIR_USE_CONFIG)
+ should_run_hookdir = configured_hookdir_opt();
+
+ could_run_hookdir = (should_run_hookdir == HOOKDIR_INTERACTIVE ||
+ should_run_hookdir == HOOKDIR_WARN ||
+ should_run_hookdir == HOOKDIR_YES)
+ && !!find_hook(hookname);
+
+ strbuf_addf(&hook_key, "hook.%s.command", hookname);
+
+ return (!git_config_get_value(hook_key.buf, &value)) || could_run_hookdir;
+}
+
void run_hooks_opt_clear(struct run_hooks_opt *o)
{
strvec_clear(&o->env);
@@ -23,6 +23,7 @@ struct list_head* hook_list(const char *hookname);
enum hookdir_opt
{
+ HOOKDIR_USE_CONFIG,
HOOKDIR_NO,
HOOKDIR_ERROR,
HOOKDIR_WARN,
@@ -56,6 +57,15 @@ struct run_hooks_opt
void run_hooks_opt_init(struct run_hooks_opt *o);
void run_hooks_opt_clear(struct run_hooks_opt *o);
+/*
+ * Returns 1 if any hooks are specified in the config or if a hook exists in the
+ * hookdir. Typically, invoke hook_exsts() like:
+ * hook_exists(hookname, configured_hookdir_opt());
+ * Like with run_hooks, if you take a --run-hookdir flag, reflect that
+ * user-specified behavior here instead.
+ */
+int hook_exists(const char *hookname, enum hookdir_opt should_run_hookdir);
+
/*
* Runs all hooks associated to the 'hookname' event in order. Each hook will be
* passed 'env' and 'args'.
Add a helper to easily determine whether any hooks exist for a given hook event. Many callers want to check whether some state could be modified by a hook; that check should include the config-based hooks as well. Optimize by checking the config directly. Since commands which execute hooks might want to take args to replace 'hook.runHookDir', let 'hook_exists()' take a hookdir_opt to override that config. In some cases, external callers today use find_hook() to discover the location of a hook and then run it manually with run-command.h (that is, not with run_hook_le()). Later, those cases will call hook.h:run_hook() directly instead. Once the entire codebase is using hook_exists() instead of find_hook(), find_hook() can be safely rolled into hook_exists() and removed from run-command.h. Signed-off-by: Emily Shaffer <emilyshaffer@google.com> --- hook.c | 19 +++++++++++++++++++ hook.h | 10 ++++++++++ 2 files changed, 29 insertions(+)