Merge branch 'ab/hooks-regression-fix'
In Git 2.36 we revamped the way how hooks are invoked. One change that is end-user visible is that the output of a hook is no longer directly connected to the standard output of "git" that spawns the hook, which was noticed post release. This is getting corrected. * ab/hooks-regression-fix: hook API: fix v2.36.0 regression: hooks should be connected to a TTY run-command: add an "ungroup" option to run_process_parallel()
This commit is contained in:
@ -1472,6 +1472,7 @@ enum child_state {
|
||||
GIT_CP_WAIT_CLEANUP,
|
||||
};
|
||||
|
||||
int run_processes_parallel_ungroup;
|
||||
struct parallel_processes {
|
||||
void *data;
|
||||
|
||||
@ -1495,6 +1496,7 @@ struct parallel_processes {
|
||||
struct pollfd *pfd;
|
||||
|
||||
unsigned shutdown : 1;
|
||||
unsigned ungroup : 1;
|
||||
|
||||
int output_owner;
|
||||
struct strbuf buffered_output; /* of finished children */
|
||||
@ -1538,7 +1540,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;
|
||||
|
||||
@ -1560,15 +1562,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;
|
||||
@ -1616,24 +1624,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;
|
||||
@ -1641,7 +1656,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;
|
||||
}
|
||||
|
||||
@ -1675,6 +1691,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);
|
||||
@ -1697,7 +1714,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);
|
||||
|
||||
@ -1708,10 +1725,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 {
|
||||
@ -1748,9 +1768,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 &&
|
||||
@ -1767,8 +1792,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;
|
||||
|
||||
Reference in New Issue
Block a user