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

[PATCH v4 00/36] Run hooks via "git run hook" & hook library

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Aug 3, 2021, 19:38 UTC
Message-ID
<cover-v4-00.36-00000000000-20210803T191505Z-avarab@gmail.com>
In-Reply-To
<cover-00.27-0000000000-20210617T101216Z-avarab@gmail.com>
This is a v4 re-roll of the "Base for "config-based-hooks" topic.

It's grown from 27 to 36 patches mainly because I re-folded the two topics it depended on into it, i.e.:

    https://lore.kernel.org/git/cover-0.3-0000000000-20210629T190137Z-avarab@gmail.com/
    https://lore.kernel.org/git/cover-0.3-0000000000-20210629T183325Z-avarab@gmail.com/

I think those have long since reached a level of stability suitable for being merged down, but since Junio didn't pick them up separately[1][2] there wasn't much point in keeping them split-up.

This re-roll mostly addresses Emily's comments on the v3: https://lore.kernel.org/git/YQHAasrmcbdiCDQF@google.com/

I.e.:
 * I did not change the part where I die on hooks that aren't known to
   git itself. I think it makes sense to keep this topic purely for
   bug-for-bug compatibility with existing behavior, and to flip the
   RUN_SETUP_GENTLY flag in her follow-up feature topic.
 * The (ab)use of the run_processes_parallel() API should be gone. I
   just misunderstood how it worked.
 * The v3 would segfault on a plain "git hook run". I've changed
   builtin/hook.c to use the same pattern for subcommands as
   builtin/commit-graph.c et al. This also makes the usage output more
   consistent.
 * The stub "jobs" member of the struct is now gone, and it's
   hardcoded to 1. Emily's feature topic can add it back (per her
   suggestion).
Other updates:
 * In the base topic the s/Signed-off-by/Reviewed-by/g from René
   change that Junio applied locally has been folded in.
 * Almost all the callers were just "one-shot" callers, I introduced a
   new run_hooks_oneshot() function for those, which gets rid of the
   verbosity around memory management, see e.g. the "builtin/gc.c" in
   the range-diff below. That run_hooks_oneshot() can also take a NULL
   set of options.
 * We'd leak memory from "my_hook.feed_pipe_cb_data" in hook.c, we now
   free() it.
 * Some s/STRING_LIST_INIT_DUP/STRING_LIST_INIT_NODUP &
   strbuf_detach()/ changes in transport.c and reference-transaction
   to avoid needless verbosity around memory management.
 * A new 'hook.c users: use "hook_exists()" insted of "find_hook()"'
   patch in what was previously one of the base topics, makes
   subsequent changes smaller.
1. https://lore.kernel.org/git/87sg00qfbp.fsf@evledraar.gmail.com/
2. https://lore.kernel.org/git/87a6mevkrx.fsf@evledraar.gmail.com/
Emily Shaffer (26):
  hook.c: add a hook_exists() wrapper and use it in bugreport.c
  hook: add 'run' subcommand
  gc: use hook library for pre-auto-gc hook
  rebase: convert pre-rebase to use hook.h
  am: convert applypatch to use hook.h
  hooks: convert 'post-checkout' hook to hook library
  merge: convert post-merge to use hook.h
  send-email: use 'git hook run' for 'sendemail-validate'
  git-p4: use 'git hook' to run hooks
  commit: convert {pre-commit,prepare-commit-msg} hook to hook.h
  read-cache: convert post-index-change to use hook.h
  receive-pack: convert push-to-checkout hook to hook.h
  run-command: remove old run_hook_{le,ve}() hook API
  run-command: allow stdin for run_processes_parallel
  hook: support passing stdin to hooks
  am: convert 'post-rewrite' hook to hook.h
  run-command: add stdin callback for parallelization
  hook: provide stdin by string_list or callback
  hook: convert 'post-rewrite' hook in sequencer.c to hook.h
  transport: convert pre-push hook to hook.h
  reference-transaction: use hook.h to run hooks
  run-command: allow capturing of collated output
  hooks: allow callers to capture output
  receive-pack: convert 'update' hook to hook.h
  post-update: use hook.h library
  receive-pack: convert receive hooks to hook.h
Ævar Arnfjörð Bjarmason (10):
  Makefile: mark "check" target as .PHONY
  Makefile: stop hardcoding {command,config}-list.h
  Makefile: remove an out-of-date comment
  hook.[ch]: move find_hook() to this new library
  hook.c users: use "hook_exists()" insted of "find_hook()"
  hook-list.h: add a generated list of hooks, like config-list.h
  git hook run: add an --ignore-missing flag
  hook tests: test for exact "pre-push" hook input
  hook tests: use a modern style for "pre-push" tests
  hooks: fix a TOCTOU in "did we run a hook?" heuristic
 .gitignore                          |   2 +
 Documentation/git-hook.txt          |  51 +++++
 Documentation/githooks.txt          |   4 +
 Makefile                            |  26 ++-
 builtin.h                           |   1 +
 builtin/am.c                        |  29 +--
 builtin/bugreport.c                 |  46 +----
 builtin/checkout.c                  |  14 +-
 builtin/clone.c                     |   6 +-
 builtin/commit.c                    |  19 +-
 builtin/fetch.c                     |   1 +
 builtin/gc.c                        |   3 +-
 builtin/hook.c                      |  92 +++++++++
 builtin/merge.c                     |  21 +-
 builtin/rebase.c                    |   6 +-
 builtin/receive-pack.c              | 285 +++++++++++++---------------
 builtin/submodule--helper.c         |   2 +-
 builtin/worktree.c                  |  29 ++-
 command-list.txt                    |   1 +
 commit.c                            |  16 +-
 commit.h                            |   3 +-
 compat/vcbuild/README               |   2 +-
 config.mak.uname                    |   6 +-
 contrib/buildsystems/CMakeLists.txt |   7 +
 generate-hooklist.sh                |  18 ++
 git-p4.py                           |  72 +------
 git-send-email.perl                 |  20 +-
 git.c                               |   1 +
 hook.c                              | 246 ++++++++++++++++++++++++
 hook.h                              | 126 ++++++++++++
 read-cache.c                        |  11 +-
 refs.c                              |  41 ++--
 reset.c                             |  14 +-
 run-command.c                       | 157 +++++++--------
 run-command.h                       |  55 +++---
 sequencer.c                         |  86 ++++-----
 submodule.c                         |   1 +
 t/helper/test-run-command.c         |  46 ++++-
 t/t0061-run-command.sh              |  37 ++++
 t/t1800-hook.sh                     | 156 +++++++++++++++
 t/t5571-pre-push-hook.sh            |  94 +++++----
 t/t9001-send-email.sh               |   4 +-
 transport.c                         |  57 ++----
 43 files changed, 1303 insertions(+), 611 deletions(-)
 create mode 100644 Documentation/git-hook.txt
 create mode 100644 builtin/hook.c
 create mode 100755 generate-hooklist.sh
 create mode 100644 hook.c
 create mode 100644 hook.h
 create mode 100755 t/t1800-hook.sh
