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

Re: [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line

From
Johan Herland <johan@herland.net>
Date
Nov 1, 2013, 00:16 UTC
Message-ID
<CALKQrgcTA6cODDMOwX_hNwsfKU-+X-rhgf0U9SVYqg7bpMAthA@mail.gmail.com>
In-Reply-To
<xmqqa9hp9x2e.fsf@gitster.dls.corp.google.com>
On Thu, Oct 31, 2013 at 6:20 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 9 quoted lines
> Duy Nguyen <pclouds@gmail.com> writes:
>> OK how about, if $GIT_DIR/hooks/something is a directory, then the
>> directory must contain a file named "index", listing all the hooks of
>> type "something". All the hooks in "index" will be executed in the
>> listing order.
>
> Hooks that take arbitrary amount of information from the body read
> their standard input. How are your multiple hooks supposed to
> interact?

As an example, at $dayjob we have a "dispatcher" post-receive hook running on our Git server that captures the current environment, and reads all of stdin. It then iterates through a (configurable) sequence of "subhooks" providing them each with a copy of the data that was passed to it. The "subhooks" may perform duties such as notifying automated build and test systems, triggering updates of mirrors, updating bug trackers, formatting and sending commit emails to mailing lists, etc. Some of them are run synchronously (redirecting their output back to the push client), and some are run asynchronously (redirecting their output to logs). The nice thing is that each of the "subhooks" use the same post-receive hook interface, and is therefore a fully capable stand-alone hook by itself (often implemented in different languages, some of them are not even written by us), and also fully independent of the other "subhooks". It is therefore relatively straightforward to add, remove and mix hooks.

Show 5 quoted lines
> Hooks that prevent you from doing something stupid signal allow/deny
> with their exit code. Do you fail a commit if any of your pre-commit
> hook fails, or is it OK to commit as long as one of them says so?
> If the former, do all the hooks described in the index still run, or
> does the first failure short-cut the remainder?

This clearly needs to be configurable, as there are valid use cases for all the behaviors you mention. That said, I believe that a sane default would be for a single hook failure to cause the entire chain-of-hooks to fail, including short-cutting the remainder of the hooks (at least for the hooks where the exit code determines the outcome of the entire operation). For example, one could envision a sequence of pre-commit hooks being configured something like this:

  [hook "pre-commit.check-whitespace"]
          run = /path/to/whitespace-checker
          on-error = fail-later
  [hook "pre-commit.check-valid-ident"]
          run = /path/to/ident-checker
          on-error = fail-later
  [hook "pre-commit.run-testsuite"]
          run = "/path/to/testsuite --with --arguments"
          on-error = fail-later

The hooks would be run in sequence. The hook.pre-commit.*.run variable specifies how to execute the hook (it is assumed that each of the configured hooks behaves according to the pre-commit hook interface). The hook.pre-commit.*.on-error variable specifies how to handle a non-zero exit code from the hook. Possible values would be "abort" (abort the remaining hooks and return failure immediately), "fail-later" (keep running the remainder of the hooks, but make sure we do return failure in the end), or "ignore" (always pretend the hook returns successfully). The default on-error behavior should IMHO be "abort", but in this case, we don't want to abort on the first failure, as we'd rather report errors from _multiple_ hooks to the user in a single go.

Similarly, a sequence of post-receive hooks could be configure like this:
  [hook "post-receive.trigger-buildbot"]
          run = /path/to/buildbot-trigger-hook
  [hook "post-receive.update-bugtracker"]
          run = /path/to/bugtracker-update-hook
  [hook "post-receive.trigger-mirror-update"]
          run = /path/to/mirror-update-hook
          async = true
          redirect-output = /var/log/mirror-update-hook.log
  [hook "post-receive.send-commit-emails"]
          run = /path/to/commit-emailer
          async = true

Here, the .on-error variable is probably less than useful, since post-receive hooks cannot affect the outcome of the push operation (and having one post-receive hook abort the running of another is probably uncommon). Instead, the .async variable (default: false) is used to indicate which hooks should be run asynchronously (i.e. the client does not have to wait for these hooks to complete).

On a server with many repos, you could even store the above in the global git config, to have the hooks available to all repos, and then use hook.post-receive.*.enabled = true/false to turn hooks on/off for individual repos.

(A nice side-effect of putting this stuff in the config is that it makes is easy to add/remove/manage hooks through our Gitolite setup - which already has support for managing per-repo config options in the Gitolite config.)

This is just some initial thoughts about a possible config format. A more important point though, is that we don't really need to add anything to core Git to support this. All we need to do is to implement a set of "dispatcher" hooks that read the relevant configuration and perform the job accordingly.

Although these "dispatcher" hooks could certainly be developed as a separate project - more or less independent from git.git, I do believe there would be considerable value in distributing them along with Git and easily enabling them (maybe even enabling them by default, as without the config options they would just be no-ops). Otherwise, it would be hard to make them used/accepted widely enough to actually replace current ad hoc solutions.

...Johan
-- 
Johan Herland, <johan@herland.net>
www.herland.net
Previous: Duy NguyenNext: Duy Nguyen
Message 34 of 49 in “commit: Add -f, --fixes <commit> option to add Fixes: line”
  1. commit: Add -f, --fixes <commit> option to add Fixes: lineJosh Triplett, Oct 27, 2013
  2. Michael HaggertyOct 27, 2013
  3. Theodore Ts'oOct 27, 2013
  4. Josh TriplettOct 27, 2013
  5. Michel LespinasseOct 27, 2013
  6. Josh TriplettOct 27, 2013
  7. Thomas RastOct 27, 2013
  8. Josh TriplettOct 27, 2013
  9. Johan HerlandOct 27, 2013
  10. Christian CouderOct 27, 2013
  11. Johan HerlandOct 28, 2013
  12. Thomas RastOct 28, 2013
  13. Jeff KingOct 29, 2013
  14. Johan HerlandOct 30, 2013
  15. Christian CouderOct 29, 2013
  16. Johan HerlandOct 30, 2013
  17. Christian CouderNov 2, 2013
  18. Stefan BellerOct 27, 2013
  19. Thomas RastOct 27, 2013
  20. Stefan BellerOct 27, 2013
  21. Stefan BellerOct 31, 2013
  22. Documentation: add a script to generate a (long/short) options overviewStefan Beller, Oct 31, 2013
  23. Stefan BellerOct 31, 2013
  24. brian m. carlsonOct 31, 2013
  25. Junio C HamanoNov 1, 2013
  26. Michael HaggertyOct 28, 2013
  27. Johan HerlandOct 28, 2013
  28. Jeff KingOct 29, 2013
  29. Matthieu MoyOct 29, 2013
  30. Johan HerlandOct 30, 2013
  31. Duy NguyenOct 31, 2013
  32. Junio C HamanoOct 31, 2013
  33. Duy NguyenOct 31, 2013
  34. Johan HerlandNov 1, 2013
  35. Duy NguyenOct 27, 2013
  36. Josh TriplettOct 27, 2013
  37. Jim HillOct 28, 2013
  38. Junio C HamanoOct 28, 2013
  39. Josh TriplettOct 28, 2013
  40. Michael HaggertyOct 28, 2013
  41. Christoph HellwigOct 28, 2013
  42. Benjamin HerrenschmidtOct 28, 2013
  43. Russell King - ARM LinuxOct 28, 2013
  44. Russell King - ARM LinuxOct 28, 2013
  45. Junio C HamanoOct 28, 2013
  46. Christian CouderOct 29, 2013
  47. Junio C HamanoOct 29, 2013
  48. Tony LuckOct 30, 2013
  49. Junio C HamanoOct 30, 2013

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.