summaryrefslogtreecommitdiff
path: root/run-command.c
diff options
context:
space:
mode:
Diffstat (limited to 'run-command.c')
-rw-r--r--run-command.c92
1 files changed, 63 insertions, 29 deletions
diff --git a/run-command.c b/run-command.c
index a8501e3..14f1783 100644
--- a/run-command.c
+++ b/run-command.c
@@ -20,7 +20,7 @@ void child_process_init(struct child_process *child)
void child_process_clear(struct child_process *child)
{
strvec_clear(&child->args);
- strvec_clear(&child->env_array);
+ strvec_clear(&child->env);
}
struct child_to_clean {
@@ -646,7 +646,7 @@ static void trace_run_command(const struct child_process *cp)
sq_quote_buf_pretty(&buf, cp->dir);
strbuf_addch(&buf, ';');
}
- trace_add_env(&buf, cp->env_array.v);
+ trace_add_env(&buf, cp->env.v);
if (cp->git_cmd)
strbuf_addstr(&buf, " git");
sq_quote_argv_pretty(&buf, cp->args.v);
@@ -751,7 +751,7 @@ fail_pipe:
set_cloexec(null_fd);
}
- childenv = prep_childenv(cmd->env_array.v);
+ childenv = prep_childenv(cmd->env.v);
atfork_prepare(&as);
/*
@@ -914,8 +914,9 @@ end_of_spawn:
else if (cmd->use_shell)
cmd->args.v = prepare_shell_cmd(&nargv, sargv);
- cmd->pid = mingw_spawnvpe(cmd->args.v[0], cmd->args.v, (char**) cmd->env_array.v,
- cmd->dir, fhin, fhout, fherr);
+ cmd->pid = mingw_spawnvpe(cmd->args.v[0], cmd->args.v,
+ (char**) cmd->env.v,
+ cmd->dir, fhin, fhout, fherr);
failed_errno = errno;
if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
error_errno("cannot spawn %s", cmd->args.v[0]);
@@ -983,7 +984,8 @@ int finish_command(struct child_process *cmd)
int finish_command_in_signal(struct child_process *cmd)
{
int ret = wait_or_whine(cmd->pid, cmd->args.v[0], 1);
- trace2_child_exit(cmd, ret);
+ if (ret != -1)
+ trace2_child_exit(cmd, ret);
return ret;
}
@@ -1031,7 +1033,7 @@ int run_command_v_opt_cd_env_tr2(const char **argv, int opt, const char *dir,
cmd.close_object_store = opt & RUN_CLOSE_OBJECT_STORE ? 1 : 0;
cmd.dir = dir;
if (env)
- strvec_pushv(&cmd.env_array, (const char **)env);
+ strvec_pushv(&cmd.env, (const char **)env);
cmd.trace2_child_class = tr2_class;
return run_command(&cmd);
}
@@ -1471,6 +1473,7 @@ enum child_state {
GIT_CP_WAIT_CLEANUP,
};
+int run_processes_parallel_ungroup;
struct parallel_processes {
void *data;
@@ -1494,6 +1497,7 @@ struct parallel_processes {
struct pollfd *pfd;
unsigned shutdown : 1;
+ unsigned ungroup : 1;
int output_owner;
struct strbuf buffered_output; /* of finished children */
@@ -1537,7 +1541,7 @@ static void pp_init(struct parallel_processes *pp,
get_next_task_fn get_next_task,
start_failure_fn start_failure,
task_finished_fn task_finished,
- void *data)
+ void *data, int ungroup)
{
int i;
@@ -1559,15 +1563,21 @@ static void pp_init(struct parallel_processes *pp,
pp->nr_processes = 0;
pp->output_owner = 0;
pp->shutdown = 0;
+ pp->ungroup = ungroup;
CALLOC_ARRAY(pp->children, n);
- CALLOC_ARRAY(pp->pfd, n);
+ if (pp->ungroup)
+ pp->pfd = NULL;
+ else
+ CALLOC_ARRAY(pp->pfd, n);
strbuf_init(&pp->buffered_output, 0);
for (i = 0; i < n; i++) {
strbuf_init(&pp->children[i].err, 0);
child_process_init(&pp->children[i].process);
- pp->pfd[i].events = POLLIN | POLLHUP;
- pp->pfd[i].fd = -1;
+ if (pp->pfd) {
+ pp->pfd[i].events = POLLIN | POLLHUP;
+ pp->pfd[i].fd = -1;
+ }
}
pp_for_signal = pp;
@@ -1615,24 +1625,31 @@ static int pp_start_one(struct parallel_processes *pp)
BUG("bookkeeping is hard");
code = pp->get_next_task(&pp->children[i].process,
- &pp->children[i].err,
+ pp->ungroup ? NULL : &pp->children[i].err,
pp->data,
&pp->children[i].data);
if (!code) {
- strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
- strbuf_reset(&pp->children[i].err);
+ if (!pp->ungroup) {
+ strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
+ strbuf_reset(&pp->children[i].err);
+ }
return 1;
}
- pp->children[i].process.err = -1;
- pp->children[i].process.stdout_to_stderr = 1;
+ if (!pp->ungroup) {
+ pp->children[i].process.err = -1;
+ pp->children[i].process.stdout_to_stderr = 1;
+ }
pp->children[i].process.no_stdin = 1;
if (start_command(&pp->children[i].process)) {
- code = pp->start_failure(&pp->children[i].err,
+ code = pp->start_failure(pp->ungroup ? NULL :
+ &pp->children[i].err,
pp->data,
pp->children[i].data);
- strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
- strbuf_reset(&pp->children[i].err);
+ if (!pp->ungroup) {
+ strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
+ strbuf_reset(&pp->children[i].err);
+ }
if (code)
pp->shutdown = 1;
return code;
@@ -1640,7 +1657,8 @@ static int pp_start_one(struct parallel_processes *pp)
pp->nr_processes++;
pp->children[i].state = GIT_CP_WORKING;
- pp->pfd[i].fd = pp->children[i].process.err;
+ if (pp->pfd)
+ pp->pfd[i].fd = pp->children[i].process.err;
return 0;
}
@@ -1674,6 +1692,7 @@ 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);
@@ -1696,7 +1715,7 @@ static int pp_collect_finished(struct parallel_processes *pp)
code = finish_command(&pp->children[i].process);
- code = pp->task_finished(code,
+ code = pp->task_finished(code, pp->ungroup ? NULL :
&pp->children[i].err, pp->data,
pp->children[i].data);
@@ -1707,10 +1726,13 @@ static int pp_collect_finished(struct parallel_processes *pp)
pp->nr_processes--;
pp->children[i].state = GIT_CP_FREE;
- pp->pfd[i].fd = -1;
+ if (pp->pfd)
+ pp->pfd[i].fd = -1;
child_process_init(&pp->children[i].process);
- if (i != pp->output_owner) {
+ if (pp->ungroup) {
+ ; /* no strbuf_*() work to do here */
+ } else if (i != pp->output_owner) {
strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
strbuf_reset(&pp->children[i].err);
} else {
@@ -1747,9 +1769,14 @@ int run_processes_parallel(int n,
int i, code;
int output_timeout = 100;
int spawn_cap = 4;
+ int ungroup = run_processes_parallel_ungroup;
struct parallel_processes pp;
- pp_init(&pp, n, get_next_task, start_failure, task_finished, pp_cb);
+ /* unset for the next API user */
+ run_processes_parallel_ungroup = 0;
+
+ pp_init(&pp, n, get_next_task, start_failure, task_finished, pp_cb,
+ ungroup);
while (1) {
for (i = 0;
i < spawn_cap && !pp.shutdown &&
@@ -1766,8 +1793,15 @@ int run_processes_parallel(int n,
}
if (!pp.nr_processes)
break;
- pp_buffer_stderr(&pp, output_timeout);
- pp_output(&pp);
+ if (ungroup) {
+ int i;
+
+ for (i = 0; i < pp.max_processes; i++)
+ pp.children[i].state = GIT_CP_WAIT_CLEANUP;
+ } else {
+ pp_buffer_stderr(&pp, output_timeout);
+ pp_output(&pp);
+ }
code = pp_collect_finished(&pp);
if (code) {
pp.shutdown = 1;
@@ -1815,16 +1849,16 @@ int run_auto_maintenance(int quiet)
return run_command(&maint);
}
-void prepare_other_repo_env(struct strvec *env_array, const char *new_git_dir)
+void prepare_other_repo_env(struct strvec *env, const char *new_git_dir)
{
const char * const *var;
for (var = local_repo_env; *var; var++) {
if (strcmp(*var, CONFIG_DATA_ENVIRONMENT) &&
strcmp(*var, CONFIG_COUNT_ENVIRONMENT))
- strvec_push(env_array, *var);
+ strvec_push(env, *var);
}
- strvec_pushf(env_array, "%s=%s", GIT_DIR_ENVIRONMENT, new_git_dir);
+ strvec_pushf(env, "%s=%s", GIT_DIR_ENVIRONMENT, new_git_dir);
}
enum start_bg_result start_bg_command(struct child_process *cmd,