Range-diff against v3:
 1:  27c94247f87 =  1:  81fe1ed90d5 Makefile: mark "check" target as .PHONY
 2:  6e164edb0b0 !  2:  0f749530777 Makefile: stop hardcoding {command,config}-list.h
    @@ Commit message
         added in 029bac01a8 (Makefile: add {program,xdiff,test,git,fuzz}-objs
         & objects targets, 2021-02-23).
     
    +    A subsequent commit will add a new generated hook-list.h. By doing
    +    this refactoring we'll only need to add the new file to the
    +    GENERATED_H variable, not EXCEPT_HDRS, the vcbuild/README etc.
    +
         I have not tested the Windows-specific change in config.mak.uname
         being made here, but we use other variables from the Makefile in the
         same block, and the GENERATED_H is fully defined before we include
         config.mak.uname.
     
         Hardcoding command-list.h there seems to have been a case of
    -    copy/paste programming in dce7d29551 (msvc: support building Git using
    -    MS Visual C++, 2019-06-25). The config-list.h was added later in
    -    709df95b78 (help: move list_config_help to builtin/help, 2020-04-16).
    +    copy/paste programming in 976aaedca0 (msvc: add a Makefile target to
    +    pre-generate the Visual Studio solution, 2019-07-29). The
    +    config-list.h was added later in 709df95b78 (help: move
    +    list_config_help to builtin/help, 2020-04-16).
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
 3:  ddae86802e2 !  3:  644b31fe281 Makefile: remove an out-of-date comment
    @@ Commit message
         The rest of it was also somewhere between inaccurate and outdated,
         since as of b8ba629264 (Makefile: fold MISC_H into LIB_H, 2012-06-20)
         it's not followed by a list of header files, that got moved earlier in
    -    the file into LIB_H in b8ba629264 (Makefile: fold MISC_H into LIB_H,
    -    2012-06-20).
    +    the file into LIB_H in 60d24dd255 (Makefile: fold XDIFF_H and VCSSVN_H
    +    into LIB_H, 2012-07-06).
     
         Let's just remove it entirely, to the extent that we have anything
         useful to say here the comment on the
    @@ Makefile: ifneq ($(dep_files_present),)
     -# Dependencies on automatically generated headers such as command-list.h
     -# should _not_ be included here, since they are necessary even when
     -# building an object for the first time.
    - 
    +-
      $(OBJECTS): $(LIB_H) $(GENERATED_H)
      endif
    + 
 4:  58c37e4f06e =  4:  89c4d44b0c3 hook.[ch]: move find_hook() to this new library
 5:  0cf7e078ef4 =  5:  3514e0c0251 hook.c: add a hook_exists() wrapper and use it in bugreport.c
 -:  ----------- >  6:  d5ef40f77dc hook.c users: use "hook_exists()" insted of "find_hook()"
 6:  f343fc7ae66 !  7:  4cfd72722c1 hook-list.h: add a generated list of hooks, like config-list.h
    @@ Commit message
          - 976aaedca0 (msvc: add a Makefile target to pre-generate the Visual
            Studio solution, 2019-07-29)
     
    +    The LC_ALL=C is needed because at least in my locale the dash ("-") is
    +    ignored for the purposes of sorting, which results in a different
    +    order. I'm not aware of anything in git that has a hard dependency on
    +    the order, but e.g. the bugreport output would end up using whatever
    +    locale was in effect when git was compiled.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
    +    Helped-by: René Scharfe <l.s.r@web.de>
     
      ## .gitignore ##
     @@
    @@ Makefile: command-list.h: $(wildcard Documentation/git*.txt)
      		$(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
      		command-list.txt >$@+ && mv $@+ $@
      
    -+hook-list.h: generate-hooklist.sh
    -+hook-list.h: Documentation/githooks.txt
    ++hook-list.h: generate-hooklist.sh Documentation/githooks.txt
     +	$(QUIET_GEN)$(SHELL_PATH) ./generate-hooklist.sh \
     +		>$@+ && mv $@+ $@
     +
    @@ contrib/buildsystems/CMakeLists.txt: if(NOT EXISTS ${CMAKE_BINARY_DIR}/config-li
      ## generate-hooklist.sh (new) ##
     @@
     +#!/bin/sh
    ++#
    ++# Usage: ./generate-hooklist.sh >hook-list.h
     +
    -+echo "/* Automatically generated by generate-hooklist.sh */"
    ++cat <<EOF
    ++/* Automatically generated by generate-hooklist.sh */
     +
    -+print_hook_list () {
    -+	cat <<EOF
     +static const char *hook_name_list[] = {
     +EOF
    -+	perl -ne '
    -+		chomp;
    -+		@l[$.] = $_;
    -+		push @h => $l[$. - 1] if /^~~~+$/s;
    -+		END {
    -+			print qq[\t"$_",\n] for sort @h;
    -+		}
    -+	' <Documentation/githooks.txt
    -+	cat <<EOF
    ++
    ++sed -n -e '/^~~~~*$/ {x; s/^.*$/	"&",/; p;}; x' \
    ++	<Documentation/githooks.txt |
    ++	LC_ALL=C sort
    ++
    ++cat <<EOF
     +	NULL,
     +};
     +EOF
    -+}
    -+
    -+echo
    -+print_hook_list
     
      ## hook.c ##
     @@
 7:  cf4b06bfdf8 !  8:  7cb4a4cb69e hook: add 'run' subcommand
    @@ Commit message
         let's start with the bare minimum required to support our simplest
         hooks.
     
    +    In terms of implementation the usage_with_options() and "goto usage"
    +    pattern here mirrors that of
    +    builtin/{commit-graph,multi-pack-index}.c.
    +
         Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ builtin/hook.c (new)
     +#include "strbuf.h"
     +#include "strvec.h"
     +
    ++#define BUILTIN_HOOK_RUN_USAGE \
    ++	N_("git hook run <hook-name> [-- <hook-args>]")
    ++
     +static const char * const builtin_hook_usage[] = {
    -+	N_("git hook <command> [...]"),
    -+	N_("git hook run <hook-name> [-- <hook-args>]"),
    ++	BUILTIN_HOOK_RUN_USAGE,
     +	NULL
     +};
     +
     +static const char * const builtin_hook_run_usage[] = {
    -+	N_("git hook run <hook-name> [-- <hook-args>]"),
    ++	BUILTIN_HOOK_RUN_USAGE,
     +	NULL
     +};
     +
    @@ builtin/hook.c (new)
     +{
     +	int i;
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
    -+	int rc = 0;
     +	const char *hook_name;
     +	const char *hook_path;
    -+
     +	struct option run_options[] = {
     +		OPT_END(),
     +	};
    ++	int ret;
     +
     +	argc = parse_options(argc, argv, prefix, run_options,
     +			     builtin_hook_run_usage,
    -+			     PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH);
    -+
    -+	if (argc > 1) {
    -+		if (strcmp(argv[1], "--") &&
    -+		    strcmp(argv[1], "--end-of-options"))
    -+			/* Having a -- for "run" is mandatory */
    -+			usage_with_options(builtin_hook_usage, run_options);
    -+		/* Add our arguments, start after -- */
    -+		for (i = 2 ; i < argc; i++)
    -+			strvec_push(&opt.args, argv[i]);
    -+	}
    ++			     PARSE_OPT_KEEP_DASHDASH);
     +
    -+	/* Need to take into account core.hooksPath */
    -+	git_config(git_default_config, NULL);
    ++	if (!argc)
    ++		goto usage;
     +
     +	/*
    -+	 * We are not using run_hooks() because we'd like to detect
    -+	 * missing hooks. Let's find it ourselves and call
    -+	 * run_found_hooks() instead.
    ++	 * Having a -- for "run" when providing <hook-args> is
    ++	 * mandatory.
     +	 */
    ++	if (argc > 1 && strcmp(argv[1], "--") &&
    ++	    strcmp(argv[1], "--end-of-options"))
    ++		goto usage;
    ++
    ++	/* Add our arguments, start after -- */
    ++	for (i = 2 ; i < argc; i++)
    ++		strvec_push(&opt.args, argv[i]);
    ++
    ++	/* Need to take into account core.hooksPath */
    ++	git_config(git_default_config, NULL);
    ++
     +	hook_name = argv[0];
     +	hook_path = find_hook(hook_name);
     +	if (!hook_path) {
     +		error("cannot find a hook named %s", hook_name);
     +		return 1;
     +	}
    -+	rc = run_found_hooks(hook_name, hook_path, &opt);
     +
    ++	ret = run_hooks(hook_name, hook_path, &opt);
     +	run_hooks_opt_clear(&opt);
    -+
    -+	return rc;
    ++	return ret;
    ++usage:
    ++	usage_with_options(builtin_hook_run_usage, run_options);
     +}
     +
     +int cmd_hook(int argc, const char **argv, const char *prefix)
    @@ builtin/hook.c (new)
     +	struct option builtin_hook_options[] = {
     +		OPT_END(),
     +	};
    ++
     +	argc = parse_options(argc, argv, NULL, builtin_hook_options,
     +			     builtin_hook_usage, PARSE_OPT_STOP_AT_NON_OPTION);
     +	if (!argc)
    -+		usage_with_options(builtin_hook_usage, builtin_hook_options);
    ++		goto usage;
     +
     +	if (!strcmp(argv[0], "run"))
     +		return run(argc, argv, prefix);
    -+	else
    -+		usage_with_options(builtin_hook_usage, builtin_hook_options);
    ++
    ++usage:
    ++	usage_with_options(builtin_hook_usage, builtin_hook_options);
     +}
     
      ## command-list.txt ##
    @@ hook.c: int hook_exists(const char *name)
     +	struct hook_cb_data *hook_cb = pp_cb;
     +	struct hook *run_me = hook_cb->run_me;
     +
    ++	if (!run_me)
    ++		return 0;
    ++
     +	cp->no_stdin = 1;
     +	cp->env = hook_cb->options->env.v;
     +	cp->stdout_to_stderr = 1;
    @@ hook.c: int hook_exists(const char *name)
     +	/* Provide context for errors if necessary */
     +	*pp_task_cb = run_me;
     +
    ++	/*
    ++	 * This pick_next_hook() will be called again, we're only
    ++	 * running one hook, so indicate that no more work will be
    ++	 * done.
    ++	 */
    ++	hook_cb->run_me = NULL;
    ++
     +	return 1;
     +}
     +
    @@ hook.c: int hook_exists(const char *name)
     +
     +	hook_cb->rc |= result;
     +
    -+	return 1;
    ++	return 0;
     +}
     +
    -+int run_found_hooks(const char *hook_name, const char *hook_path,
    -+		    struct run_hooks_opt *options)
    ++int run_hooks(const char *hook_name, const char *hook_path,
    ++	      struct run_hooks_opt *options)
     +{
     +	struct hook my_hook = {
     +		.hook_path = hook_path,
    @@ hook.c: int hook_exists(const char *name)
     +		.hook_name = hook_name,
     +		.options = options,
     +	};
    -+	cb_data.run_me = &my_hook;
    ++	int jobs = 1;
    ++
    ++	if (!options)
    ++		BUG("a struct run_hooks_opt must be provided to run_hooks");
     +
    -+	if (options->jobs != 1)
    -+		BUG("we do not handle %d or any other != 1 job number yet", options->jobs);
    ++	cb_data.run_me = &my_hook;
     +
    -+	run_processes_parallel_tr2(options->jobs,
    ++	run_processes_parallel_tr2(jobs,
     +				   pick_next_hook,
     +				   notify_start_failure,
     +				   notify_hook_finished,
    @@ hook.c: int hook_exists(const char *name)
     +				   hook_name);
     +
     +	return cb_data.rc;
    -+}
    -+
    -+int run_hooks(const char *hook_name, struct run_hooks_opt *options)
    -+{
    -+	const char *hook_path;
    -+	int ret;
    -+	if (!options)
    -+		BUG("a struct run_hooks_opt must be provided to run_hooks");
    -+
    -+	hook_path = find_hook(hook_name);
    -+
    -+	/*
    -+	 * If you need to act on a missing hook, use run_found_hooks()
    -+	 * instead
    -+	 */
    -+	if (!hook_path)
    -+		return 0;
    -+
    -+	ret = run_found_hooks(hook_name, hook_path, options);
    -+	return ret;
     +}
     
      ## hook.h ##
    @@ hook.h: const char *find_hook(const char *name);
     +
     +	/* Args to be passed to each hook */
     +	struct strvec args;
    -+
    -+	/*
    -+	 * Number of threads to parallelize across, currently a stub,
    -+	 * we use the parallel API for future-proofing, but we always
    -+	 * have one hook of a given name, so this is always an
    -+	 * implicit 1 for now.
    -+	 */
    -+	int jobs;
     +};
     +
     +#define RUN_HOOKS_OPT_INIT { \
    -+	.jobs = 1, \
     +	.env = STRVEC_INIT, \
     +	.args = STRVEC_INIT, \
     +}
     +
    ++/*
    ++ * Callback provided to feed_pipe_fn and consume_sideband_fn.
    ++ */
     +struct hook_cb_data {
     +	/* rc reflects the cumulative failure state */
     +	int rc;
    @@ hook.h: const char *find_hook(const char *name);
     +
     +void run_hooks_opt_clear(struct run_hooks_opt *o);
     +
    -+/*
    -+ * Calls find_hook(hookname) and runs the hooks (if any) with
    -+ * run_found_hooks().
    -+ */
    -+int run_hooks(const char *hook_name, struct run_hooks_opt *options);
    -+
    -+/*
    -+ * Takes an already resolved hook and runs it. Internally the simpler
    -+ * run_hooks() will call this.
    ++/**
    ++ * Takes an already resolved hook found via find_hook() and runs
    ++ * it. Does not call run_hooks_opt_clear() for you.
     + */
    -+int run_found_hooks(const char *hookname, const char *hook_path,
    -+		    struct run_hooks_opt *options);
    ++int run_hooks(const char *hookname, const char *hook_path,
    ++	      struct run_hooks_opt *options);
      #endif
     
      ## t/t1800-hook.sh (new) ##
    @@ t/t1800-hook.sh (new)
     +
     +test_expect_success 'git hook usage' '
     +	test_expect_code 129 git hook &&
    -+	test_expect_code 129 git hook -h &&
    -+	test_expect_code 129 git hook run -h
    ++	test_expect_code 129 git hook run &&
    ++	test_expect_code 129 git hook run -h &&
    ++	test_expect_code 129 git hook run --unknown 2>err &&
    ++	grep "unknown option" err
     +'
     +
     +test_expect_success 'setup GIT_TEST_FAKE_HOOKS=true to permit "test-hook" and "does-not-exist" names"' '
 8:  7209f73f281 !  9:  2b8500aa675 gc: use hook library for pre-auto-gc hook
    @@ Metadata
      ## Commit message ##
         gc: use hook library for pre-auto-gc hook
     
    -    Using the hook.h library instead of the run-command.h library to run
    -    pre-auto-gc means that those hooks can be set up in config files, as
    -    well as in the hookdir. pre-auto-gc is called only from builtin/gc.c.
    +    Move the pre-auto-gc hook away from run-command.h to and over to the
    +    new hook.h library.
    +
    +    To do this introduce a simple run_hooks_oneshot() wrapper, we'll be
    +    using it extensively for these simple cases of wanting to run a single
    +    hook under a given name, and having it free the memory we allocate for
    +    us.
     
         Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
    @@ builtin/gc.c
      
      #define FAILED_RUN "failed to run %s"
      
    -@@ builtin/gc.c: static void add_repack_incremental_option(void)
    - 
    - static int need_to_gc(void)
    - {
    -+	struct run_hooks_opt hook_opt = RUN_HOOKS_OPT_INIT;
    -+
    - 	/*
    - 	 * Setting gc.auto to 0 or negative can disable the
    - 	 * automatic gc.
     @@ builtin/gc.c: static int need_to_gc(void)
      	else
      		return 0;
      
     -	if (run_hook_le(NULL, "pre-auto-gc", NULL))
    -+	if (run_hooks("pre-auto-gc", &hook_opt)) {
    -+		run_hooks_opt_clear(&hook_opt);
    ++	if (run_hooks_oneshot("pre-auto-gc", NULL))
      		return 0;
    -+	}
    -+	run_hooks_opt_clear(&hook_opt);
      	return 1;
      }
    +
    + ## hook.c ##
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
      
    + 	return cb_data.rc;
    + }
    ++
    ++int run_hooks_oneshot(const char *hook_name, struct run_hooks_opt *options)
    ++{
    ++	const char *hook_path;
    ++	int ret;
    ++	struct run_hooks_opt hook_opt_scratch = RUN_HOOKS_OPT_INIT;
    ++
    ++	if (!options)
    ++		options = &hook_opt_scratch;
    ++
    ++	hook_path = find_hook(hook_name);
    ++	if (!hook_path) {
    ++		ret = 0;
    ++		goto cleanup;
    ++	}
    ++
    ++	ret = run_hooks(hook_name, hook_path, options);
    ++cleanup:
    ++	run_hooks_opt_clear(options);
    ++	return ret;
    ++}
    +
    + ## hook.h ##
    +@@ hook.h: void run_hooks_opt_clear(struct run_hooks_opt *o);
    + /**
    +  * Takes an already resolved hook found via find_hook() and runs
    +  * it. Does not call run_hooks_opt_clear() for you.
    ++ *
    ++ * See run_hooks_oneshot() for the simpler one-shot API.
    +  */
    + int run_hooks(const char *hookname, const char *hook_path,
    + 	      struct run_hooks_opt *options);
    ++
    ++/**
    ++ * Calls find_hook() on your "hook_name" and runs the hooks (if any)
    ++ * with run_hooks().
    ++ *
    ++ * If "options" is provided calls run_hooks_opt_clear() on it for
    ++ * you. If "options" is NULL a scratch one will be provided for you
    ++ * before calling run_hooks().
    ++ */
    ++int run_hooks_oneshot(const char *hook_name, struct run_hooks_opt *options);
    ++
    + #endif
 9:  e9a1e7cf61e ! 10:  3ee55d2c10f rebase: teach pre-rebase to use hook.h
    @@ Metadata
     Author: Emily Shaffer <emilyshaffer@google.com>
     
      ## Commit message ##
    -    rebase: teach pre-rebase to use hook.h
    +    rebase: convert pre-rebase to use hook.h
     
         Move the pre-rebase hook away from run-command.h to and over to the
         new hook.h library.
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      	if (!ok_to_skip_pre_rebase &&
     -	    run_hook_le(NULL, "pre-rebase", options.upstream_arg,
     -			argc ? argv[0] : NULL, NULL))
    -+	    run_hooks("pre-rebase", &hook_opt)) {
    -+		run_hooks_opt_clear(&hook_opt);
    ++	    run_hooks_oneshot("pre-rebase", &hook_opt))
      		die(_("The pre-rebase hook refused to rebase."));
    -+	}
    -+	run_hooks_opt_clear(&hook_opt);
      
      	if (options.flags & REBASE_DIFFSTAT) {
    - 		struct diff_options opts;
10:  1d087269303 ! 11:  050f20d14f0 am: convert applypatch hooks to use config
    @@ Metadata
     Author: Emily Shaffer <emilyshaffer@google.com>
     
      ## Commit message ##
    -    am: convert applypatch hooks to use config
    +    am: convert applypatch to use hook.h
     
         Teach pre-applypatch, post-applypatch, and applypatch-msg to use the
         hook.h library instead of the run-command.h library.
    @@ builtin/am.c: static void am_destroy(const struct am_state *state)
      	assert(state->msg);
     -	ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
     +	strvec_push(&opt.args, am_path(state, "final-commit"));
    -+	ret = run_hooks("applypatch-msg", &opt);
    -+	run_hooks_opt_clear(&opt);
    ++	ret = run_hooks_oneshot("applypatch-msg", &opt);
      
      	if (!ret) {
      		FREE_AND_NULL(state->msg);
     @@ builtin/am.c: static void do_commit(const struct am_state *state)
    - 	struct commit_list *parents = NULL;
      	const char *reflog_msg, *author, *committer = NULL;
      	struct strbuf sb = STRBUF_INIT;
    -+	struct run_hooks_opt hook_opt_pre = RUN_HOOKS_OPT_INIT;
    -+	struct run_hooks_opt hook_opt_post = RUN_HOOKS_OPT_INIT;
      
     -	if (run_hook_le(NULL, "pre-applypatch", NULL))
    -+	if (run_hooks("pre-applypatch", &hook_opt_pre)) {
    -+		run_hooks_opt_clear(&hook_opt_pre);
    ++	if (run_hooks_oneshot("pre-applypatch", NULL))
      		exit(1);
    -+	}
      
      	if (write_cache_as_tree(&tree, 0, NULL))
    - 		die(_("git write-tree failed to write a tree"));
     @@ builtin/am.c: static void do_commit(const struct am_state *state)
      		fclose(fp);
      	}
      
     -	run_hook_le(NULL, "post-applypatch", NULL);
    -+	run_hooks("post-applypatch", &hook_opt_post);
    ++	run_hooks_oneshot("post-applypatch", NULL);
      
    -+	run_hooks_opt_clear(&hook_opt_pre);
    -+	run_hooks_opt_clear(&hook_opt_post);
      	strbuf_release(&sb);
      }
    - 
