mbox series

[0/6] configuration-based hook management

Message ID 20191210023335.49987-1-emilyshaffer@google.com (mailing list archive)
Headers show
Series configuration-based hook management | expand

Message

Emily Shaffer Dec. 10, 2019, 2:33 a.m. UTC
An implementation of the first piece of the proposal given in
lore.kernel.org/git/20191116011125.GG22855@google.com.

Teaches a new command, 'git hook', which will someday include 'git hook
--add ...', 'git hook --edit ...', and maybe more. For now, just teach
it how to check the config files with 'git hook --list ...'.

The hooks-to-run list is collected in a new library, hook.o, which can
someday reimplement find_hook() or otherwise be invoked to run all hooks
for a given hookname (e.g. "pre-commit").

The change to config.[ch] allows us to display a similar scope name to
the one a user may use to 'git config --add' or later 'git hook --add' a
hook at a certain scope, e.g.:

  $ git hook --list pre-commit
  001	global	~/foo.sh
  $ git hook --add --global pre-commit 005 ~/bar.sh
  Added.
  001	global	~/foo.sh
  005	global	~/bar.sh

There are config examples in many of the commit messages in this chain.

Before I consider "--list" to be done, I also want to add support to
check "hook.runHookDir" and take .git/hooks/* into account. But I wanted
us to spend time chewing on the config format for a while before I got
too far.

It's also very possible (likely, even!) to put this feature behind an
experimental flag, which gives us more room to change the config format
if we want before the feature is "done".

In the discussion thread with brian, I also mentioned a self-paced
deprecation of hooks which live in .git/hooks/, which I'm aware some
users may not want to follow. However, it occurred to me that we may be
able to hide a Git-paced deprecation behind a config macro (since those
are new and shiny) which is opt-in, and handles something like:

  hook.runHookDir = true
  hook.warnHookDir = false

  {some months pass, we are sure config-based hooks are working nicely}

  hook.runHookDir = true
  hook.warnHookDir = true

  {so start yelling at users to move away, and wait some more
  months/years}

  hook.runHookDir = false

  {users who have opted into the hookdir phaseout macro are no longer
  using the hookdir}

As it's opt-in (and easily reversible by changing configs) this might be
a good middle ground for the "deprecate or not" discussion brian and I
had.

Thanks.
 - Emily

Emily Shaffer (6):
  hook: scaffolding for git-hook subcommand
  config: add string mapping for enum config_scope
  hook: add --list mode
  hook: support reordering of hook list
  hook: remove prior hook with '---'
  hook: teach --porcelain mode

 .gitignore                    |  1 +
 Documentation/git-hook.txt    | 53 ++++++++++++++++++++
 Makefile                      |  2 +
 builtin.h                     |  1 +
 builtin/hook.c                | 80 ++++++++++++++++++++++++++++++
 config.c                      | 17 +++++++
 config.h                      |  1 +
 git.c                         |  1 +
 hook.c                        | 93 +++++++++++++++++++++++++++++++++++
 hook.h                        | 14 ++++++
 t/t1360-config-based-hooks.sh | 89 +++++++++++++++++++++++++++++++++
 11 files changed, 352 insertions(+)
 create mode 100644 Documentation/git-hook.txt
 create mode 100644 builtin/hook.c
 create mode 100644 hook.c
 create mode 100644 hook.h
 create mode 100755 t/t1360-config-based-hooks.sh

Comments

Junio C Hamano Dec. 11, 2019, 10:42 p.m. UTC | #1
Emily Shaffer <emilyshaffer@google.com> writes:

> An implementation of the first piece of the proposal given in
> lore.kernel.org/git/20191116011125.GG22855@google.com.
>
> Teaches a new command, 'git hook', which will someday include 'git hook
> --add ...', 'git hook --edit ...', and maybe more. For now, just teach
> it how to check the config files with 'git hook --list ...'.
>
> The hooks-to-run list is collected in a new library, hook.o, which can
> someday reimplement find_hook() or otherwise be invoked to run all hooks
> for a given hookname (e.g. "pre-commit").

Nice to see the endgame vision upfront.

A few things that I'd like to see in the endgame that you did not
mention here are:

 - We may probably not want to have an authoritative "these are the
   hooks Git runs" catalog, so it would be great if the resulting
   system can operate without one.

 - There are at least two kinds of hooks wrt the style of input they
   take.  Some take their input on their command line, which makes
   it quite easy to run multiple of them in a row.  Others take
   their input from their standard input stream, which probably
   means that there needs a cache of the input stream to feed to
   each such hook script (unless Git process itself is generating
   the stream to drive the hook, in which case we could run the
   generation of the stream multiple times) if we want to run
   multiple of them.  

   . With the design goal of *not* having an authoritiative catalog,
     we'd probably need some way to annotate each entry in the [hook]
     configuration which kind of invication the hook program wants.

   . There may be more than the above two styles.  The system should
     be designed to be extensible to accomodate yet more.


Thanks.