From: Calvin Wan <calvinwan@google.com>
To: git@vger.kernel.org
Cc: Calvin Wan <calvinwan@google.com>,
emilyshaffer@google.com, avarab@gmail.com,
phillip.wood123@gmail.com
Subject: [PATCH v2 1/4] run-command: add pipe_output_fn to run_processes_parallel_opts
Date: Tue, 11 Oct 2022 23:26:01 +0000 [thread overview]
Message-ID: <20221011232604.839941-2-calvinwan@google.com> (raw)
In-Reply-To: <https://lore.kernel.org/git/20220922232947.631309-1-calvinwan@google.com/>
Add pipe_output_fn as an optionally set function in
run_process_parallel_opts. If set, output from each child process is
piped to the callback function to allow for separate parsing.
Signed-off-by: Calvin Wan <calvinwan@google.com>
---
run-command.c | 12 +++++--
run-command.h | 22 +++++++++++++
t/helper/test-run-command.c | 18 ++++++++++
t/t0061-run-command.sh | 65 +++++++++++++++++++++++--------------
4 files changed, 90 insertions(+), 27 deletions(-)
diff --git a/run-command.c b/run-command.c
index da02631933..c6090e4cb8 100644
--- a/run-command.c
+++ b/run-command.c
@@ -1689,12 +1689,16 @@ static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout)
}
}
-static void pp_output(struct parallel_processes *pp)
+static void pp_output(struct parallel_processes *pp,
+ const struct run_process_parallel_opts *opts)
{
int i = pp->output_owner;
if (pp->children[i].state == GIT_CP_WORKING &&
pp->children[i].err.len) {
+ if (opts->pipe_output)
+ opts->pipe_output(&pp->children[i].err, pp->data,
+ pp->children[i].data);
strbuf_write(&pp->children[i].err, stderr);
strbuf_reset(&pp->children[i].err);
}
@@ -1716,6 +1720,10 @@ static int pp_collect_finished(struct parallel_processes *pp,
code = finish_command(&pp->children[i].process);
+ if (opts->pipe_output)
+ opts->pipe_output(&pp->children[i].err, pp->data,
+ pp->children[i].data);
+
if (opts->task_finished)
code = opts->task_finished(code, opts->ungroup ? NULL :
&pp->children[i].err, pp->data,
@@ -1803,7 +1811,7 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts)
pp.children[i].state = GIT_CP_WAIT_CLEANUP;
} else {
pp_buffer_stderr(&pp, output_timeout);
- pp_output(&pp);
+ pp_output(&pp, opts);
}
code = pp_collect_finished(&pp, opts);
if (code) {
diff --git a/run-command.h b/run-command.h
index 075bd9b9de..cb51c56ea6 100644
--- a/run-command.h
+++ b/run-command.h
@@ -440,6 +440,22 @@ typedef int (*start_failure_fn)(struct strbuf *out,
void *pp_cb,
void *pp_task_cb);
+/**
+ * This callback is periodically called while child processes are
+ * running and also when a child process finishes.
+ *
+ * "struct strbuf *out" contains the output collected from pp_task_cb
+ * since the last call of this function.
+ *
+ * pp_cb is the callback cookie as passed into run_processes_parallel,
+ * pp_task_cb is the callback cookie as passed into get_next_task_fn.
+ *
+ * This function is incompatible with "ungroup"
+ */
+typedef void (*pipe_output_fn)(struct strbuf *out,
+ void *pp_cb,
+ void *pp_task_cb);
+
/**
* This callback is called on every child process that finished processing.
*
@@ -493,6 +509,12 @@ struct run_process_parallel_opts
*/
start_failure_fn start_failure;
+ /**
+ * pipe_output: See pipe_output_fn() above. This should be
+ * NULL unless process specific output is needed
+ */
+ pipe_output_fn pipe_output;
+
/**
* task_finished: See task_finished_fn() above. This can be
* NULL to omit any special handling.
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 46bac2bb70..d3c3df7960 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -52,6 +52,18 @@ static int no_job(struct child_process *cp,
return 0;
}
+static void pipe_output(struct strbuf *out,
+ void *pp_cb,
+ void *pp_task_cb)
+{
+ fprintf(stderr, "%s", out->buf);
+ /*
+ * Resetting output to show that piped output would print the
+ * same as other tests without the pipe_output() function set
+ */
+ strbuf_reset(out);
+}
+
static int task_finished(int result,
struct strbuf *err,
void *pp_cb,
@@ -439,6 +451,12 @@ int cmd__run_command(int argc, const char **argv)
opts.ungroup = 1;
}
+ if (!strcmp(argv[1], "--pipe-output")) {
+ argv += 1;
+ argc -= 1;
+ opts.pipe_output = pipe_output;
+ }
+
jobs = atoi(argv[2]);
strvec_clear(&proc.args);
strvec_pushv(&proc.args, (const char **)argv + 3);
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
index 19af082750..feabb3717b 100755
--- a/t/t0061-run-command.sh
+++ b/t/t0061-run-command.sh
@@ -129,11 +129,14 @@ Hello
World
EOF
-test_expect_success 'run_command runs in parallel with more jobs available than tasks' '
- test-tool run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
- test_must_be_empty out &&
- test_cmp expect err
-'
+for opt in '' '--pipe-output'
+do
+ test_expect_success "run_command runs in parallel with more jobs available than tasks $opt" '
+ test-tool run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test_cmp expect err
+ '
+done
test_expect_success 'run_command runs ungrouped in parallel with more jobs available than tasks' '
test-tool run-command --ungroup run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
@@ -141,11 +144,14 @@ test_expect_success 'run_command runs ungrouped in parallel with more jobs avail
test_line_count = 4 err
'
-test_expect_success 'run_command runs in parallel with as many jobs as tasks' '
- test-tool run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
- test_must_be_empty out &&
- test_cmp expect err
-'
+for opt in '' '--pipe-output'
+do
+ test_expect_success "run_command runs in parallel with as many jobs as tasks $opt" '
+ test-tool run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test_cmp expect err
+ '
+done
test_expect_success 'run_command runs ungrouped in parallel with as many jobs as tasks' '
test-tool run-command --ungroup run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
@@ -153,11 +159,14 @@ test_expect_success 'run_command runs ungrouped in parallel with as many jobs as
test_line_count = 4 err
'
-test_expect_success 'run_command runs in parallel with more tasks than jobs available' '
- test-tool run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
- test_must_be_empty out &&
- test_cmp expect err
-'
+for opt in '' '--pipe-output'
+do
+ test_expect_success "run_command runs in parallel with more tasks than jobs available $opt" '
+ test-tool run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test_cmp expect err
+ '
+done
test_expect_success 'run_command runs ungrouped in parallel with more tasks than jobs available' '
test-tool run-command --ungroup run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
@@ -174,11 +183,14 @@ preloaded output of a child
asking for a quick stop
EOF
-test_expect_success 'run_command is asked to abort gracefully' '
- test-tool run-command run-command-abort 3 false >out 2>err &&
- test_must_be_empty out &&
- test_cmp expect err
-'
+for opt in '' '--pipe-output'
+do
+ test_expect_success "run_command is asked to abort gracefully $opt" '
+ test-tool run-command run-command-abort 3 false >out 2>err &&
+ test_must_be_empty out &&
+ test_cmp expect err
+ '
+done
test_expect_success 'run_command is asked to abort gracefully (ungroup)' '
test-tool run-command --ungroup run-command-abort 3 false >out 2>err &&
@@ -190,11 +202,14 @@ cat >expect <<-EOF
no further jobs available
EOF
-test_expect_success 'run_command outputs ' '
- test-tool run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
- test_must_be_empty out &&
- test_cmp expect err
-'
+for opt in '' '--pipe-output'
+do
+ test_expect_success "run_command outputs $opt" '
+ test-tool run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test_cmp expect err
+ '
+done
test_expect_success 'run_command outputs (ungroup) ' '
test-tool run-command --ungroup run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
--
2.38.0.rc1.362.ged0d419d3c-goog
next prev parent reply other threads:[~2022-10-11 23:26 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <https://lore.kernel.org/git/20220922232947.631309-1-calvinwan@google.com/>
2022-10-11 23:26 ` [PATCH v2 0/4] submodule: parallelize diff Calvin Wan
2022-10-12 5:52 ` Junio C Hamano
2022-10-14 0:39 ` Calvin Wan
2022-10-11 23:26 ` Calvin Wan [this message]
2022-10-12 7:58 ` [PATCH v2 1/4] run-command: add pipe_output_fn to run_processes_parallel_opts Ævar Arnfjörð Bjarmason
2022-10-11 23:26 ` [PATCH v2 2/4] submodule: move status parsing into function Calvin Wan
2022-10-12 7:41 ` Ævar Arnfjörð Bjarmason
2022-10-12 8:27 ` Ævar Arnfjörð Bjarmason
2022-10-11 23:26 ` [PATCH v2 3/4] diff-lib: refactor match_stat_with_submodule Calvin Wan
2022-10-11 23:26 ` [PATCH v2 4/4] diff-lib: parallelize run_diff_files for submodules Calvin Wan
2022-10-12 8:31 ` Ævar Arnfjörð Bjarmason
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=20221011232604.839941-2-calvinwan@google.com \
--to=calvinwan@google.com \
--cc=avarab@gmail.com \
--cc=emilyshaffer@google.com \
--cc=git@vger.kernel.org \
--cc=phillip.wood123@gmail.com \
/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).