From: Emily Shaffer <emilyshaffer@google.com>
To: git@vger.kernel.org
Cc: Emily Shaffer <emilyshaffer@google.com>
Subject: [PATCH v7 16/17] run-command: allow capturing of collated output
Date: Mon, 21 Dec 2020 16:02:19 -0800 [thread overview]
Message-ID: <20201222000220.1491091-17-emilyshaffer@google.com> (raw)
In-Reply-To: <20201222000220.1491091-1-emilyshaffer@google.com>
Some callers, for example server-side hooks which wish to relay hook
output to clients across a transport, want to capture what would
normally print to stderr and do something else with it. Allow that via a
callback.
By calling the callback regardless of whether there's output available,
we allow clients to send e.g. a keepalive if necessary.
Because we expose a strbuf, not a fd or FILE*, there's no need to create
a temporary pipe or similar - we can just skip the print to stderr and
instead hand it to the caller.
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
---
Notes:
Originally when writing this patch I attempted to use a pipe in memory -
but managing its lifetime was actually pretty tricky, and I found I could
achieve the same thing with less code by doing it this way. Critique welcome,
including "no, you really need to do it with a pipe".
builtin/fetch.c | 2 +-
builtin/submodule--helper.c | 2 +-
hook.c | 1 +
run-command.c | 33 +++++++++++++++++++++++++--------
run-command.h | 18 +++++++++++++++++-
submodule.c | 2 +-
t/helper/test-run-command.c | 25 ++++++++++++++++++++-----
t/t0061-run-command.sh | 7 +++++++
8 files changed, 73 insertions(+), 17 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 5e153b5193..6a634085d9 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1647,7 +1647,7 @@ static int fetch_multiple(struct string_list *list, int max_children)
result = run_processes_parallel_tr2(max_children,
&fetch_next_remote,
&fetch_failed_to_start,
- NULL,
+ NULL, NULL,
&fetch_finished,
&state,
"fetch", "parallel/fetch");
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index bb623c1852..8c543d33fd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2294,7 +2294,7 @@ static int update_submodules(struct submodule_update_clone *suc)
int i;
run_processes_parallel_tr2(suc->max_jobs, update_clone_get_next_task,
- update_clone_start_failure, NULL,
+ update_clone_start_failure, NULL, NULL,
update_clone_task_finished, suc, "submodule",
"parallel/update");
diff --git a/hook.c b/hook.c
index b63a34d0a6..1439322a29 100644
--- a/hook.c
+++ b/hook.c
@@ -406,6 +406,7 @@ int run_hooks(const char *hookname, struct run_hooks_opt *options)
pick_next_hook,
notify_start_failure,
options->feed_pipe,
+ NULL,
notify_hook_finished,
&cb_data,
"hook",
diff --git a/run-command.c b/run-command.c
index 7b65c087f8..0dce6bec83 100644
--- a/run-command.c
+++ b/run-command.c
@@ -1549,6 +1549,7 @@ struct parallel_processes {
get_next_task_fn get_next_task;
start_failure_fn start_failure;
feed_pipe_fn feed_pipe;
+ consume_sideband_fn consume_sideband;
task_finished_fn task_finished;
struct {
@@ -1614,6 +1615,7 @@ static void pp_init(struct parallel_processes *pp,
get_next_task_fn get_next_task,
start_failure_fn start_failure,
feed_pipe_fn feed_pipe,
+ consume_sideband_fn consume_sideband,
task_finished_fn task_finished,
void *data)
{
@@ -1634,6 +1636,7 @@ static void pp_init(struct parallel_processes *pp,
pp->start_failure = start_failure ? start_failure : default_start_failure;
pp->feed_pipe = feed_pipe ? feed_pipe : default_feed_pipe;
pp->task_finished = task_finished ? task_finished : default_task_finished;
+ pp->consume_sideband = consume_sideband;
pp->nr_processes = 0;
pp->output_owner = 0;
@@ -1670,7 +1673,10 @@ static void pp_cleanup(struct parallel_processes *pp)
* When get_next_task added messages to the buffer in its last
* iteration, the buffered output is non empty.
*/
- strbuf_write(&pp->buffered_output, stderr);
+ if (pp->consume_sideband)
+ pp->consume_sideband(&pp->buffered_output, pp->data);
+ else
+ strbuf_write(&pp->buffered_output, stderr);
strbuf_release(&pp->buffered_output);
sigchain_pop_common();
@@ -1786,9 +1792,13 @@ static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout)
static void pp_output(struct parallel_processes *pp)
{
int i = pp->output_owner;
+
if (pp->children[i].state == GIT_CP_WORKING &&
pp->children[i].err.len) {
- strbuf_write(&pp->children[i].err, stderr);
+ if (pp->consume_sideband)
+ pp->consume_sideband(&pp->children[i].err, pp->data);
+ else
+ strbuf_write(&pp->children[i].err, stderr);
strbuf_reset(&pp->children[i].err);
}
}
@@ -1827,11 +1837,15 @@ static int pp_collect_finished(struct parallel_processes *pp)
strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
strbuf_reset(&pp->children[i].err);
} else {
- strbuf_write(&pp->children[i].err, stderr);
+ /* Output errors, then all other finished child processes */
+ if (pp->consume_sideband) {
+ pp->consume_sideband(&pp->children[i].err, pp->data);
+ pp->consume_sideband(&pp->buffered_output, pp->data);
+ } else {
+ strbuf_write(&pp->children[i].err, stderr);
+ strbuf_write(&pp->buffered_output, stderr);
+ }
strbuf_reset(&pp->children[i].err);
-
- /* Output all other finished child processes */
- strbuf_write(&pp->buffered_output, stderr);
strbuf_reset(&pp->buffered_output);
/*
@@ -1855,6 +1869,7 @@ int run_processes_parallel(int n,
get_next_task_fn get_next_task,
start_failure_fn start_failure,
feed_pipe_fn feed_pipe,
+ consume_sideband_fn consume_sideband,
task_finished_fn task_finished,
void *pp_cb)
{
@@ -1865,7 +1880,7 @@ int run_processes_parallel(int n,
sigchain_push(SIGPIPE, SIG_IGN);
- pp_init(&pp, n, get_next_task, start_failure, feed_pipe, task_finished, pp_cb);
+ pp_init(&pp, n, get_next_task, start_failure, feed_pipe, consume_sideband, task_finished, pp_cb);
while (1) {
for (i = 0;
i < spawn_cap && !pp.shutdown &&
@@ -1903,6 +1918,7 @@ int run_processes_parallel(int n,
int run_processes_parallel_tr2(int n, get_next_task_fn get_next_task,
start_failure_fn start_failure,
feed_pipe_fn feed_pipe,
+ consume_sideband_fn consume_sideband,
task_finished_fn task_finished, void *pp_cb,
const char *tr2_category, const char *tr2_label)
{
@@ -1912,7 +1928,8 @@ int run_processes_parallel_tr2(int n, get_next_task_fn get_next_task,
((n < 1) ? online_cpus() : n));
result = run_processes_parallel(n, get_next_task, start_failure,
- feed_pipe, task_finished, pp_cb);
+ feed_pipe, consume_sideband,
+ task_finished, pp_cb);
trace2_region_leave(tr2_category, tr2_label, NULL);
diff --git a/run-command.h b/run-command.h
index e058c0e2c8..2ad8271f56 100644
--- a/run-command.h
+++ b/run-command.h
@@ -450,6 +450,20 @@ typedef int (*feed_pipe_fn)(struct strbuf *pipe,
void *pp_cb,
void *pp_task_cb);
+/**
+ * If this callback is provided, instead of collating process output to stderr,
+ * they will be collated into a new pipe. consume_sideband_fn will be called
+ * repeatedly. When output is available on that pipe, it will be contained in
+ * 'output'. But it will be called with an empty 'output' too, to allow for
+ * keepalives or similar operations if necessary.
+ *
+ * pp_cb is the callback cookie as passed into run_processes_parallel.
+ *
+ * Since this callback is provided with the collated output, no task cookie is
+ * provided.
+ */
+typedef void (*consume_sideband_fn)(struct strbuf *output, void *pp_cb);
+
/**
* This callback is called on every child process that finished processing.
*
@@ -485,10 +499,12 @@ int run_processes_parallel(int n,
get_next_task_fn,
start_failure_fn,
feed_pipe_fn,
+ consume_sideband_fn,
task_finished_fn,
void *pp_cb);
int run_processes_parallel_tr2(int n, get_next_task_fn, start_failure_fn,
- feed_pipe_fn, task_finished_fn, void *pp_cb,
+ feed_pipe_fn, consume_sideband_fn,
+ task_finished_fn, void *pp_cb,
const char *tr2_category, const char *tr2_label);
#endif
diff --git a/submodule.c b/submodule.c
index 953f41818c..215bff22d9 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1638,7 +1638,7 @@ int fetch_populated_submodules(struct repository *r,
run_processes_parallel_tr2(max_parallel_jobs,
get_next_submodule,
fetch_start_failure,
- NULL,
+ NULL, NULL,
fetch_finish,
&spf,
"submodule", "parallel/fetch");
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 9348184d30..d53db6d11c 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -51,6 +51,16 @@ static int no_job(struct child_process *cp,
return 0;
}
+static void test_consume_sideband(struct strbuf *output, void *cb)
+{
+ FILE *sideband;
+
+ sideband = fopen("./sideband", "a");
+
+ strbuf_write(output, sideband);
+ fclose(sideband);
+}
+
static int task_finished(int result,
struct strbuf *err,
void *pp_cb,
@@ -201,7 +211,7 @@ static int testsuite(int argc, const char **argv)
suite.tests.nr, max_jobs);
ret = run_processes_parallel(max_jobs, next_test, test_failed,
- test_stdin, test_finished, &suite);
+ test_stdin, NULL, test_finished, &suite);
if (suite.failed.nr > 0) {
ret = 1;
@@ -429,23 +439,28 @@ int cmd__run_command(int argc, const char **argv)
if (!strcmp(argv[1], "run-command-parallel"))
exit(run_processes_parallel(jobs, parallel_next,
- NULL, NULL, NULL, &proc));
+ NULL, NULL, NULL, NULL, &proc));
if (!strcmp(argv[1], "run-command-abort"))
exit(run_processes_parallel(jobs, parallel_next,
- NULL, NULL, task_finished, &proc));
+ NULL, NULL, NULL, task_finished, &proc));
if (!strcmp(argv[1], "run-command-no-jobs"))
exit(run_processes_parallel(jobs, no_job,
- NULL, NULL, task_finished, &proc));
+ NULL, NULL, NULL, task_finished, &proc));
if (!strcmp(argv[1], "run-command-stdin")) {
proc.in = -1;
proc.no_stdin = 0;
exit (run_processes_parallel(jobs, parallel_next, NULL,
- test_stdin, NULL, &proc));
+ test_stdin, NULL, NULL, &proc));
}
+ if (!strcmp(argv[1], "run-command-sideband"))
+ exit(run_processes_parallel(jobs, parallel_next, NULL, NULL,
+ test_consume_sideband, NULL,
+ &proc));
+
fprintf(stderr, "check usage\n");
return 1;
}
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
index 87759482ad..e99f6c7f44 100755
--- a/t/t0061-run-command.sh
+++ b/t/t0061-run-command.sh
@@ -143,6 +143,13 @@ test_expect_success 'run_command runs in parallel with more tasks than jobs avai
test_cmp expect actual
'
+test_expect_success 'run_command can divert output' '
+ test_when_finished rm sideband &&
+ test-tool run-command run-command-sideband 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test_must_be_empty actual &&
+ test_cmp expect sideband
+'
+
cat >expect <<-EOF
preloaded output of a child
listening for stdin:
--
2.28.0.rc0.142.g3c755180ce-goog
next prev parent reply other threads:[~2020-12-22 0:04 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 ` [PATCH 12/17] hook: allow parallel hook execution Emily Shaffer
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 ` Emily Shaffer [this message]
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201222000220.1491091-17-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.
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 NNTP newsgroup(s).