11:  32eec5dc2f0 ! 12:  ac875d284da hooks: convert 'post-checkout' hook to hook library
    @@ builtin/checkout.c: struct branch_info {
     -			   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),
     -			   changed ? "1" : "0", NULL);
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
    -+	int rc;
     +
      	/* "new_commit" can be NULL when checking out from the index before
      	   a commit exists. */
    @@ builtin/checkout.c: struct branch_info {
     +		     oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),
     +		     changed ? "1" : "0",
     +		     NULL);
    -+	rc = run_hooks("post-checkout", &opt);
    -+	run_hooks_opt_clear(&opt);
    -+	return rc;
    ++	return run_hooks_oneshot("post-checkout", &opt);
      }
      
      static int update_some(const struct object_id *oid, struct strbuf *base,
    @@ builtin/clone.c: static int checkout(int submodule_progress)
     -	err |= run_hook_le(NULL, "post-checkout", oid_to_hex(null_oid()),
     -			   oid_to_hex(&oid), "1", NULL);
     +	strvec_pushl(&hook_opt.args, oid_to_hex(null_oid()), oid_to_hex(&oid), "1", NULL);
    -+	err |= run_hooks("post-checkout", &hook_opt);
    -+	run_hooks_opt_clear(&hook_opt);
    ++	err |= run_hooks_oneshot("post-checkout", &hook_opt);
      
      	if (!err && (option_recurse_submodules.nr > 0)) {
      		struct strvec args = STRVEC_INIT;
    @@ builtin/worktree.c: static int add_worktree(const char *path, const char *refnam
     +		opt.dir = path;
     +		opt.absolute_path = 1;
     +
    -+		ret = run_hooks("post-checkout", &opt);
    -+
    -+		run_hooks_opt_clear(&opt);
    ++		ret = run_hooks_oneshot("post-checkout", &opt);
      	}
      
      	strvec_clear(&child_env);
    @@ hook.c: static int pick_next_hook(struct child_process *cp,
      	/* add command */
      	strvec_push(&cp->args, run_me->hook_path);
     @@ hook.c: static int notify_hook_finished(int result,
    - int run_found_hooks(const char *hook_name, const char *hook_path,
    - 		    struct run_hooks_opt *options)
    + int run_hooks(const char *hook_name, const char *hook_path,
    + 	      struct run_hooks_opt *options)
      {
     +	struct strbuf abs_path = STRBUF_INIT;
      	struct hook my_hook = {
      		.hook_path = hook_path,
      	};
    -@@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
    - 		.hook_name = hook_name,
    - 		.options = options,
    - 	};
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
    + 	if (!options)
    + 		BUG("a struct run_hooks_opt must be provided to run_hooks");
    + 
     +	if (options->absolute_path) {
     +		strbuf_add_absolute_path(&abs_path, hook_path);
     +		my_hook.hook_path = abs_path.buf;
     +	}
      	cb_data.run_me = &my_hook;
      
    - 	if (options->jobs != 1)
    -@@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
    - 				   &cb_data,
    + 	run_processes_parallel_tr2(jobs,
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
      				   "hook",
      				   hook_name);
    + 
     +	if (options->absolute_path)
     +		strbuf_release(&abs_path);
    - 
    ++
      	return cb_data.rc;
      }
    + 
     
      ## hook.h ##
     @@ hook.h: struct run_hooks_opt
    - 	 * implicit 1 for now.
    - 	 */
    - 	int jobs;
    + 
    + 	/* Args to be passed to each hook */
    + 	struct strvec args;
     +
     +	/* Resolve and run the "absolute_path(hook)" instead of
     +	 * "hook". Used for "git worktree" hooks
    @@ hook.h: struct run_hooks_opt
     +
     +	/* Path to initial working directory for subprocess */
     +	const char *dir;
    -+
      };
      
      #define RUN_HOOKS_OPT_INIT { \
     
      ## read-cache.c ##
     @@
    - #include "progress.h"
      #include "sparse-index.h"
      #include "csum-file.h"
    + #include "promisor-remote.h"
     +#include "hook.h"
      
      /* Mask for the name length in ce_flags in the on-disk index */
    @@ reset.c: int reset_head(struct repository *r, struct object_id *oid, const char
     +			     oid_to_hex(oid),
     +			     "1",
     +			     NULL);
    -+		run_hooks("post-checkout", &opt);
    -+		run_hooks_opt_clear(&opt);
    ++		run_hooks_oneshot("post-checkout", &opt);
     +	}
      
      leave_reset_head:
12:  e9fa3f67593 ! 13:  69763bc2255 merge: use config-based hooks for post-merge hook
    @@ Metadata
     Author: Emily Shaffer <emilyshaffer@google.com>
     
      ## Commit message ##
    -    merge: use config-based hooks for post-merge hook
    +    merge: convert post-merge to use hook.h
     
    -    Teach post-merge to use the hook.h library instead of the run-command.h
    -    library to run hooks. This means that post-merge hooks can come from the
    -    config as well as from the hookdir. post-merge is invoked only from
    -    builtin/merge.c.
    +    Teach post-merge to use the hook.h library instead of the
    +    run-command.h library to run hooks.
     
         Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
    @@ builtin/merge.c: static void finish(struct commit *head_commit,
      	/* Run a post-merge hook */
     -	run_hook_le(NULL, "post-merge", squash ? "1" : "0", NULL);
     +	strvec_push(&opt.args, squash ? "1" : "0");
    -+	run_hooks("post-merge", &opt);
    -+	run_hooks_opt_clear(&opt);
    ++	run_hooks_oneshot("post-merge", &opt);
      
      	apply_autostash(git_path_merge_autostash(the_repository));
      	strbuf_release(&reflog_message);
    -@@ builtin/merge.c: static void prepare_to_commit(struct commit_list *remoteheads)
    - 	 * and write it out as a tree.  We must do this before we invoke
    - 	 * the editor and after we invoke run_status above.
    - 	 */
    --	if (find_hook("pre-merge-commit"))
    -+	if (hook_exists("pre-merge-commit"))
    - 		discard_cache();
    - 	read_cache_from(index_file);
    - 	strbuf_addbuf(&msg, &merge_msg);
13:  12347d901bb ! 14:  2ca1ca1b8e4 git hook run: add an --ignore-missing flag
    @@ Documentation/git-hook.txt: optional `--` (or `--end-of-options`, see linkgit:gi
      linkgit:githooks[5]
     
      ## builtin/hook.c ##
    +@@
    + #include "strvec.h"
    + 
    + #define BUILTIN_HOOK_RUN_USAGE \
    +-	N_("git hook run <hook-name> [-- <hook-args>]")
    ++	N_("git hook run [--ignore-missing] <hook-name> [-- <hook-args>]")
    + 
    + static const char * const builtin_hook_usage[] = {
    + 	BUILTIN_HOOK_RUN_USAGE,
     @@ builtin/hook.c: static int run(int argc, const char **argv, const char *prefix)
    + {
      	int i;
      	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
    - 	int rc = 0;
     +	int ignore_missing = 0;
      	const char *hook_name;
      	const char *hook_path;
    - 
      	struct option run_options[] = {
     +		OPT_BOOL(0, "ignore-missing", &ignore_missing,
     +			 N_("exit quietly with a zero exit code if the requested hook cannot be found")),
      		OPT_END(),
      	};
    - 
    + 	int ret;
     @@ builtin/hook.c: static int run(int argc, const char **argv, const char *prefix)
    - 	/*
    - 	 * We are not using run_hooks() because we'd like to detect
    - 	 * missing hooks. Let's find it ourselves and call
    --	 * run_found_hooks() instead.
    -+	 * run_found_hooks() instead...
    - 	 */
    + 	git_config(git_default_config, NULL);
    + 
      	hook_name = argv[0];
    ++	if (ignore_missing)
    ++		return run_hooks_oneshot(hook_name, &opt);
      	hook_path = find_hook(hook_name);
      	if (!hook_path) {
    -+		/* ... act like run_hooks() under --ignore-missing */
    -+		if (ignore_missing)
    -+			return 0;
      		error("cannot find a hook named %s", hook_name);
    - 		return 1;
    - 	}
     
      ## t/t1800-hook.sh ##
     @@ t/t1800-hook.sh: test_expect_success 'git hook run: nonexistent hook' '
      	test_cmp stderr.expect stderr.actual
      '
      
    --test_expect_success 'git hook run: basic' '
     +test_expect_success 'git hook run: nonexistent hook with --ignore-missing' '
     +	git hook run --ignore-missing does-not-exist 2>stderr.actual &&
     +	test_must_be_empty stderr.actual
     +'
     +
    -+test_expect_success 'git hook run -- basic' '
    + test_expect_success 'git hook run: basic' '
      	write_script .git/hooks/test-hook <<-EOF &&
      	echo Test hook
    - 	EOF
14:  71d209b4077 ! 15:  5b66b04bec7 send-email: use 'git hook run' for 'sendemail-validate'
    @@ git-send-email.perl: sub validate_patch {
      	if ($repo) {
     +		my $hook_name = 'sendemail-validate';
      		my $hooks_path = $repo->command_oneline('rev-parse', '--git-path', 'hooks');
    --		my $validate_hook = catfile($hooks_path,
    + 		require File::Spec;
    +-		my $validate_hook = File::Spec->catfile($hooks_path,
     -					    'sendemail-validate');
    -+		my $validate_hook = catfile($hooks_path, $hook_name);
    ++		my $validate_hook = File::Spec->catfile($hooks_path, $hook_name);
      		my $hook_error;
      		if (-x $validate_hook) {
    - 			my $target = abs_path($fn);
    + 			require Cwd;
     @@ git-send-email.perl: sub validate_patch {
      			chdir($repo->wc_path() or $repo->repo_path())
      				or die("chdir: $!");
15:  246a82b55b2 = 16:  14a37a43db2 git-p4: use 'git hook' to run hooks
16:  e3f8482d803 ! 17:  ad5d0e0e7de commit: use hook.h to execute hooks
    @@ Metadata
     Author: Emily Shaffer <emilyshaffer@google.com>
     
      ## Commit message ##
    -    commit: use hook.h to execute hooks
    +    commit: convert {pre-commit,prepare-commit-msg} hook to hook.h
     
    -    Teach run_commit_hook() to call hook.h instead of run-command.h. This
    -    covers 'pre-commit', 'commit-msg', and
    -    'prepare-commit-msg'.
    -
    -    Additionally, ask the hook library - not run-command - whether any
    -    hooks will be run, as it's possible hooks may exist in the config but
    -    not the hookdir.
    -
    -    Because all but 'post-commit' hooks are expected to make some state
    -    change, force all but 'post-commit' hook to run in series. 'post-commit'
    -    "is meant primarily for notification, and cannot affect the outcome of
    -    `git commit`," so it is fine to run in parallel.
    +    Move these hooks hook away from run-command.h to and over to the new
    +    hook.h library.
     
         Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    - ## builtin/commit.c ##
    -@@ builtin/commit.c: static int prepare_to_commit(const char *index_file, const char *prefix,
    - 		return 0;
    - 	}
    - 
    --	if (!no_verify && find_hook("pre-commit")) {
    -+	if (!no_verify && hook_exists("pre-commit")) {
    - 		/*
    - 		 * Re-read the index as pre-commit hook could have updated it,
    - 		 * and write it out as a tree.  We must do this before we invoke
    -
      ## commit.c ##
     @@
      #include "commit-reach.h"
    @@ commit.c: size_t ignore_non_trailer(const char *buf, size_t len)
     -	struct strvec hook_env = STRVEC_INIT;
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
      	va_list args;
    +-	int ret;
     +	const char *arg;
    - 	int ret;
    --
    + 
     -	strvec_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file);
     +	strvec_pushf(&opt.env, "GIT_INDEX_FILE=%s", index_file);
      
    @@ commit.c: size_t ignore_non_trailer(const char *buf, size_t len)
     +		strvec_push(&opt.args, arg);
      	va_end(args);
     -	strvec_clear(&hook_env);
    -+
    -+	ret = run_hooks(name, &opt);
    -+	run_hooks_opt_clear(&opt);
      
    - 	return ret;
    +-	return ret;
    ++	return run_hooks_oneshot(name, &opt);
      }
    -
    - ## sequencer.c ##
    -@@ sequencer.c: static int try_to_commit(struct repository *r,
    - 		}
    - 	}
    - 
    --	if (find_hook("prepare-commit-msg")) {
    -+	if (hook_exists("prepare-commit-msg")) {
    - 		res = run_prepare_commit_msg_hook(r, msg, hook_commit);
    - 		if (res)
    - 			goto out;
17:  6ed61071c5e ! 18:  3d3a33e2674 read-cache: convert post-index-change hook to use config
    @@ Metadata
     Author: Emily Shaffer <emilyshaffer@google.com>
     
      ## Commit message ##
    -    read-cache: convert post-index-change hook to use config
    +    read-cache: convert post-index-change to use hook.h
     
    -    By using hook.h instead of run-command.h to run, post-index-change hooks
    -    can now be specified in the config in addition to the hookdir.
    -    post-index-change is not run anywhere besides in read-cache.c.
    +    Move the post-index-change hook away from run-command.h to and over to
    +    the new hook.h library.
     
         This removes the last direct user of run_hook_ve(), so we can make the
         function static now. It'll be removed entirely soon.
    @@ read-cache.c: static int do_write_locked_index(struct index_state *istate, struc
     +		     istate->updated_workdir ? "1" : "0",
     +		     istate->updated_skipworktree ? "1" : "0",
     +		     NULL);
    -+	run_hooks("post-index-change", &hook_opt);
    -+	run_hooks_opt_clear(&hook_opt);
    ++	run_hooks_oneshot("post-index-change", &hook_opt);
     +
      	istate->updated_workdir = 0;
      	istate->updated_skipworktree = 0;
18:  e4ef3f4548a ! 19:  893f8666301 receive-pack: convert push-to-checkout hook to hook.h
    @@ Metadata
      ## Commit message ##
         receive-pack: convert push-to-checkout hook to hook.h
     
    -    By using hook.h instead of run-command.h to invoke push-to-checkout,
    -    hooks can now be specified in the config as well as in the hookdir.
    -    push-to-checkout is not called anywhere but in builtin/receive-pack.c.
    +    Move the push-to-checkout hook away from run-command.h to and over to
    +    the new hook.h library.
     
         Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
    @@ builtin/receive-pack.c: static const char *push_to_checkout(unsigned char *hash,
     -			hash_to_hex(hash), NULL))
     +	strvec_pushv(&opt.env, env->v);
     +	strvec_push(&opt.args, hash_to_hex(hash));
    -+	if (run_hooks(push_to_checkout_hook, &opt)) {
    -+		run_hooks_opt_clear(&opt);
    ++	if (run_hooks_oneshot(push_to_checkout_hook, &opt))
      		return "push-to-checkout hook declined";
    --	else
    -+	} else {
    -+		run_hooks_opt_clear(&opt);
    - 		return NULL;
    -+	}
    - }
    - 
    - static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree)
    -@@ builtin/receive-pack.c: static const char *update_worktree(unsigned char *sha1, const struct worktree *w
    - 
    - 	strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir));
    - 
    --	if (!find_hook(push_to_checkout_hook))
    -+	if (!hook_exists(push_to_checkout_hook))
    - 		retval = push_to_deploy(sha1, &env, work_tree);
      	else
    - 		retval = push_to_checkout(sha1, &env, work_tree);
    + 		return NULL;
19:  e3dda367ec9 = 20:  070433deba5 run-command: remove old run_hook_{le,ve}() hook API
20:  477d75bf579 = 21:  1028e0c1667 run-command: allow stdin for run_processes_parallel
21:  b7c0ee9719a ! 22:  639e59e9ed0 hook: support passing stdin to hooks
    @@ Documentation/git-hook.txt: what those are.
     
      ## builtin/hook.c ##
     @@
    + #include "strvec.h"
      
    - static const char * const builtin_hook_usage[] = {
    - 	N_("git hook <command> [...]"),
    --	N_("git hook run <hook-name> [-- <hook-args>]"),
    -+	N_("git hook run [<args>] <hook-name> [-- <hook-args>]"),
    - 	NULL
    - };
    - 
    - static const char * const builtin_hook_run_usage[] = {
    - 	N_("git hook run <hook-name> [-- <hook-args>]"),
    -+	N_("git hook run [--to-stdin=<path>] <hook-name> [-- <hook-args>]"),
    - 	NULL
    - };
    + #define BUILTIN_HOOK_RUN_USAGE \
    +-	N_("git hook run [--ignore-missing] <hook-name> [-- <hook-args>]")
    ++	N_("git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]")
      
    + static const char * const builtin_hook_usage[] = {
    + 	BUILTIN_HOOK_RUN_USAGE,
     @@ builtin/hook.c: static int run(int argc, const char **argv, const char *prefix)
      	struct option run_options[] = {
      		OPT_BOOL(0, "ignore-missing", &ignore_missing,
    @@ builtin/hook.c: static int run(int argc, const char **argv, const char *prefix)
     +			   N_("file to read into hooks' stdin")),
      		OPT_END(),
      	};
    - 
    + 	int ret;
     
      ## hook.c ##
     @@ hook.c: static int pick_next_hook(struct child_process *cp,
    - 	struct hook_cb_data *hook_cb = pp_cb;
    - 	struct hook *run_me = hook_cb->run_me;
    + 	if (!run_me)
    + 		return 0;
      
     -	cp->no_stdin = 1;
    -+
     +	/* reopen the file for stdin; run_command closes it. */
     +	if (hook_cb->options->path_to_stdin) {
     +		cp->no_stdin = 0;
    @@ hook.c: static int pick_next_hook(struct child_process *cp,
     
      ## hook.h ##
     @@ hook.h: struct run_hooks_opt
    + 
      	/* Path to initial working directory for subprocess */
      	const char *dir;
    - 
    ++
     +	/* Path to file which should be piped to stdin for each hook */
     +	const char *path_to_stdin;
      };
22:  4035069a98c ! 23:  7d1925cca48 am: convert 'post-rewrite' hook to hook.h
    @@ builtin/am.c: static int run_applypatch_msg_hook(struct am_state *state)
      {
     -	struct child_process cp = CHILD_PROCESS_INIT;
     -	const char *hook = find_hook("post-rewrite");
    -+	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
    - 	int ret;
    - 
    +-	int ret;
    +-
     -	if (!hook)
     -		return 0;
     -
    @@ builtin/am.c: static int run_applypatch_msg_hook(struct am_state *state)
     -	cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
     -	cp.stdout_to_stderr = 1;
     -	cp.trace2_hook_name = "post-rewrite";
    -+	strvec_push(&opt.args, "rebase");
    -+	opt.path_to_stdin = am_path(state, "rewritten");
    ++	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
      
     -	ret = run_command(&cp);
    -+	ret = run_hooks("post-rewrite", &opt);
    ++	strvec_push(&opt.args, "rebase");
    ++	opt.path_to_stdin = am_path(state, "rewritten");
      
     -	close(cp.in);
    -+	run_hooks_opt_clear(&opt);
    - 	return ret;
    +-	return ret;
    ++	return run_hooks_oneshot("post-rewrite", &opt);
      }
      
    + /**
23:  c847a19581a ! 24:  0c24221b522 run-command: add stdin callback for parallelization
    @@ builtin/submodule--helper.c: static int update_submodules(struct submodule_updat
      
     
      ## hook.c ##
    -@@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
    - 	run_processes_parallel_tr2(options->jobs,
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
    + 	run_processes_parallel_tr2(jobs,
      				   pick_next_hook,
      				   notify_start_failure,
     +				   NULL,
    @@ run-command.h: typedef int (*task_finished_fn)(int result,
     +			       feed_pipe_fn, task_finished_fn, void *pp_cb,
      			       const char *tr2_category, const char *tr2_label);
      
    - #endif
    + /**
     
      ## submodule.c ##
     @@ submodule.c: int fetch_populated_submodules(struct repository *r,
24:  da46c859c1c ! 25:  05d1085f7eb hook: provide stdin by string_list or callback
    @@ hook.c: static int pick_next_hook(struct child_process *cp,
      	} else {
      		cp->no_stdin = 1;
      	}
    -@@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
    - 	run_processes_parallel_tr2(options->jobs,
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
    + 	run_processes_parallel_tr2(jobs,
      				   pick_next_hook,
      				   notify_start_failure,
     -				   NULL,
    @@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
      				   notify_hook_finished,
      				   &cb_data,
      				   "hook",
    -@@ hook.c: int run_hooks(const char *hook_name, struct run_hooks_opt *options)
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
    + 
    + 	if (options->absolute_path)
    + 		strbuf_release(&abs_path);
    ++	free(my_hook.feed_pipe_cb_data);
    + 
    + 	return cb_data.rc;
    + }
    +@@ hook.c: int run_hooks_oneshot(const char *hook_name, struct run_hooks_opt *options)
      	if (!options)
    - 		BUG("a struct run_hooks_opt must be provided to run_hooks");
    + 		options = &hook_opt_scratch;
      
     +	if (options->path_to_stdin && options->feed_pipe)
     +		BUG("choose only one method to populate stdin");
     +
      	hook_path = find_hook(hook_name);
    - 
    - 	/*
    + 	if (!hook_path) {
    + 		ret = 0;
     
      ## hook.h ##
     @@ hook.h: int hook_exists(const char *hookname);
    @@ hook.h: struct run_hooks_opt
     + */
     +int pipe_from_string_list(struct strbuf *pipe, void *pp_cb, void *pp_task_cb);
     +
    - struct hook_cb_data {
    - 	/* rc reflects the cumulative failure state */
    - 	int rc;
    + /*
    +  * Callback provided to feed_pipe_fn and consume_sideband_fn.
    +  */
25:  7343be28ef4 ! 26:  4b7175af2e5 hook: convert 'post-rewrite' hook in sequencer.c to hook.h
    @@ sequencer.c: int update_head_with_reflog(const struct commit *old_head,
     +	opt.feed_pipe = pipe_from_string_list;
     +	opt.feed_pipe_ctx = &to_stdin;
     +
    -+	code = run_hooks("post-rewrite", &opt);
    ++	code = run_hooks_oneshot("post-rewrite", &opt);
     +
    -+	run_hooks_opt_clear(&opt);
     +	strbuf_release(&tmp);
     +	string_list_clear(&to_stdin, 0);
     +	return code;
    @@ sequencer.c: static int pick_commits(struct repository *r,
     +
     +			hook_opt.path_to_stdin = rebase_path_rewritten_list();
     +			strvec_push(&hook_opt.args, "rebase");
    -+			run_hooks("post-rewrite", &hook_opt);
    -+			run_hooks_opt_clear(&hook_opt);
    ++			run_hooks_oneshot("post-rewrite", &hook_opt);
      		}
      		apply_autostash(rebase_path_autostash());
      
26:  85bf13a0835 ! 27:  3f24e056410 transport: convert pre-push hook to use config
    @@ Metadata
     Author: Emily Shaffer <emilyshaffer@google.com>
     
      ## Commit message ##
    -    transport: convert pre-push hook to use config
    +    transport: convert pre-push hook to hook.h
     
    -    By using the hook.h:run_hooks API, pre-push hooks can be specified in
    -    the config as well as in the hookdir.
    +    Move the pre-push hook away from run-command.h to and over to the new
    +    hook.h library.
     
         Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
    @@ transport.c: static void die_with_unpushed_submodules(struct string_list *needs_
     -	int ret = 0, x;
     +	int ret = 0;
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
    -+	struct strbuf tmp = STRBUF_INIT;
      	struct ref *r;
     -	struct child_process proc = CHILD_PROCESS_INIT;
     -	struct strbuf buf;
    @@ transport.c: static void die_with_unpushed_submodules(struct string_list *needs_
     -		finish_command(&proc);
     -		return -1;
     -	}
    --
    --	sigchain_push(SIGPIPE, SIG_IGN);
    -+	struct string_list to_stdin = STRING_LIST_INIT_DUP;
    ++	struct string_list to_stdin = STRING_LIST_INIT_NODUP;
      
    +-	sigchain_push(SIGPIPE, SIG_IGN);
    +-
     -	strbuf_init(&buf, 256);
     +	strvec_push(&opt.args, transport->remote->name);
     +	strvec_push(&opt.args, transport->url);
      
      	for (r = remote_refs; r; r = r->next) {
    ++		struct strbuf buf = STRBUF_INIT;
    ++
      		if (!r->peer_ref) continue;
    -@@ transport.c: static int run_pre_push_hook(struct transport *transport,
    + 		if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
    + 		if (r->status == REF_STATUS_REJECT_STALE) continue;
      		if (r->status == REF_STATUS_REJECT_REMOTE_UPDATED) continue;
      		if (r->status == REF_STATUS_UPTODATE) continue;
      
     -		strbuf_reset(&buf);
     -		strbuf_addf( &buf, "%s %s %s %s\n",
    -+		strbuf_reset(&tmp);
    -+		strbuf_addf(&tmp, "%s %s %s %s",
    ++		strbuf_addf(&buf, "%s %s %s %s",
      			 r->peer_ref->name, oid_to_hex(&r->new_oid),
      			 r->name, oid_to_hex(&r->old_oid));
     -
    @@ transport.c: static int run_pre_push_hook(struct transport *transport,
     -				ret = -1;
     -			break;
     -		}
    -+		string_list_append(&to_stdin, tmp.buf);
    ++		string_list_append(&to_stdin, strbuf_detach(&buf, NULL));
      	}
      
     -	strbuf_release(&buf);
    @@ transport.c: static int run_pre_push_hook(struct transport *transport,
     -	x = finish_command(&proc);
     -	if (!ret)
     -		ret = x;
    -+	ret = run_hooks("pre-push", &opt);
    -+	run_hooks_opt_clear(&opt);
    -+	strbuf_release(&tmp);
    ++	ret = run_hooks_oneshot("pre-push", &opt);
    ++	to_stdin.strdup_strings = 1;
     +	string_list_clear(&to_stdin, 0);
      
      	return ret;
 -:  ----------- > 28:  ecf75f33233 hook tests: test for exact "pre-push" hook input
 -:  ----------- > 29:  2c961be94b4 hook tests: use a modern style for "pre-push" tests
27:  331014bad17 ! 30:  1ce456f9d9d reference-transaction: use hook.h to run hooks
    @@ refs.c: int ref_update_reject_duplicates(struct string_list *refnames,
      				const char *state)
      {
     -	struct child_process proc = CHILD_PROCESS_INIT;
    - 	struct strbuf buf = STRBUF_INIT;
    +-	struct strbuf buf = STRBUF_INIT;
     -	const char *hook;
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
    -+	struct string_list to_stdin = STRING_LIST_INIT_DUP;
    ++	struct string_list to_stdin = STRING_LIST_INIT_NODUP;
      	int ret = 0, i;
    -+	char o[GIT_MAX_HEXSZ + 1], n[GIT_MAX_HEXSZ + 1];
      
     -	hook = find_hook("reference-transaction");
     -	if (!hook)
    -+	if (!hook_exists("reference-transaction"))
    - 		return ret;
    - 
    +-		return ret;
    +-
     -	strvec_pushl(&proc.args, hook, state, NULL);
     -	proc.in = -1;
     -	proc.stdout_to_stderr = 1;
    @@ refs.c: int ref_update_reject_duplicates(struct string_list *refnames,
     -
     -	ret = start_command(&proc);
     -	if (ret)
    --		return ret;
    --
    ++	if (!hook_exists("reference-transaction"))
    + 		return ret;
    + 
     -	sigchain_push(SIGPIPE, SIG_IGN);
     +	strvec_push(&opt.args, state);
      
      	for (i = 0; i < transaction->nr; i++) {
      		struct ref_update *update = transaction->updates[i];
    -+		oid_to_hex_r(o, &update->old_oid);
    -+		oid_to_hex_r(n, &update->new_oid);
    ++		struct strbuf buf = STRBUF_INIT;
      
    - 		strbuf_reset(&buf);
    +-		strbuf_reset(&buf);
     -		strbuf_addf(&buf, "%s %s %s\n",
    --			    oid_to_hex(&update->old_oid),
    --			    oid_to_hex(&update->new_oid),
    --			    update->refname);
    ++		strbuf_addf(&buf, "%s %s %s",
    + 			    oid_to_hex(&update->old_oid),
    + 			    oid_to_hex(&update->new_oid),
    + 			    update->refname);
     -
     -		if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
     -			if (errno != EPIPE)
     -				ret = -1;
     -			break;
     -		}
    -+		strbuf_addf(&buf, "%s %s %s", o, n, update->refname);
    -+		string_list_append(&to_stdin, buf.buf);
    ++		string_list_append(&to_stdin, strbuf_detach(&buf, NULL));
      	}
      
     -	close(proc.in);
     -	sigchain_pop(SIGPIPE);
    +-	strbuf_release(&buf);
     +	opt.feed_pipe = pipe_from_string_list;
     +	opt.feed_pipe_ctx = &to_stdin;
     +
    -+	ret = run_hooks("reference-transaction", &opt);
    -+	run_hooks_opt_clear(&opt);
    - 	strbuf_release(&buf);
    ++	ret = run_hooks_oneshot("reference-transaction", &opt);
    ++	to_stdin.strdup_strings = 1;
     +	string_list_clear(&to_stdin, 0);
      
     -	ret |= finish_command(&proc);
28:  f7f56d0a3bb ! 31:  6e5f1f5bd3a run-command: allow capturing of collated output
    @@ builtin/submodule--helper.c: static int update_submodules(struct submodule_updat
      
     
      ## hook.c ##
    -@@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
      				   pick_next_hook,
      				   notify_start_failure,
      				   options->feed_pipe,
    @@ run-command.h: int run_processes_parallel(int n,
     +			       task_finished_fn, void *pp_cb,
      			       const char *tr2_category, const char *tr2_label);
      
    - #endif
    + /**
     
      ## submodule.c ##
     @@ submodule.c: int fetch_populated_submodules(struct repository *r,
29:  7f7fcc06885 ! 32:  0b6e9c6d07a hooks: allow callers to capture output
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## hook.c ##
    -@@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
      				   pick_next_hook,
      				   notify_start_failure,
      				   options->feed_pipe,
    @@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
      				   notify_hook_finished,
      				   &cb_data,
      				   "hook",
    + 				   hook_name);
    + 
    ++
    + 	if (options->absolute_path)
    + 		strbuf_release(&abs_path);
    + 	free(my_hook.feed_pipe_cb_data);
     
      ## hook.h ##
     @@ hook.h: struct run_hooks_opt
30:  e74d49e5593 ! 33:  dcf63634338 receive-pack: convert 'update' hook to hook.h
    @@ builtin/receive-pack.c: static int run_receive_hook(struct command *commands,
     +static int run_update_hook(struct command *cmd)
     +{
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
    -+	int code;
     +
     +	strvec_pushl(&opt.args,
     +		     cmd->ref_name,
    @@ builtin/receive-pack.c: static int run_receive_hook(struct command *commands,
     -	return finish_command(&proc);
     +		opt.consume_sideband = hook_output_to_sideband;
     +
    -+	code = run_hooks("update", &opt);
    -+	run_hooks_opt_clear(&opt);
    -+	return code;
    ++	return run_hooks_oneshot("update", &opt);
      }
      
      static struct command *find_command_by_refname(struct command *list,
31:  0bdc4878ac8 ! 34:  f352a485e59 post-update: use hook.h library
    @@ builtin/receive-pack.c: static const char *update(struct command *cmd, struct sh
     -			copy_to_sideband(proc.err, -1, NULL);
     -		finish_command(&proc);
     -	}
    -+	run_hooks("post-update", &opt);
    -+	run_hooks_opt_clear(&opt);
    ++	run_hooks_oneshot("post-update", &opt);
      }
      
      static void check_aliased_update_internal(struct command *cmd,
32:  db70b59b3bd ! 35:  ceef2f3e804 receive-pack: convert receive hooks to hook.h
    @@ builtin/receive-pack.c: static void hook_output_to_sideband(struct strbuf *outpu
     +{
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
     +	struct receive_hook_feed_context ctx;
    -+	int rc;
     +	struct command *iter = commands;
     +
     +	/* if there are no valid commands, don't invoke the hook at all. */
    @@ builtin/receive-pack.c: static void hook_output_to_sideband(struct strbuf *outpu
     +	if (!iter)
     +		return 0;
     +
    -+	/* pre-receive hooks should run in series as the hook updates refs */
    -+	if (!strcmp(hook_name, "pre-receive"))
    -+		opt.jobs = 1;
    -+
     +	if (push_options) {
     +		int i;
     +		for (i = 0; i < push_options->nr; i++)
    @@ builtin/receive-pack.c: static void hook_output_to_sideband(struct strbuf *outpu
     +	opt.feed_pipe = feed_receive_hook_cb;
     +	opt.feed_pipe_ctx = &ctx;
     +
    -+	rc = run_hooks(hook_name, &opt);
    -+	run_hooks_opt_clear(&opt);
    -+	return rc;
    ++	return run_hooks_oneshot(hook_name, &opt);
     +}
     +
      static int run_update_hook(struct command *cmd)
33:  d86fedf041c ! 36:  b71d7628b40 hooks: fix a TOCTOU in "did we run a hook?" heuristic
    @@ hook.c: static int notify_hook_finished(int result,
     +	if (hook_cb->invoked_hook)
     +		*hook_cb->invoked_hook = 1;
     +
    - 	return 1;
    + 	return 0;
      }
      
    -@@ hook.c: int run_found_hooks(const char *hook_name, const char *hook_path,
    +@@ hook.c: int run_hooks(const char *hook_name, const char *hook_path,
      		.rc = 0,
      		.hook_name = hook_name,
      		.options = options,
     +		.invoked_hook = options->invoked_hook,
      	};
    - 	if (options->absolute_path) {
    - 		strbuf_add_absolute_path(&abs_path, hook_path);
    + 	int jobs = 1;
    + 
     
      ## hook.h ##
     @@ hook.h: struct run_hooks_opt
-- 
2.33.0.rc0.595.ge31e012651d
Previous: Emily ShafferNext: Ævar Arnfjörð Bjarmason
Message 330 of 479 in “config-based hooks”
  1. 00/37 config-based hooksEmily Shaffer, Mar 11, 2021
  2. 04/37 hook: include hookdir hook in listEmily Shaffer, Mar 11, 2021
  3. Ævar Arnfjörð BjarmasonMar 12, 2021
  4. Emily ShafferMar 24, 2021
  5. Junio C HamanoMar 24, 2021
  6. Eric SunshineMar 24, 2021
  7. Emily ShafferMar 24, 2021
  8. 01/37 doc: propose hooks managed by the configEmily Shaffer, Mar 11, 2021
  9. 05/37 hook: teach hook.runHookDirEmily Shaffer, Mar 11, 2021
  10. Ævar Arnfjörð BjarmasonMar 12, 2021
  11. Emily ShafferMar 24, 2021
  12. Ævar Arnfjörð BjarmasonMar 24, 2021
  13. 07/37 parse-options: parse into strvecEmily Shaffer, Mar 11, 2021
  14. Ævar Arnfjörð BjarmasonMar 12, 2021
  15. Emily ShafferMar 24, 2021
  16. 09/37 hook: introduce hook_exists()Emily Shaffer, Mar 11, 2021
  17. 11/37 run-command: allow stdin for run_processes_parallelEmily Shaffer, Mar 11, 2021
  18. 02/37 hook: scaffolding for git-hook subcommandEmily Shaffer, Mar 11, 2021
  19. 08/37 hook: add 'run' subcommandEmily Shaffer, Mar 11, 2021
  20. Ævar Arnfjörð BjarmasonMar 12, 2021
  21. Emily ShafferMar 24, 2021
  22. Junio C HamanoMar 12, 2021
  23. 10/37 hook: support passing stdin to hooksEmily Shaffer, Mar 11, 2021
  24. Ævar Arnfjörð BjarmasonMar 12, 2021
  25. Junio C HamanoMar 12, 2021
  26. 03/37 hook: add list commandEmily Shaffer, Mar 11, 2021
  27. Ævar Arnfjörð BjarmasonMar 12, 2021
  28. Emily ShafferMar 24, 2021
  29. Ævar Arnfjörð BjarmasonMar 25, 2021
  30. 13/37 hook: allow specifying working directory for hooksEmily Shaffer, Mar 11, 2021
  31. 06/37 hook: implement hookcmd.<name>.skipEmily Shaffer, Mar 11, 2021
  32. Ævar Arnfjörð BjarmasonMar 12, 2021
  33. 14/37 run-command: add stdin callback for parallelizationEmily Shaffer, Mar 11, 2021
  34. 18/37 commit: use config-based hooksEmily Shaffer, Mar 11, 2021
  35. Junio C HamanoMar 12, 2021
  36. 12/37 hook: allow parallel hook executionEmily Shaffer, Mar 11, 2021
  37. 15/37 hook: provide stdin by string_list or callbackEmily Shaffer, Mar 11, 2021
  38. 17/37 hooks: allow callers to capture outputEmily Shaffer, Mar 11, 2021
  39. Ævar Arnfjörð BjarmasonMar 12, 2021
  40. Emily ShafferMar 24, 2021
  41. 21/37 gc: use hook library for pre-auto-gc hookEmily Shaffer, Mar 11, 2021
  42. 19/37 am: convert applypatch hooks to use configEmily Shaffer, Mar 11, 2021
  43. Junio C HamanoMar 12, 2021
  44. Emily ShafferMar 29, 2021
  45. 20/37 merge: use config-based hooks for post-merge hookEmily Shaffer, Mar 11, 2021
  46. 16/37 run-command: allow capturing of collated outputEmily Shaffer, Mar 11, 2021
  47. 22/37 rebase: teach pre-rebase to use hook.hEmily Shaffer, Mar 11, 2021
  48. Junio C HamanoMar 12, 2021
  49. 26/37 hooks: convert 'post-checkout' hook to hook libraryEmily Shaffer, Mar 11, 2021
  50. 23/37 read-cache: convert post-index-change hook to use configEmily Shaffer, Mar 11, 2021
  51. Junio C HamanoMar 12, 2021
  52. Emily ShafferMar 29, 2021
  53. 29/37 reference-transaction: look for hooks in configEmily Shaffer, Mar 11, 2021
  54. 28/37 transport: convert pre-push hook to use configEmily Shaffer, Mar 11, 2021
  55. 27/37 hook: convert 'post-rewrite' hook to configEmily Shaffer, Mar 11, 2021
  56. 30/37 receive-pack: convert 'update' hook to hook.hEmily Shaffer, Mar 11, 2021
  57. 24/37 receive-pack: convert push-to-checkout hook to hook.hEmily Shaffer, Mar 11, 2021
  58. Junio C HamanoMar 12, 2021
  59. Emily ShafferMar 29, 2021
  60. Junio C HamanoMar 30, 2021
  61. 25/37 git-p4: use 'git hook' to run hooksEmily Shaffer, Mar 11, 2021
  62. 32/37 post-update: use hook.h libraryEmily Shaffer, Mar 11, 2021
  63. Ævar Arnfjörð BjarmasonMar 12, 2021
  64. Emily ShafferMar 30, 2021
  65. 31/37 proc-receive: acquire hook list from hook.hEmily Shaffer, Mar 11, 2021
  66. 34/37 bugreport: use hook_exists instead of find_hookEmily Shaffer, Mar 11, 2021
  67. 33/37 receive-pack: convert receive hooks to hook.hEmily Shaffer, Mar 11, 2021
  68. 35/37 git-send-email: use 'git hook run' for 'sendemail-validate'Emily Shaffer, Mar 11, 2021
  69. Ævar Arnfjörð BjarmasonMar 12, 2021
  70. Emily ShafferMar 30, 2021
  71. Emily ShafferMar 31, 2021
  72. Junio C HamanoMar 31, 2021
  73. Emily ShafferApr 1, 2021
  74. Junio C HamanoApr 1, 2021
  75. 0/2 git-send-email: refactor duplicate $? checks into a functionÆvar Arnfjörð Bjarmason, Apr 2, 2021
  76. 2/2 git-send-email: refactor duplicate $? checks into a functionÆvar Arnfjörð Bjarmason, Apr 2, 2021
  77. Junio C HamanoApr 2, 2021
  78. 1/2 git-send-email: replace "map" in void context with "for"Ævar Arnfjörð Bjarmason, Apr 2, 2021
  79. Junio C HamanoApr 2, 2021
  80. Emily ShafferApr 2, 2021
  81. 0/4 refactor duplicate $? checks into a function + improve errorsÆvar Arnfjörð Bjarmason, Apr 4, 2021
  82. 1/4 git-send-email: replace "map" in void context with "for"Ævar Arnfjörð Bjarmason, Apr 4, 2021
  83. 3/4 git-send-email: test full --validate outputÆvar Arnfjörð Bjarmason, Apr 4, 2021
  84. 4/4 git-send-email: improve --validate error outputÆvar Arnfjörð Bjarmason, Apr 4, 2021
  85. Junio C HamanoApr 5, 2021
  86. 2/4 git-send-email: refactor duplicate $? checks into a functionÆvar Arnfjörð Bjarmason, Apr 4, 2021
  87. Junio C HamanoApr 5, 2021
  88. Junio C HamanoApr 5, 2021
  89. Junio C HamanoApr 8, 2021
  90. Junio C HamanoApr 8, 2021
  91. Ævar Arnfjörð BjarmasonApr 8, 2021
  92. Junio C HamanoApr 9, 2021
  93. Emily ShafferMay 3, 2021
  94. 0/3 refactor duplicate $? checks into a function + improve errorsÆvar Arnfjörð Bjarmason, Apr 6, 2021
  95. 1/3 git-send-email: test full --validate outputÆvar Arnfjörð Bjarmason, Apr 6, 2021
  96. 2/3 git-send-email: refactor duplicate $? checks into a functionÆvar Arnfjörð Bjarmason, Apr 6, 2021
  97. 3/3 git-send-email: improve --validate error outputÆvar Arnfjörð Bjarmason, Apr 6, 2021
  98. Junio C HamanoApr 6, 2021
  99. Emily ShafferMar 12, 2021
  100. 36/37 run-command: stop thinking about hooksEmily Shaffer, Mar 11, 2021
  101. Ævar Arnfjörð BjarmasonMar 12, 2021
  102. Emily ShafferMar 30, 2021
  103. 37/37 docs: unify githooks and git-hook manpagesEmily Shaffer, Mar 11, 2021
  104. Ævar Arnfjörð BjarmasonMar 12, 2021
  105. Emily ShafferMar 30, 2021
  106. Junio C HamanoApr 7, 2021
  107. Jeff HostetlerApr 8, 2021
  108. Junio C HamanoApr 8, 2021
  109. Emily ShafferApr 8, 2021
  110. Junio C HamanoApr 9, 2021
  111. Junio C HamanoMar 11, 2021
  112. Emily ShafferMar 12, 2021
  113. Ævar Arnfjörð BjarmasonMar 12, 2021
  114. Emily ShafferMar 17, 2021
  115. Emily ShafferMar 17, 2021
  116. Ævar Arnfjörð BjarmasonMar 12, 2021
  117. Ævar Arnfjörð BjarmasonMar 25, 2021
  118. 00/37 propose config-based hooksEmily Shaffer, May 27, 2021
  119. 01/37 doc: propose hooks managed by the configEmily Shaffer, May 27, 2021
  120. 02/37 hook: introduce git-hook subcommandEmily Shaffer, May 27, 2021
  121. Junio C HamanoMay 27, 2021
  122. 03/37 hook: include hookdir hook in listEmily Shaffer, May 27, 2021
  123. 04/37 hook: teach hook.runHookDirEmily Shaffer, May 27, 2021
  124. 05/37 hook: implement hookcmd.<name>.skipEmily Shaffer, May 27, 2021
  125. 06/37 parse-options: parse into strvecEmily Shaffer, May 27, 2021
  126. 08/37 hook: introduce hook_exists()Emily Shaffer, May 27, 2021
  127. 07/37 hook: add 'run' subcommandEmily Shaffer, May 27, 2021
  128. Ævar Arnfjörð BjarmasonJun 3, 2021
  129. Junio C HamanoJun 3, 2021
  130. 09/37 hook: support passing stdin to hooksEmily Shaffer, May 27, 2021
  131. 10/37 run-command: allow stdin for run_processes_parallelEmily Shaffer, May 27, 2021
  132. 11/37 hook: allow parallel hook executionEmily Shaffer, May 27, 2021
  133. 12/37 hook: allow specifying working directory for hooksEmily Shaffer, May 27, 2021
  134. 13/37 run-command: add stdin callback for parallelizationEmily Shaffer, May 27, 2021
  135. 14/37 hook: provide stdin by string_list or callbackEmily Shaffer, May 27, 2021
  136. 15/37 run-command: allow capturing of collated outputEmily Shaffer, May 27, 2021
  137. 16/37 hooks: allow callers to capture outputEmily Shaffer, May 27, 2021
  138. 17/37 commit: use config-based hooksEmily Shaffer, May 27, 2021
  139. 18/37 am: convert applypatch hooks to use configEmily Shaffer, May 27, 2021
  140. 19/37 merge: use config-based hooks for post-merge hookEmily Shaffer, May 27, 2021
  141. 20/37 gc: use hook library for pre-auto-gc hookEmily Shaffer, May 27, 2021
  142. 21/37 rebase: teach pre-rebase to use hook.hEmily Shaffer, May 27, 2021
  143. 22/37 read-cache: convert post-index-change hook to use configEmily Shaffer, May 27, 2021
  144. Ævar Arnfjörð BjarmasonMay 27, 2021
  145. Taylor BlauMay 28, 2021
  146. Felipe ContrerasMay 31, 2021
  147. 23/37 receive-pack: convert push-to-checkout hook to hook.hEmily Shaffer, May 27, 2021
  148. 24/37 git-p4: use 'git hook' to run hooksEmily Shaffer, May 27, 2021
  149. 25/37 hooks: convert 'post-checkout' hook to hook libraryEmily Shaffer, May 27, 2021
  150. 26/37 hook: convert 'post-rewrite' hook to configEmily Shaffer, May 27, 2021
  151. 27/37 transport: convert pre-push hook to use configEmily Shaffer, May 27, 2021
  152. 28/37 reference-transaction: look for hooks in configEmily Shaffer, May 27, 2021
  153. 29/37 receive-pack: convert 'update' hook to hook.hEmily Shaffer, May 27, 2021
  154. 30/37 proc-receive: acquire hook list from hook.hEmily Shaffer, May 27, 2021
  155. 31/37 post-update: use hook.h libraryEmily Shaffer, May 27, 2021
  156. Ævar Arnfjörð BjarmasonJun 14, 2021
  157. 32/37 receive-pack: convert receive hooks to hook.hEmily Shaffer, May 27, 2021
  158. 33/37 bugreport: use hook_exists instead of find_hookEmily Shaffer, May 27, 2021
  159. 34/37 git-send-email: use 'git hook run' for 'sendemail-validate'Emily Shaffer, May 27, 2021
  160. Ævar Arnfjörð BjarmasonMay 27, 2021
  161. 35/37 run-command: stop thinking about hooksEmily Shaffer, May 27, 2021
  162. 36/37 doc: clarify fsmonitor-watchman specificationEmily Shaffer, May 27, 2021
  163. 37/37 docs: link githooks and git-hook manpagesEmily Shaffer, May 27, 2021
  164. Ævar Arnfjörð BjarmasonJun 3, 2021
  165. Ævar Arnfjörð BjarmasonMay 27, 2021
  166. Ævar Arnfjörð BjarmasonMay 27, 2021
  167. Felipe ContrerasMay 27, 2021
  168. 00/31 minimal restart of "config-based-hooks"Ævar Arnfjörð Bjarmason, May 28, 2021
  169. 01/31 hooks tests: don't leave "actual" nonexisting on failureÆvar Arnfjörð Bjarmason, May 28, 2021
  170. 02/31 gc tests: add a test for the "pre-auto-gc" hookÆvar Arnfjörð Bjarmason, May 28, 2021
  171. 03/31 hook: add 'run' subcommandÆvar Arnfjörð Bjarmason, May 28, 2021
  172. 04/31 run-command.h: move find_hook() to hook.hÆvar Arnfjörð Bjarmason, May 28, 2021
  173. 05/31 hook.c: add a hook_exists() wrapper and use it in bugreport.cÆvar Arnfjörð Bjarmason, May 28, 2021
  174. 06/31 gc: use hook library for pre-auto-gc hookÆvar Arnfjörð Bjarmason, May 28, 2021
  175. 08/31 am: convert applypatch hooks to use configÆvar Arnfjörð Bjarmason, May 28, 2021
  176. 07/31 rebase: teach pre-rebase to use hook.hÆvar Arnfjörð Bjarmason, May 28, 2021
  177. 09/31 hooks: convert 'post-checkout' hook to hook libraryÆvar Arnfjörð Bjarmason, May 28, 2021
  178. 10/31 merge: use config-based hooks for post-merge hookÆvar Arnfjörð Bjarmason, May 28, 2021
  179. 11/31 git hook run: add an --ignore-missing flagÆvar Arnfjörð Bjarmason, May 28, 2021
  180. 12/31 send-email: use 'git hook run' for 'sendemail-validate'Ævar Arnfjörð Bjarmason, May 28, 2021
  181. 13/31 git-p4: use 'git hook' to run hooksÆvar Arnfjörð Bjarmason, May 28, 2021
  182. 14/31 commit: use hook.h to execute hooksÆvar Arnfjörð Bjarmason, May 28, 2021
  183. 15/31 read-cache: convert post-index-change hook to use configÆvar Arnfjörð Bjarmason, May 28, 2021
  184. 16/31 receive-pack: convert push-to-checkout hook to hook.hÆvar Arnfjörð Bjarmason, May 28, 2021
  185. Felipe ContrerasJun 2, 2021
  186. 19/31 am: convert 'post-rewrite' hook to hook.hÆvar Arnfjörð Bjarmason, May 28, 2021
  187. 17/31 run-command: allow stdin for run_processes_parallelÆvar Arnfjörð Bjarmason, May 28, 2021
  188. 18/31 hook: support passing stdin to hooksÆvar Arnfjörð Bjarmason, May 28, 2021
  189. 20/31 run-command: add stdin callback for parallelizationÆvar Arnfjörð Bjarmason, May 28, 2021
  190. 21/31 hook: provide stdin by string_list or callbackÆvar Arnfjörð Bjarmason, May 28, 2021
  191. Felipe ContrerasJun 2, 2021
  192. 22/31 hook: convert 'post-rewrite' hook in sequencer.c to hook.hÆvar Arnfjörð Bjarmason, May 28, 2021
  193. 23/31 transport: convert pre-push hook to use configÆvar Arnfjörð Bjarmason, May 28, 2021
  194. 24/31 reference-transaction: use hook.h to run hooksÆvar Arnfjörð Bjarmason, May 28, 2021
  195. 25/31 run-command: allow capturing of collated outputÆvar Arnfjörð Bjarmason, May 28, 2021
  196. 26/31 hooks: allow callers to capture outputÆvar Arnfjörð Bjarmason, May 28, 2021
  197. 28/31 post-update: use hook.h libraryÆvar Arnfjörð Bjarmason, May 28, 2021
  198. 27/31 receive-pack: convert 'update' hook to hook.hÆvar Arnfjörð Bjarmason, May 28, 2021
  199. Felipe ContrerasJun 2, 2021
  200. 29/31 receive-pack: convert receive hooks to hook.hÆvar Arnfjörð Bjarmason, May 28, 2021
  201. 30/31 hooks: fix a TOCTOU in "did we run a hook?" heuristicÆvar Arnfjörð Bjarmason, May 28, 2021
  202. Bagas SanjayaMay 28, 2021
  203. Ævar Arnfjörð BjarmasonMay 28, 2021
  204. 31/31 hook-list.h: add a generated list of hooks, like config-list.hÆvar Arnfjörð Bjarmason, May 28, 2021
  205. Ævar Arnfjörð BjarmasonJun 1, 2021
  206. Emily ShafferJun 1, 2021
  207. Derrick StoleeJun 1, 2021
  208. Felipe ContrerasJun 2, 2021
  209. Ævar Arnfjörð BjarmasonJun 2, 2021
  210. Ævar Arnfjörð BjarmasonJun 2, 2021
  211. Felipe ContrerasJun 2, 2021
  212. Ævar Arnfjörð BjarmasonJun 2, 2021
  213. Ævar Arnfjörð BjarmasonJun 2, 2021
  214. Felipe ContrerasJun 25, 2021
  215. 00/30 Minimal restart of "config-based-hooks"Ævar Arnfjörð Bjarmason, Jun 14, 2021
  216. 03/30 hook.c: add a hook_exists() wrapper and use it in bugreport.cÆvar Arnfjörð Bjarmason, Jun 14, 2021
  217. 01/30 hook: add 'run' subcommandÆvar Arnfjörð Bjarmason, Jun 14, 2021
  218. Emily ShafferJun 14, 2021
  219. Ævar Arnfjörð BjarmasonJun 15, 2021
  220. Emily ShafferJun 18, 2021
  221. Ævar Arnfjörð BjarmasonJun 20, 2021
  222. Junio C HamanoJun 21, 2021
  223. Emily ShafferJun 22, 2021
  224. Junio C HamanoJun 29, 2021
  225. Felipe ContrerasJun 25, 2021
  226. Felipe ContrerasJun 25, 2021
  227. 02/30 run-command.h: move find_hook() to hook.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  228. 12/30 commit: use hook.h to execute hooksÆvar Arnfjörð Bjarmason, Jun 14, 2021
  229. 13/30 read-cache: convert post-index-change hook to use configÆvar Arnfjörð Bjarmason, Jun 14, 2021
  230. Felipe ContrerasJun 25, 2021
  231. 09/30 git hook run: add an --ignore-missing flagÆvar Arnfjörð Bjarmason, Jun 14, 2021
  232. 07/30 hooks: convert 'post-checkout' hook to hook libraryÆvar Arnfjörð Bjarmason, Jun 14, 2021
  233. 06/30 am: convert applypatch hooks to use configÆvar Arnfjörð Bjarmason, Jun 14, 2021
  234. 05/30 rebase: teach pre-rebase to use hook.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  235. 04/30 gc: use hook library for pre-auto-gc hookÆvar Arnfjörð Bjarmason, Jun 14, 2021
  236. Emily ShafferJun 14, 2021
  237. 08/30 merge: use config-based hooks for post-merge hookÆvar Arnfjörð Bjarmason, Jun 14, 2021
  238. 11/30 git-p4: use 'git hook' to run hooksÆvar Arnfjörð Bjarmason, Jun 14, 2021
  239. 16/30 run-command: allow stdin for run_processes_parallelÆvar Arnfjörð Bjarmason, Jun 14, 2021
  240. 17/30 hook: support passing stdin to hooksÆvar Arnfjörð Bjarmason, Jun 14, 2021
  241. 10/30 send-email: use 'git hook run' for 'sendemail-validate'Ævar Arnfjörð Bjarmason, Jun 14, 2021
  242. 26/30 receive-pack: convert 'update' hook to hook.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  243. 15/30 run-command: remove old run_hook_{le,ve}() hook APIÆvar Arnfjörð Bjarmason, Jun 14, 2021
  244. Felipe ContrerasJun 25, 2021
  245. 29/30 hooks: fix a TOCTOU in "did we run a hook?" heuristicÆvar Arnfjörð Bjarmason, Jun 14, 2021
  246. 14/30 receive-pack: convert push-to-checkout hook to hook.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  247. 18/30 am: convert 'post-rewrite' hook to hook.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  248. 23/30 reference-transaction: use hook.h to run hooksÆvar Arnfjörð Bjarmason, Jun 14, 2021
  249. 20/30 hook: provide stdin by string_list or callbackÆvar Arnfjörð Bjarmason, Jun 14, 2021
  250. 22/30 transport: convert pre-push hook to use configÆvar Arnfjörð Bjarmason, Jun 14, 2021
  251. 19/30 run-command: add stdin callback for parallelizationÆvar Arnfjörð Bjarmason, Jun 14, 2021
  252. 21/30 hook: convert 'post-rewrite' hook in sequencer.c to hook.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  253. 30/30 hook-list.h: add a generated list of hooks, like config-list.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  254. Ævar Arnfjörð BjarmasonJun 15, 2021
  255. 27/30 post-update: use hook.h libraryÆvar Arnfjörð Bjarmason, Jun 14, 2021
  256. 25/30 hooks: allow callers to capture outputÆvar Arnfjörð Bjarmason, Jun 14, 2021
  257. 24/30 run-command: allow capturing of collated outputÆvar Arnfjörð Bjarmason, Jun 14, 2021
  258. 28/30 receive-pack: convert receive hooks to hook.hÆvar Arnfjörð Bjarmason, Jun 14, 2021
  259. Emily ShafferJun 14, 2021
  260. Junio C HamanoJun 16, 2021
  261. 00/27 Base for "config-based-hooks"Ævar Arnfjörð Bjarmason, Jun 17, 2021
  262. 01/27 hook: add 'run' subcommandÆvar Arnfjörð Bjarmason, Jun 17, 2021
  263. 04/27 am: convert applypatch hooks to use configÆvar Arnfjörð Bjarmason, Jun 17, 2021
  264. 06/27 merge: use config-based hooks for post-merge hookÆvar Arnfjörð Bjarmason, Jun 17, 2021
  265. 02/27 gc: use hook library for pre-auto-gc hookÆvar Arnfjörð Bjarmason, Jun 17, 2021
  266. Emily ShafferJul 22, 2021
  267. 03/27 rebase: teach pre-rebase to use hook.hÆvar Arnfjörð Bjarmason, Jun 17, 2021
  268. 05/27 hooks: convert 'post-checkout' hook to hook libraryÆvar Arnfjörð Bjarmason, Jun 17, 2021
  269. 09/27 git-p4: use 'git hook' to run hooksÆvar Arnfjörð Bjarmason, Jun 17, 2021
  270. 07/27 git hook run: add an --ignore-missing flagÆvar Arnfjörð Bjarmason, Jun 17, 2021
  271. Emily ShafferJul 2, 2021
  272. 08/27 send-email: use 'git hook run' for 'sendemail-validate'Ævar Arnfjörð Bjarmason, Jun 17, 2021
  273. 10/27 commit: use hook.h to execute hooksÆvar Arnfjörð Bjarmason, Jun 17, 2021
  274. 12/27 receive-pack: convert push-to-checkout hook to hook.hÆvar Arnfjörð Bjarmason, Jun 17, 2021
  275. 13/27 run-command: remove old run_hook_{le,ve}() hook APIÆvar Arnfjörð Bjarmason, Jun 17, 2021
  276. 14/27 run-command: allow stdin for run_processes_parallelÆvar Arnfjörð Bjarmason, Jun 17, 2021
  277. 15/27 hook: support passing stdin to hooksÆvar Arnfjörð Bjarmason, Jun 17, 2021
  278. 11/27 read-cache: convert post-index-change hook to use configÆvar Arnfjörð Bjarmason, Jun 17, 2021
  279. 16/27 am: convert 'post-rewrite' hook to hook.hÆvar Arnfjörð Bjarmason, Jun 17, 2021
  280. 17/27 run-command: add stdin callback for parallelizationÆvar Arnfjörð Bjarmason, Jun 17, 2021
  281. 18/27 hook: provide stdin by string_list or callbackÆvar Arnfjörð Bjarmason, Jun 17, 2021
  282. 19/27 hook: convert 'post-rewrite' hook in sequencer.c to hook.hÆvar Arnfjörð Bjarmason, Jun 17, 2021
  283. 20/27 transport: convert pre-push hook to use configÆvar Arnfjörð Bjarmason, Jun 17, 2021
  284. 22/27 run-command: allow capturing of collated outputÆvar Arnfjörð Bjarmason, Jun 17, 2021
  285. 21/27 reference-transaction: use hook.h to run hooksÆvar Arnfjörð Bjarmason, Jun 17, 2021
  286. 23/27 hooks: allow callers to capture outputÆvar Arnfjörð Bjarmason, Jun 17, 2021
  287. 24/27 receive-pack: convert 'update' hook to hook.hÆvar Arnfjörð Bjarmason, Jun 17, 2021
  288. 25/27 post-update: use hook.h libraryÆvar Arnfjörð Bjarmason, Jun 17, 2021
  289. 26/27 receive-pack: convert receive hooks to hook.hÆvar Arnfjörð Bjarmason, Jun 17, 2021
  290. 27/27 hooks: fix a TOCTOU in "did we run a hook?" heuristicÆvar Arnfjörð Bjarmason, Jun 17, 2021
  291. Emily ShafferJun 18, 2021
  292. 0/9 config-based hooks restartedEmily Shaffer, Jul 15, 2021
  293. 1/9 hook: run a list of hooks insteadEmily Shaffer, Jul 15, 2021
  294. 2/9 hook: allow parallel hook executionEmily Shaffer, Jul 15, 2021
  295. Ævar Arnfjörð BjarmasonJul 16, 2021
  296. Emily ShafferJul 22, 2021
  297. Ævar Arnfjörð BjarmasonJul 23, 2021
  298. 5/9 hook: allow running non-native hooksEmily Shaffer, Jul 15, 2021
  299. 4/9 hook: treat hookdir hook speciallyEmily Shaffer, Jul 15, 2021
  300. Ævar Arnfjörð BjarmasonJul 16, 2021
  301. Emily ShafferJul 22, 2021
  302. Ævar Arnfjörð BjarmasonJul 23, 2021
  303. Felipe ContrerasJul 23, 2021
  304. Eric SunshineJul 23, 2021
  305. Felipe ContrerasJul 23, 2021
  306. 3/9 hook: introduce "git hook list"Emily Shaffer, Jul 15, 2021
  307. Ævar Arnfjörð BjarmasonJul 16, 2021
  308. Emily ShafferJul 22, 2021
  309. Ævar Arnfjörð BjarmasonJul 23, 2021
  310. 6/9 hook: include hooks from the configEmily Shaffer, Jul 15, 2021
  311. Ævar Arnfjörð BjarmasonJul 16, 2021
  312. Emily ShafferJul 22, 2021
  313. Ævar Arnfjörð BjarmasonJul 23, 2021
  314. 8/9 hook: teach 'hookcmd' config to alias hook scriptsEmily Shaffer, Jul 15, 2021
  315. Ævar Arnfjörð BjarmasonJul 16, 2021
  316. Emily ShafferJul 22, 2021
  317. Ævar Arnfjörð BjarmasonJul 23, 2021
  318. Emily ShafferAug 4, 2021
  319. Ævar Arnfjörð BjarmasonAug 5, 2021
  320. Emily ShafferAug 5, 2021
  321. Ævar Arnfjörð BjarmasonAug 5, 2021
  322. Emily ShafferAug 6, 2021
  323. Jonathan TanAug 4, 2021
  324. 7/9 hook: allow out-of-repo 'git hook' invocationsEmily Shaffer, Jul 15, 2021
  325. Ævar Arnfjörð BjarmasonJul 16, 2021
  326. Emily ShafferJul 22, 2021
  327. Ævar Arnfjörð BjarmasonJul 23, 2021
  328. 9/9 hook: implement hookcmd.<name>.skipEmily Shaffer, Jul 15, 2021
  329. Emily ShafferJul 28, 2021
  330. 00/36 Run hooks via "git run hook" & hook libraryÆvar Arnfjörð Bjarmason, Aug 3, 2021
  331. 01/36 Makefile: mark "check" target as .PHONYÆvar Arnfjörð Bjarmason, Aug 3, 2021
  332. Emily ShafferAug 20, 2021
  333. 02/36 Makefile: stop hardcoding {command,config}-list.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  334. Emily ShafferAug 20, 2021
  335. Ævar Arnfjörð BjarmasonAug 24, 2021
  336. 03/36 Makefile: remove an out-of-date commentÆvar Arnfjörð Bjarmason, Aug 3, 2021
  337. Emily ShafferAug 20, 2021
  338. 04/36 hook.[ch]: move find_hook() to this new libraryÆvar Arnfjörð Bjarmason, Aug 3, 2021
  339. Emily ShafferAug 20, 2021
  340. 05/36 hook.c: add a hook_exists() wrapper and use it in bugreport.cÆvar Arnfjörð Bjarmason, Aug 3, 2021
  341. Emily ShafferAug 20, 2021
  342. 07/36 hook-list.h: add a generated list of hooks, like config-list.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  343. 06/36 hook.c users: use "hook_exists()" insted of "find_hook()"Ævar Arnfjörð Bjarmason, Aug 3, 2021
  344. Emily ShafferAug 20, 2021
  345. 08/36 hook: add 'run' subcommandÆvar Arnfjörð Bjarmason, Aug 3, 2021
  346. Ævar Arnfjörð BjarmasonAug 4, 2021
  347. 12/36 hooks: convert 'post-checkout' hook to hook libraryÆvar Arnfjörð Bjarmason, Aug 3, 2021
  348. 09/36 gc: use hook library for pre-auto-gc hookÆvar Arnfjörð Bjarmason, Aug 3, 2021
  349. 10/36 rebase: convert pre-rebase to use hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  350. 11/36 am: convert applypatch to use hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  351. 13/36 merge: convert post-merge to use hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  352. 14/36 git hook run: add an --ignore-missing flagÆvar Arnfjörð Bjarmason, Aug 3, 2021
  353. 15/36 send-email: use 'git hook run' for 'sendemail-validate'Ævar Arnfjörð Bjarmason, Aug 3, 2021
  354. 16/36 git-p4: use 'git hook' to run hooksÆvar Arnfjörð Bjarmason, Aug 3, 2021
  355. 17/36 commit: convert {pre-commit,prepare-commit-msg} hook to hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  356. 18/36 read-cache: convert post-index-change to use hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  357. 19/36 receive-pack: convert push-to-checkout hook to hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  358. 20/36 run-command: remove old run_hook_{le,ve}() hook APIÆvar Arnfjörð Bjarmason, Aug 3, 2021
  359. 21/36 run-command: allow stdin for run_processes_parallelÆvar Arnfjörð Bjarmason, Aug 3, 2021
  360. 22/36 hook: support passing stdin to hooksÆvar Arnfjörð Bjarmason, Aug 3, 2021
  361. 24/36 run-command: add stdin callback for parallelizationÆvar Arnfjörð Bjarmason, Aug 3, 2021
  362. 23/36 am: convert 'post-rewrite' hook to hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  363. 26/36 hook: convert 'post-rewrite' hook in sequencer.c to hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  364. 25/36 hook: provide stdin by string_list or callbackÆvar Arnfjörð Bjarmason, Aug 3, 2021
  365. 27/36 transport: convert pre-push hook to hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  366. 28/36 hook tests: test for exact "pre-push" hook inputÆvar Arnfjörð Bjarmason, Aug 3, 2021
  367. Emily ShafferAug 20, 2021
  368. 29/36 hook tests: use a modern style for "pre-push" testsÆvar Arnfjörð Bjarmason, Aug 3, 2021
  369. Emily ShafferAug 20, 2021
  370. 30/36 reference-transaction: use hook.h to run hooksÆvar Arnfjörð Bjarmason, Aug 3, 2021
  371. 32/36 hooks: allow callers to capture outputÆvar Arnfjörð Bjarmason, Aug 3, 2021
  372. 31/36 run-command: allow capturing of collated outputÆvar Arnfjörð Bjarmason, Aug 3, 2021
  373. 33/36 receive-pack: convert 'update' hook to hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  374. 36/36 hooks: fix a TOCTOU in "did we run a hook?" heuristicÆvar Arnfjörð Bjarmason, Aug 3, 2021
  375. 34/36 post-update: use hook.h libraryÆvar Arnfjörð Bjarmason, Aug 3, 2021
  376. 35/36 receive-pack: convert receive hooks to hook.hÆvar Arnfjörð Bjarmason, Aug 3, 2021
  377. 0/6 config-based hooks restartedEmily Shaffer, Aug 12, 2021
  378. 1/6 hook: run a list of hooks insteadEmily Shaffer, Aug 12, 2021
  379. Junio C HamanoAug 12, 2021
  380. Emily ShafferAug 16, 2021
  381. 2/6 hook: allow parallel hook executionEmily Shaffer, Aug 12, 2021
  382. Junio C HamanoAug 12, 2021
  383. Emily ShafferAug 16, 2021
  384. 3/6 hook: introduce "git hook list"Emily Shaffer, Aug 12, 2021
  385. Junio C HamanoAug 12, 2021
  386. Emily ShafferAug 17, 2021
  387. 4/6 hook: allow running non-native hooksEmily Shaffer, Aug 12, 2021
  388. Junio C HamanoAug 12, 2021
  389. Emily ShafferAug 18, 2021
  390. Emily ShafferAug 18, 2021
  391. Junio C HamanoAug 18, 2021
  392. 5/6 hook: include hooks from the configEmily Shaffer, Aug 12, 2021
  393. Junio C HamanoAug 12, 2021
  394. Emily ShafferAug 19, 2021
  395. 6/6 hook: allow out-of-repo 'git hook' invocationsEmily Shaffer, Aug 12, 2021
  396. Junio C HamanoAug 12, 2021
  397. Junio C HamanoAug 12, 2021
  398. Emily ShafferAug 16, 2021
  399. 0/6 config-based hooks restartedEmily Shaffer, Aug 19, 2021
  400. 1/6 hook: run a list of hooks insteadEmily Shaffer, Aug 19, 2021
  401. Ævar Arnfjörð BjarmasonAug 24, 2021
  402. Emily ShafferAug 26, 2021
  403. Ævar Arnfjörð BjarmasonAug 27, 2021
  404. 2/6 hook: allow parallel hook executionEmily Shaffer, Aug 19, 2021
  405. Ævar Arnfjörð BjarmasonAug 24, 2021
  406. Eric SunshineAug 24, 2021
  407. Emily ShafferAug 26, 2021
  408. 3/6 hook: introduce "git hook list"Emily Shaffer, Aug 19, 2021
  409. Ævar Arnfjörð BjarmasonAug 24, 2021
  410. Emily ShafferAug 26, 2021
  411. Ævar Arnfjörð BjarmasonAug 24, 2021
  412. Emily ShafferAug 26, 2021
  413. 4/6 hook: allow running non-native hooksEmily Shaffer, Aug 19, 2021
  414. Ævar Arnfjörð BjarmasonAug 24, 2021
  415. Emily ShafferAug 26, 2021
  416. Junio C HamanoAug 27, 2021
  417. 5/6 hook: include hooks from the configEmily Shaffer, Aug 19, 2021
  418. Junio C HamanoAug 19, 2021
  419. Emily ShafferAug 19, 2021
  420. Junio C HamanoAug 19, 2021
  421. Ævar Arnfjörð BjarmasonAug 24, 2021
  422. Emily ShafferAug 31, 2021
  423. 6/6 hook: allow out-of-repo 'git hook' invocationsEmily Shaffer, Aug 19, 2021
  424. Ævar Arnfjörð BjarmasonAug 24, 2021
  425. Randall S. BeckerAug 24, 2021
  426. Ævar Arnfjörð BjarmasonAug 24, 2021
  427. Emily ShafferAug 31, 2021
  428. Ævar Arnfjörð BjarmasonAug 24, 2021
  429. Emily ShafferSep 2, 2021
  430. 0/5 config-based hooks restartedÆvar Arnfjörð Bjarmason, Sep 9, 2021
  431. 1/5 hook: run a list of hooks insteadÆvar Arnfjörð Bjarmason, Sep 9, 2021
  432. fixup! hook: run a list of hooks insteadÆvar Arnfjörð Bjarmason, Sep 9, 2021
  433. 2/5 hook: allow parallel hook executionÆvar Arnfjörð Bjarmason, Sep 9, 2021
  434. 3/5 hook: introduce "git hook list"Ævar Arnfjörð Bjarmason, Sep 9, 2021
  435. 5/5 hook: allow out-of-repo 'git hook' invocationsÆvar Arnfjörð Bjarmason, Sep 9, 2021
  436. 4/5 hook: include hooks from the configÆvar Arnfjörð Bjarmason, Sep 9, 2021
  437. Emily ShafferAug 19, 2021
  438. Emily ShafferAug 19, 2021
  439. Ævar Arnfjörð BjarmasonSep 2, 2021
  440. 00/36 Run hooks via "git run hook" & hook libraryÆvar Arnfjörð Bjarmason, Sep 2, 2021
  441. 01/36 Makefile: mark "check" target as .PHONYÆvar Arnfjörð Bjarmason, Sep 2, 2021
  442. 02/36 Makefile: stop hardcoding {command,config}-list.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  443. 03/36 Makefile: remove an out-of-date commentÆvar Arnfjörð Bjarmason, Sep 2, 2021
  444. 04/36 hook.[ch]: move find_hook() from run-command.c to hook.cÆvar Arnfjörð Bjarmason, Sep 2, 2021
  445. 05/36 hook.c: add a hook_exists() wrapper and use it in bugreport.cÆvar Arnfjörð Bjarmason, Sep 2, 2021
  446. 06/36 hook.c users: use "hook_exists()" instead of "find_hook()"Ævar Arnfjörð Bjarmason, Sep 2, 2021
  447. 07/36 hook-list.h: add a generated list of hooks, like config-list.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  448. 08/36 hook: add 'run' subcommandÆvar Arnfjörð Bjarmason, Sep 2, 2021
  449. 09/36 gc: use hook library for pre-auto-gc hookÆvar Arnfjörð Bjarmason, Sep 2, 2021
  450. 10/36 rebase: convert pre-rebase to use hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  451. 11/36 am: convert applypatch to use hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  452. 12/36 hooks: convert 'post-checkout' hook to hook libraryÆvar Arnfjörð Bjarmason, Sep 2, 2021
  453. 13/36 merge: convert post-merge to use hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  454. 14/36 git hook run: add an --ignore-missing flagÆvar Arnfjörð Bjarmason, Sep 2, 2021
  455. 15/36 send-email: use 'git hook run' for 'sendemail-validate'Ævar Arnfjörð Bjarmason, Sep 2, 2021
  456. 16/36 git-p4: use 'git hook' to run hooksÆvar Arnfjörð Bjarmason, Sep 2, 2021
  457. 17/36 commit: convert {pre-commit,prepare-commit-msg} hook to hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  458. 18/36 read-cache: convert post-index-change to use hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  459. 19/36 receive-pack: convert push-to-checkout hook to hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  460. 20/36 run-command: remove old run_hook_{le,ve}() hook APIÆvar Arnfjörð Bjarmason, Sep 2, 2021
  461. 21/36 run-command: allow stdin for run_processes_parallelÆvar Arnfjörð Bjarmason, Sep 2, 2021
  462. 22/36 hook: support passing stdin to hooksÆvar Arnfjörð Bjarmason, Sep 2, 2021
  463. 23/36 am: convert 'post-rewrite' hook to hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  464. 24/36 run-command: add stdin callback for parallelizationÆvar Arnfjörð Bjarmason, Sep 2, 2021
  465. ab/config-based-hooks-N status (was Re: [PATCH v5 24/36] run-command: add stdin callback for parallelization)Ævar Arnfjörð Bjarmason, Oct 6, 2021
  466. Ævar Arnfjörð BjarmasonOct 12, 2021
  467. 25/36 hook: provide stdin by string_list or callbackÆvar Arnfjörð Bjarmason, Sep 2, 2021
  468. 26/36 hook: convert 'post-rewrite' hook in sequencer.c to hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  469. 28/36 hook tests: test for exact "pre-push" hook inputÆvar Arnfjörð Bjarmason, Sep 2, 2021
  470. 27/36 transport: convert pre-push hook to hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  471. 31/36 run-command: allow capturing of collated outputÆvar Arnfjörð Bjarmason, Sep 2, 2021
  472. 32/36 hooks: allow callers to capture outputÆvar Arnfjörð Bjarmason, Sep 2, 2021
  473. 30/36 reference-transaction: use hook.h to run hooksÆvar Arnfjörð Bjarmason, Sep 2, 2021
  474. 29/36 hook tests: use a modern style for "pre-push" testsÆvar Arnfjörð Bjarmason, Sep 2, 2021
  475. 33/36 receive-pack: convert 'update' hook to hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  476. 34/36 post-update: use hook.h libraryÆvar Arnfjörð Bjarmason, Sep 2, 2021
  477. 35/36 receive-pack: convert receive hooks to hook.hÆvar Arnfjörð Bjarmason, Sep 2, 2021
  478. 36/36 hooks: fix a TOCTOU in "did we run a hook?" heuristicÆvar Arnfjörð Bjarmason, Sep 2, 2021
  479. Felipe ContrerasJun 25, 2021

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.