From: Emily Shaffer <emilyshaffer@google.com>
To: git@vger.kernel.org
Cc: Emily Shaffer <emilyshaffer@google.com>
Subject: [PATCH 12/17] hook: allow parallel hook execution
Date: Fri, 4 Dec 2020 17:46:02 -0800 [thread overview]
Message-ID: <20201205014607.1464119-13-emilyshaffer@google.com> (raw)
In-Reply-To: <20201205014607.1464119-1-emilyshaffer@google.com>
In many cases, there's no reason not to allow hooks to execute in
parallel. run_processes_parallel() is well-suited - it's a task queue
that runs its housekeeping in series, which means users don't
need to worry about thread safety on their callback data. True
multithreaded execution with the async_* functions isn't necessary here.
Synchronous hook execution can be achieved by only allowing 1 job to run
at a time.
Teach run_hooks() to use that function for simple hooks which don't
require stdin or capture of stderr.
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
---
Notes:
Per AEvar's request - parallel hook execution on day zero.
In most ways run_processes_parallel() worked great for me - but it didn't
have great support for hooks where we pipe to and from. I had to add this
support later in the series.
Since I modified an existing and in-use library I'd appreciate a keen look on
these patches.
- Emily
Documentation/config/hook.txt | 5 ++
Documentation/git-hook.txt | 15 +++-
builtin/hook.c | 6 +-
hook.c | 142 ++++++++++++++++++++++++++--------
hook.h | 28 ++++++-
5 files changed, 158 insertions(+), 38 deletions(-)
diff --git a/Documentation/config/hook.txt b/Documentation/config/hook.txt
index 75312754ae..a423d13781 100644
--- a/Documentation/config/hook.txt
+++ b/Documentation/config/hook.txt
@@ -12,3 +12,8 @@ hook.runHookDir::
Controls how hooks contained in your hookdir are executed. Can be any of
"yes", "warn", "interactive", or "no". Defaults to "yes". See
linkgit:git-hook[1] and linkgit:git-config[1] "core.hooksPath").
+
+hook.jobs::
+ Specifies how many hooks can be run simultaneously during parallelized
+ hook execution. If unspecified, defaults to the number of processors on
+ the current system.
diff --git a/Documentation/git-hook.txt b/Documentation/git-hook.txt
index cce30a80d0..c2678c61b2 100644
--- a/Documentation/git-hook.txt
+++ b/Documentation/git-hook.txt
@@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git hook' list <hook-name>
'git hook' run [(-e|--env)=<var>...] [(-a|--arg)=<arg>...] [--to-stdin=<path>]
- <hook-name>
+ [(-j|--jobs) <n>] <hook-name>
DESCRIPTION
-----------
@@ -66,7 +66,8 @@ in the order they should be run, and print the config scope where the relevant
`hook.<hook-name>.command` was specified, not the `hookcmd` (if applicable).
This output is human-readable and the format is subject to change over time.
-run [(-e|--env)=<var>...] [(-a|--arg)=<arg>...] [--to-stdin=<path>] `<hook-name>`::
+run [(-e|--env)=<var>...] [(-a|--arg)=<arg>...] [--to-stdin=<path>]
+ [(-j|--jobs)<n>]`<hook-name>`::
Runs hooks configured for `<hook-name>`, in the same order displayed by `git
hook list`. Hooks configured this way are run prepended with `sh -c`, so paths
@@ -98,6 +99,16 @@ Specify environment variables to set for every hook that is run.
Specify a file which will be streamed into stdin for every hook that is run.
Each hook will receive the entire file from beginning to EOF.
+-j::
+--jobs::
+ Only valid for `run`.
++
+Specify how many hooks to run simultaneously. If this flag is not specified, use
+the value of the `hook.jobs` config. If the config is not specified, use the
+number of CPUs on the current system. Some hooks may be ineligible for
+parallelization: for example, 'commit-msg' intends hooks modify the commit
+message body and cannot be parallelized.
+
CONFIGURATION
-------------
include::config/hook.txt[]
diff --git a/builtin/hook.c b/builtin/hook.c
index e45831e01d..064a0fea29 100644
--- a/builtin/hook.c
+++ b/builtin/hook.c
@@ -10,7 +10,7 @@
static const char * const builtin_hook_usage[] = {
N_("git hook list <hookname>"),
N_("git hook run [(-e|--env)=<var>...] [(-a|--arg)=<arg>...]"
- "[--to-stdin=<path>] <hookname>"),
+ "[--to-stdin=<path>] [(-j|--jobs) <count>] <hookname>"),
NULL
};
@@ -90,7 +90,7 @@ static int list(int argc, const char **argv, const char *prefix)
static int run(int argc, const char **argv, const char *prefix)
{
struct strbuf hookname = STRBUF_INIT;
- struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
+ struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT_ASYNC;
int rc = 0;
struct option run_options[] = {
@@ -100,6 +100,8 @@ static int run(int argc, const char **argv, const char *prefix)
N_("argument to pass to hook")),
OPT_STRING(0, "to-stdin", &opt.path_to_stdin, N_("path"),
N_("file to read into hooks' stdin")),
+ OPT_INTEGER('j', "jobs", &opt.jobs,
+ N_("run up to <n> hooks simultaneously")),
OPT_END(),
};
diff --git a/hook.c b/hook.c
index c7fdf556fe..edea54f95c 100644
--- a/hook.c
+++ b/hook.c
@@ -136,6 +136,14 @@ enum hookdir_opt configured_hookdir_opt(void)
return hookdir_unknown;
}
+int configured_hook_jobs(void)
+{
+ int n = online_cpus();
+ git_config_get_int("hook.jobs", &n);
+
+ return n;
+}
+
static int should_include_hookdir(const char *path, enum hookdir_opt cfg)
{
struct strbuf prompt = STRBUF_INIT;
@@ -223,6 +231,7 @@ void run_hooks_opt_init(struct run_hooks_opt *o)
strvec_init(&o->env);
strvec_init(&o->args);
o->run_hookdir = configured_hookdir_opt();
+ o->jobs = configured_hook_jobs();
}
int hook_exists(const char *hookname, enum hookdir_opt should_run_hookdir)
@@ -246,11 +255,96 @@ void run_hooks_opt_clear(struct run_hooks_opt *o)
strvec_clear(&o->args);
}
+
+static int pick_next_hook(struct child_process *cp,
+ struct strbuf *out,
+ void *pp_cb,
+ void **pp_task_cb)
+{
+ struct hook_cb_data *hook_cb = pp_cb;
+
+ struct hook *hook = list_entry(hook_cb->run_me, struct hook, list);
+
+ if (hook_cb->head == hook_cb->run_me)
+ return 0;
+
+ cp->env = hook_cb->options->env.v;
+ cp->stdout_to_stderr = 1;
+ cp->trace2_hook_name = hook->command.buf;
+
+ /* reopen the file for stdin; run_command closes it. */
+ if (hook_cb->options->path_to_stdin) {
+ cp->no_stdin = 0;
+ cp->in = xopen(hook_cb->options->path_to_stdin, O_RDONLY);
+ } else {
+ cp->no_stdin = 1;
+ }
+
+ /*
+ * Commands from the config could be oneliners, but we know
+ * for certain that hookdir commands are not.
+ */
+ if (hook->from_hookdir)
+ cp->use_shell = 0;
+ else
+ cp->use_shell = 1;
+
+ /* add command */
+ strvec_push(&cp->args, hook->command.buf);
+
+ /*
+ * add passed-in argv, without expanding - let the user get back
+ * exactly what they put in
+ */
+ strvec_pushv(&cp->args, hook_cb->options->args.v);
+
+ /* Provide context for errors if necessary */
+ *pp_task_cb = hook;
+
+ /* Get the next entry ready */
+ hook_cb->run_me = hook_cb->run_me->next;
+
+ return 1;
+}
+
+static int notify_start_failure(struct strbuf *out,
+ void *pp_cb,
+ void *pp_task_cp)
+{
+ struct hook_cb_data *hook_cb = pp_cb;
+ struct hook *attempted = pp_task_cp;
+
+ /* |= rc in cb */
+ hook_cb->rc |= 1;
+
+ strbuf_addf(out, _("Couldn't start '%s', configured in '%s'\n"),
+ attempted->command.buf,
+ attempted->from_hookdir ? "hookdir"
+ : config_scope_name(attempted->origin));
+
+ /* NEEDSWORK: if halt_on_error is desired, do it here. */
+ return 0;
+}
+
+static int notify_hook_finished(int result,
+ struct strbuf *out,
+ void *pp_cb,
+ void *pp_task_cb)
+{
+ struct hook_cb_data *hook_cb = pp_cb;
+
+ /* |= rc in cb */
+ hook_cb->rc |= result;
+
+ /* NEEDSWORK: if halt_on_error is desired, do it here. */
+ return 0;
+}
+
int run_hooks(const char *hookname, struct run_hooks_opt *options)
{
struct strbuf hookname_str = STRBUF_INIT;
struct list_head *to_run, *pos = NULL, *tmp = NULL;
- int rc = 0;
+ struct hook_cb_data cb_data = { 0, NULL, NULL, options };
if (!options)
BUG("a struct run_hooks_opt must be provided to run_hooks");
@@ -260,41 +354,23 @@ int run_hooks(const char *hookname, struct run_hooks_opt *options)
to_run = hook_list(&hookname_str);
list_for_each_safe(pos, tmp, to_run) {
- struct child_process hook_proc = CHILD_PROCESS_INIT;
struct hook *hook = list_entry(pos, struct hook, list);
- /* reopen the file for stdin; run_command closes it. */
- if (options->path_to_stdin)
- hook_proc.in = xopen(options->path_to_stdin, O_RDONLY);
- else
- hook_proc.no_stdin = 1;
-
- hook_proc.env = options->env.v;
- hook_proc.stdout_to_stderr = 1;
- hook_proc.trace2_hook_name = hook->command.buf;
- hook_proc.use_shell = 1;
-
- if (hook->from_hookdir) {
- if (!should_include_hookdir(hook->command.buf, options->run_hookdir))
- continue;
- /*
- * Commands from the config could be oneliners, but we know
- * for certain that hookdir commands are not.
- */
- hook_proc.use_shell = 0;
- }
-
- /* add command */
- strvec_push(&hook_proc.args, hook->command.buf);
+ if (hook->from_hookdir &&
+ !should_include_hookdir(hook->command.buf, options->run_hookdir))
+ list_del(pos);
+ }
- /*
- * add passed-in argv, without expanding - let the user get back
- * exactly what they put in
- */
- strvec_pushv(&hook_proc.args, options->args.v);
+ cb_data.head = to_run;
+ cb_data.run_me = to_run->next;
- rc |= run_command(&hook_proc);
- }
+ run_processes_parallel_tr2(options->jobs,
+ pick_next_hook,
+ notify_start_failure,
+ notify_hook_finished,
+ &cb_data,
+ "hook",
+ hookname);
- return rc;
+ return cb_data.rc;
}
diff --git a/hook.h b/hook.h
index 5184dcaa5a..f54568afe3 100644
--- a/hook.h
+++ b/hook.h
@@ -37,6 +37,9 @@ enum hookdir_opt
*/
enum hookdir_opt configured_hookdir_opt(void);
+/* Provides the number of threads to use for parallel hook execution. */
+int configured_hook_jobs(void);
+
struct run_hooks_opt
{
/* Environment vars to be set for each hook */
@@ -54,15 +57,38 @@ struct run_hooks_opt
/* Path to file which should be piped to stdin for each hook */
const char *path_to_stdin;
+
+ /* Number of threads to parallelize across */
+ int jobs;
};
-#define RUN_HOOKS_OPT_INIT { \
+/*
+ * Callback provided to feed_pipe_fn and consume_sideband_fn.
+ */
+struct hook_cb_data {
+ int rc;
+ struct list_head *head;
+ struct list_head *run_me;
+ struct run_hooks_opt *options;
+};
+
+#define RUN_HOOKS_OPT_INIT_SYNC { \
.env = STRVEC_INIT, \
.args = STRVEC_INIT, \
.path_to_stdin = NULL, \
+ .jobs = 1, \
.run_hookdir = configured_hookdir_opt() \
}
+#define RUN_HOOKS_OPT_INIT_ASYNC { \
+ .env = STRVEC_INIT, \
+ .args = STRVEC_INIT, \
+ .path_to_stdin = NULL, \
+ .jobs = configured_hook_jobs(), \
+ .run_hookdir = configured_hookdir_opt() \
+}
+
+
void run_hooks_opt_init(struct run_hooks_opt *o);
void run_hooks_opt_clear(struct run_hooks_opt *o);
--
2.28.0.rc0.142.g3c755180ce-goog
next prev parent reply other threads:[~2020-12-05 1:57 UTC|newest]
Thread overview: 170+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-21 18:54 [PATCH v2 0/4] propose config-based hooks Emily Shaffer
2020-05-21 18:54 ` [PATCH v2 1/4] doc: propose hooks managed by the config Emily Shaffer
2020-05-22 10:13 ` Phillip Wood
2020-06-09 20:26 ` Emily Shaffer
2020-05-21 18:54 ` [PATCH v2 2/4] hook: scaffolding for git-hook subcommand Emily Shaffer
2020-05-21 18:54 ` [PATCH v2 3/4] hook: add list command Emily Shaffer
2020-05-22 10:27 ` Phillip Wood
2020-06-09 21:49 ` Emily Shaffer
2020-08-17 13:36 ` Phillip Wood
2020-05-24 23:00 ` Johannes Schindelin
2020-05-27 23:37 ` Emily Shaffer
2020-05-21 18:54 ` [PATCH v2 4/4] hook: add --porcelain to " Emily Shaffer
2020-05-24 23:00 ` Johannes Schindelin
2020-05-25 0:29 ` Johannes Schindelin
2020-07-28 22:24 ` [PATCH v3 0/6] propose config-based hooks Emily Shaffer
2020-07-28 22:24 ` [PATCH v3 1/6] doc: propose hooks managed by the config Emily Shaffer
2020-07-28 22:24 ` [PATCH v3 2/6] hook: scaffolding for git-hook subcommand Emily Shaffer
2020-07-28 22:24 ` [PATCH v3 3/6] hook: add list command Emily Shaffer
2020-07-28 22:24 ` [PATCH v3 4/6] hook: add --porcelain to " Emily Shaffer
2020-07-28 22:24 ` [RFC PATCH v3 5/6] parse-options: parse into argv_array Emily Shaffer
2020-07-29 19:33 ` Junio C Hamano
2020-07-30 23:41 ` Junio C Hamano
2020-07-28 22:24 ` [RFC PATCH v3 6/6] hook: add 'run' subcommand Emily Shaffer
2020-09-09 0:49 ` [PATCH v4 0/9] propose config-based hooks Emily Shaffer
2020-09-09 0:49 ` [PATCH v4 1/9] doc: propose hooks managed by the config Emily Shaffer
2020-09-23 22:59 ` Jonathan Tan
2020-09-24 21:54 ` Emily Shaffer
2020-10-07 9:23 ` Ævar Arnfjörð Bjarmason
2020-10-22 0:58 ` Emily Shaffer
2020-10-23 19:10 ` Ævar Arnfjörð Bjarmason
2020-10-29 15:38 ` Emily Shaffer
2020-10-29 20:04 ` Ævar Arnfjörð Bjarmason
2020-09-09 0:49 ` [PATCH v4 2/9] hook: scaffolding for git-hook subcommand Emily Shaffer
2020-10-05 23:24 ` Jonathan Nieder
2020-10-06 19:06 ` Emily Shaffer
2020-09-09 0:49 ` [PATCH v4 3/9] hook: add list command Emily Shaffer
2020-09-11 13:27 ` Phillip Wood
2020-09-11 16:51 ` Emily Shaffer
2020-09-23 23:04 ` Jonathan Tan
2020-10-06 20:46 ` Emily Shaffer
2020-09-27 19:23 ` Martin Ågren
2020-10-06 20:20 ` Emily Shaffer
2020-10-05 23:27 ` Jonathan Nieder
2020-09-09 0:49 ` [PATCH v4 4/9] hook: add --porcelain to " Emily Shaffer
2020-09-28 19:29 ` Josh Steadmon
2020-09-09 0:49 ` [PATCH v4 5/9] parse-options: parse into strvec Emily Shaffer
2020-10-05 23:30 ` Jonathan Nieder
2020-10-06 4:49 ` Junio C Hamano
2020-09-09 0:49 ` [PATCH v4 6/9] hook: add 'run' subcommand Emily Shaffer
2020-09-11 13:30 ` Phillip Wood
2020-09-28 19:29 ` Josh Steadmon
2020-10-05 23:39 ` Jonathan Nieder
2020-10-06 22:57 ` Emily Shaffer
2020-09-09 0:49 ` [PATCH v4 7/9] hook: replace run-command.h:find_hook Emily Shaffer
2020-09-09 20:32 ` Junio C Hamano
2020-09-10 19:08 ` Emily Shaffer
2020-09-23 23:20 ` Jonathan Tan
2020-10-05 23:42 ` Jonathan Nieder
2020-09-09 0:49 ` [PATCH v4 8/9] commit: use config-based hooks Emily Shaffer
2020-09-10 13:50 ` Phillip Wood
2020-09-10 22:21 ` Junio C Hamano
2020-09-23 23:47 ` Jonathan Tan
2020-10-05 21:27 ` Emily Shaffer
2020-10-05 23:48 ` Jonathan Nieder
2020-10-06 19:08 ` Emily Shaffer
2020-09-09 0:49 ` [PATCH v4 9/9] run_commit_hook: take strvec instead of varargs Emily Shaffer
2020-09-10 14:16 ` Phillip Wood
2020-09-11 13:20 ` Phillip Wood
2020-09-09 21:04 ` [PATCH v4 0/9] propose config-based hooks Junio C Hamano
2020-10-14 23:24 ` [PATCH v5 0/8] propose config-based hooks (part I) Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 1/8] doc: propose hooks managed by the config Emily Shaffer
2020-10-15 16:31 ` Ævar Arnfjörð Bjarmason
2020-10-16 17:29 ` Junio C Hamano
2020-10-21 23:37 ` Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 2/8] hook: scaffolding for git-hook subcommand Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 3/8] hook: add list command Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 4/8] hook: include hookdir hook in list Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 5/8] hook: implement hookcmd.<name>.skip Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 6/8] parse-options: parse into strvec Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 7/8] hook: add 'run' subcommand Emily Shaffer
2020-10-14 23:24 ` [PATCH v5 8/8] hook: replace find_hook() with hook_exists() Emily Shaffer
2020-12-05 1:45 ` [PATCH v6 00/17] propose config-based hooks (part I) Emily Shaffer
2020-12-05 1:45 ` [PATCH 01/17] doc: propose hooks managed by the config Emily Shaffer
2020-12-05 1:45 ` [PATCH 02/17] hook: scaffolding for git-hook subcommand Emily Shaffer
2020-12-05 1:45 ` [PATCH 03/17] hook: add list command Emily Shaffer
2020-12-05 1:45 ` [PATCH 04/17] hook: include hookdir hook in list Emily Shaffer
2020-12-05 1:45 ` [PATCH 05/17] hook: respect hook.runHookDir Emily Shaffer
2020-12-05 1:45 ` [PATCH 06/17] hook: implement hookcmd.<name>.skip Emily Shaffer
2020-12-05 1:45 ` [PATCH 07/17] parse-options: parse into strvec Emily Shaffer
2020-12-05 1:45 ` [PATCH 08/17] hook: add 'run' subcommand Emily Shaffer
2020-12-11 10:15 ` Phillip Wood
2020-12-15 21:41 ` Emily Shaffer
2020-12-05 1:45 ` [PATCH 09/17] hook: replace find_hook() with hook_exists() Emily Shaffer
2020-12-05 1:46 ` [PATCH 10/17] hook: support passing stdin to hooks Emily Shaffer
2020-12-05 1:46 ` [PATCH 11/17] run-command: allow stdin for run_processes_parallel Emily Shaffer
2020-12-05 1:46 ` Emily Shaffer [this message]
2020-12-05 1:46 ` [PATCH 13/17] hook: allow specifying working directory for hooks Emily Shaffer
2020-12-05 1:46 ` [PATCH 14/17] run-command: add stdin callback for parallelization Emily Shaffer
2020-12-05 1:46 ` [PATCH 15/17] hook: provide stdin by string_list or callback Emily Shaffer
2020-12-08 21:09 ` SZEDER Gábor
2020-12-08 22:11 ` Emily Shaffer
2020-12-05 1:46 ` [PATCH 16/17] run-command: allow capturing of collated output Emily Shaffer
2020-12-05 1:46 ` [PATCH 17/17] hooks: allow callers to capture output Emily Shaffer
2020-12-16 0:34 ` [PATCH v6 00/17] propose config-based hooks (part I) Josh Steadmon
2020-12-16 0:56 ` Junio C Hamano
2020-12-16 20:16 ` Emily Shaffer
2020-12-16 23:32 ` Junio C Hamano
2020-12-18 2:07 ` Emily Shaffer
2020-12-18 5:29 ` Junio C Hamano
2020-12-22 0:02 ` [PATCH v7 " Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 01/17] doc: propose hooks managed by the config Emily Shaffer
2021-01-23 15:38 ` Ævar Arnfjörð Bjarmason
2021-01-29 23:52 ` Emily Shaffer
2021-02-01 22:11 ` Junio C Hamano
2021-03-10 19:30 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 02/17] hook: scaffolding for git-hook subcommand Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 03/17] hook: add list command Emily Shaffer
2021-01-31 3:10 ` Jonathan Tan
2021-02-09 21:06 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 04/17] hook: include hookdir hook in list Emily Shaffer
2021-01-31 3:20 ` Jonathan Tan
2021-02-09 22:05 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 05/17] hook: respect hook.runHookDir Emily Shaffer
2021-01-31 3:35 ` Jonathan Tan
2021-02-09 22:31 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 06/17] hook: implement hookcmd.<name>.skip Emily Shaffer
2021-01-31 3:40 ` Jonathan Tan
2021-02-09 22:57 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 07/17] parse-options: parse into strvec Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 08/17] hook: add 'run' subcommand Emily Shaffer
2021-01-31 4:22 ` Jonathan Tan
2021-02-11 22:44 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 09/17] hook: replace find_hook() with hook_exists() Emily Shaffer
2021-01-31 4:39 ` Jonathan Tan
2021-02-12 22:15 ` Emily Shaffer
2021-02-18 22:23 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 10/17] hook: support passing stdin to hooks Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 11/17] run-command: allow stdin for run_processes_parallel Emily Shaffer
2021-02-01 5:38 ` Jonathan Tan
2021-02-19 20:23 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 12/17] hook: allow parallel hook execution Emily Shaffer
2021-02-01 6:04 ` Jonathan Tan
2021-02-22 21:46 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 13/17] hook: allow specifying working directory for hooks Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 14/17] run-command: add stdin callback for parallelization Emily Shaffer
2021-02-01 6:51 ` Jonathan Tan
2021-02-22 23:38 ` Emily Shaffer
2021-02-23 19:33 ` Jonathan Tan
2021-03-10 18:24 ` Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 15/17] hook: provide stdin by string_list or callback Emily Shaffer
2021-02-01 7:04 ` Jonathan Tan
2021-02-23 19:52 ` Emily Shaffer
2021-02-25 20:56 ` Jonathan Tan
2021-03-02 1:47 ` Emily Shaffer
2021-03-02 23:33 ` Jonathan Tan
2020-12-22 0:02 ` [PATCH v7 16/17] run-command: allow capturing of collated output Emily Shaffer
2020-12-22 0:02 ` [PATCH v7 17/17] hooks: allow callers to capture output Emily Shaffer
2020-12-22 2:11 ` [PATCH v7 00/17] propose config-based hooks (part I) Junio C Hamano
2020-12-28 18:34 ` Emily Shaffer
2020-12-28 22:50 ` Junio C Hamano
2020-12-28 22:37 ` [PATCH v3 18/17] doc: make git-hook.txt point of truth Emily Shaffer
2020-12-28 22:39 ` Emily Shaffer
2021-01-29 23:59 ` [PATCH v7 00/17] propose config-based hooks (part I) Emily Shaffer
2021-02-16 19:46 ` Josh Steadmon
2021-02-16 22:47 ` Junio C Hamano
2021-02-17 21:21 ` Josh Steadmon
2021-02-17 23:07 ` Junio C Hamano
2021-02-25 19:50 ` Junio C Hamano
2021-03-01 21:51 ` Emily Shaffer
2021-03-01 22:19 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201205014607.1464119-13-emilyshaffer@google.com \
--to=emilyshaffer@google.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).