Message ID | 20200909004939.1942347-8-emilyshaffer@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | propose config-based hooks | expand |
Emily Shaffer <emilyshaffer@google.com> writes: > Add a helper to easily determine whether any hooks exist for a given > hook event. > > Signed-off-by: Emily Shaffer <emilyshaffer@google.com> > --- > hook.c | 9 +++++++++ > hook.h | 1 + > 2 files changed, 10 insertions(+) Should we consider the last three patches still work-in-progress technology demonstration, or are these meant as a proposal for a new API element as-is? It is perfectly fine if it is the former. I just want to make sure we share a common understanding on the direction in which we want these patches to take us. Here is my take: - For now, a hook/event that is aware of the config-based hook system is supposed to use hook_exists(), while the traditional ones still use find_hook(). We expect more and more will be converted to the former over time. - Invoking hook scripts under the new world order is done by including hook.h and calling run_hooks(), not by driving the run-command API yourself (I count run_hook_ve() as part of the latter) like the traditional code did. We expect more and more will be converted to the former over time. - From the point of view of the end users who have been happily using scripts in $GIT_DIR/hooks, everything will stay the same. hook_exists() will find them (by calling find_hook() as a fallback) and run_hooks() will run them (by relying on hook_list() to include them). I am guessing that the above gives us a high-level description. The new interface needs to be described in hook.h once the series graduates from the technology demonstration state, in order to help others who want to help updating the callsites of traditional hooks to the new API. And the above three-bullet point list is my attempt to figure out what kind of things need to be documented to help them. I am not seeing anything in run_hooks() that consumes input from us over pipe, by the way, without which we cannot do things like the "pre-receive" hooks under the new world order. Are they planned to come in the future, after these "we feed anything they need from the command line and from the enviornment" hooks are dealt with in this first pass? Thanks. > diff --git a/hook.c b/hook.c > index 0dab981681..7c7b922369 100644 > --- a/hook.c > +++ b/hook.c > @@ -111,6 +111,15 @@ struct list_head* hook_list(const struct strbuf* hookname) > return &hook_head; > } > > +int hook_exists(const char *hookname) > +{ > + const char *value = NULL; > + struct strbuf hook_key = STRBUF_INIT; > + strbuf_addf(&hook_key, "hook.%s.command", hookname); > + > + return (!git_config_get_value(hook_key.buf, &value)) || !!find_hook(hookname); > +} > + > int run_hooks(const char *const *env, const struct strbuf *hookname, > const struct strvec *args) > { > diff --git a/hook.h b/hook.h > index d020788a6b..d94511b609 100644 > --- a/hook.h > +++ b/hook.h > @@ -11,6 +11,7 @@ struct hook > }; > > struct list_head* hook_list(const struct strbuf *hookname); > +int hook_exists(const char *hookname); > int run_hooks(const char *const *env, const struct strbuf *hookname, > const struct strvec *args);
On Wed, Sep 09, 2020 at 01:32:12PM -0700, Junio C Hamano wrote: > > Emily Shaffer <emilyshaffer@google.com> writes: > > > Add a helper to easily determine whether any hooks exist for a given > > hook event. > > > > Signed-off-by: Emily Shaffer <emilyshaffer@google.com> > > --- > > hook.c | 9 +++++++++ > > hook.h | 1 + > > 2 files changed, 10 insertions(+) > > Should we consider the last three patches still work-in-progress > technology demonstration, or are these meant as a proposal for a new > API element as-is? The former. I'm irritated with myself for spending a long time fidgeting with the wording on this reroll and still forgetting to mark the last three "RFC" as I had planned to do. > It is perfectly fine if it is the former. I just want to make sure > we share a common understanding on the direction in which we want > these patches to take us. Here is my take: > > - For now, a hook/event that is aware of the config-based hook > system is supposed to use hook_exists(), while the traditional > ones still use find_hook(). We expect more and more will be > converted to the former over time. > > - Invoking hook scripts under the new world order is done by > including hook.h and calling run_hooks(), not by driving the > run-command API yourself (I count run_hook_ve() as part of the > latter) like the traditional code did. We expect more and more > will be converted to the former over time. > > - From the point of view of the end users who have been happily > using scripts in $GIT_DIR/hooks, everything will stay the same. > hook_exists() will find them (by calling find_hook() as a > fallback) and run_hooks() will run them (by relying on > hook_list() to include them). > > I am guessing that the above gives us a high-level description. Yes. I am also working on a patch locally to include a config - optionally users could shut off the $GIT_DIR/hooks, but I don't see us making that the default behavior any time soon (or ever). > > The new interface needs to be described in hook.h once the series > graduates from the technology demonstration state, in order to help > others who want to help updating the callsites of traditional hooks > to the new API. And the above three-bullet point list is my attempt > to figure out what kind of things need to be documented to help > them. Sure. Agreed. Thanks for pointing it out - I had planned on updating the `git help hook` manpage but adding API comments in hook.h had slipped my mind, so the reminder is useful. > > I am not seeing anything in run_hooks() that consumes input from us > over pipe, by the way, without which we cannot do things like the > "pre-receive" hooks under the new world order. Are they planned to > come in the future, after these "we feed anything they need from the > command line and from the enviornment" hooks are dealt with in this > first pass? I included this conversion to demonstrate the tech and give people something to look at (and shout to stop if so needed). I do plan to include hooks which need piped input; in fact, I'm hoping to target one such for the next conversion I do. The todo list looks like so: 1. semantics for checking hook.runHookDir config 2. convert all the hooks which take input in interesting ways (or, just all the hooks) 3. add user friendliness via 'git hook add', 'git hook edit', etc The config semantics are in progress and I'm hoping to send this week. As for submission plan, I don't mind including new architecture (if unused) except for the code bloat; I'd rather push all the "conversions" simultaneously, so users don't have to wonder "is this hook a new and supported one, or not?". I don't mind adding the niceties ('git hook add' etc) later as the config is a little annoying for a human to write themselves, but not impossible. - Emily
> +int hook_exists(const char *hookname) > +{ > + const char *value = NULL; > + struct strbuf hook_key = STRBUF_INIT; > + strbuf_addf(&hook_key, "hook.%s.command", hookname); > + > + return (!git_config_get_value(hook_key.buf, &value)) || !!find_hook(hookname); > +} I was surprised that this didn't share code with hook_list. Upon further thought, hook_list might be expensive if hooks are present, but if we can cache results, I think it's worth it. A caller that calls this function usually will run hooks if they are present, so it's not wasted work to construct the hook list.
Emily Shaffer wrote: > Subject: hook: replace run-command.h:find_hook tiny nit: This doesn't remove find_hook, so this may want to be described as "add replacement for" instead of "replace". [...] > --- a/hook.c > +++ b/hook.c > @@ -111,6 +111,15 @@ struct list_head* hook_list(const struct strbuf* hookname) > return &hook_head; > } > > +int hook_exists(const char *hookname) > +{ > + const char *value = NULL; > + struct strbuf hook_key = STRBUF_INIT; > + strbuf_addf(&hook_key, "hook.%s.command", hookname); > + > + return (!git_config_get_value(hook_key.buf, &value)) || !!find_hook(hookname); > +} This feels a bit fragile, since it can go out of sync with run_hooks. I think I'd prefer if they shared code and this function either returned a parsed structure that could be used later to run hooks or cached the result keyed by hookname. Thanks, Jonathan
diff --git a/hook.c b/hook.c index 0dab981681..7c7b922369 100644 --- a/hook.c +++ b/hook.c @@ -111,6 +111,15 @@ struct list_head* hook_list(const struct strbuf* hookname) return &hook_head; } +int hook_exists(const char *hookname) +{ + const char *value = NULL; + struct strbuf hook_key = STRBUF_INIT; + strbuf_addf(&hook_key, "hook.%s.command", hookname); + + return (!git_config_get_value(hook_key.buf, &value)) || !!find_hook(hookname); +} + int run_hooks(const char *const *env, const struct strbuf *hookname, const struct strvec *args) { diff --git a/hook.h b/hook.h index d020788a6b..d94511b609 100644 --- a/hook.h +++ b/hook.h @@ -11,6 +11,7 @@ struct hook }; struct list_head* hook_list(const struct strbuf *hookname); +int hook_exists(const char *hookname); int run_hooks(const char *const *env, const struct strbuf *hookname, const struct strvec *args);
Add a helper to easily determine whether any hooks exist for a given hook event. Signed-off-by: Emily Shaffer <emilyshaffer@google.com> --- hook.c | 9 +++++++++ hook.h | 1 + 2 files changed, 10 insertions(+)