]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'ab/run-hook-api-cleanup'
authorJunio C Hamano <gitster@pobox.com>
Thu, 27 Oct 2022 21:51:53 +0000 (14:51 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 27 Oct 2022 21:51:53 +0000 (14:51 -0700)
Move a global variable added as a hack during regression fixes to
its proper place in the API.

* ab/run-hook-api-cleanup:
  run-command.c: remove "max_processes", add "const" to signal() handler
  run-command.c: pass "opts" further down, and use "opts->processes"
  run-command.c: use "opts->processes", not "pp->max_processes"
  run-command.c: don't copy "data" to "struct parallel_processes"
  run-command.c: don't copy "ungroup" to "struct parallel_processes"
  run-command.c: don't copy *_fn to "struct parallel_processes"
  run-command.c: make "struct parallel_processes" const if possible
  run-command API: move *_tr2() users to "run_processes_parallel()"
  run-command API: have run_process_parallel() take an "opts" struct
  run-command.c: use designated init for pp_init(), add "const"
  run-command API: don't fall back on online_cpus()
  run-command API: make "n" parameter a "size_t"
  run-command tests: use "return", not "exit"
  run-command API: have "run_processes_parallel{,_tr2}()" return void
  run-command test helper: use "else if" pattern

builtin/fetch.c
builtin/submodule--helper.c
hook.c
run-command.c
run-command.h
submodule-config.c
submodule.c
t/helper/test-run-command.c
t/t5526-fetch-submodules.sh

index a0fca93bb6a63e441e3921832f7c7d9a7bd3dd78..b06e454cbddaf1fb3cf8211acab71e90a526448b 100644 (file)
@@ -122,6 +122,8 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
                fetch_parallel_config = git_config_int(k, v);
                if (fetch_parallel_config < 0)
                        die(_("fetch.parallel cannot be negative"));
+               if (!fetch_parallel_config)
+                       fetch_parallel_config = online_cpus();
                return 0;
        }
 
@@ -1951,17 +1953,22 @@ static int fetch_multiple(struct string_list *list, int max_children)
 
        if (max_children != 1 && list->nr != 1) {
                struct parallel_fetch_state state = { argv.v, list, 0, 0 };
+               const struct run_process_parallel_opts opts = {
+                       .tr2_category = "fetch",
+                       .tr2_label = "parallel/fetch",
+
+                       .processes = max_children,
+
+                       .get_next_task = &fetch_next_remote,
+                       .start_failure = &fetch_failed_to_start,
+                       .task_finished = &fetch_finished,
+                       .data = &state,
+               };
 
                strvec_push(&argv, "--end-of-options");
-               result = run_processes_parallel_tr2(max_children,
-                                                   &fetch_next_remote,
-                                                   &fetch_failed_to_start,
-                                                   &fetch_finished,
-                                                   &state,
-                                                   "fetch", "parallel/fetch");
-
-               if (!result)
-                       result = state.result;
+
+               run_processes_parallel(&opts);
+               result = state.result;
        } else
                for (i = 0; i < list->nr; i++) {
                        const char *name = list->items[i].string;
index 1e29a3d7dc8d1c9db3a72704ec05ac7782c26335..a7683d35299921c3a00e74e19cdad47379bfd1bb 100644 (file)
@@ -2567,12 +2567,20 @@ static int update_submodules(struct update_data *update_data)
 {
        int i, ret = 0;
        struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
+       const struct run_process_parallel_opts opts = {
+               .tr2_category = "submodule",
+               .tr2_label = "parallel/update",
+
+               .processes = update_data->max_jobs,
+
+               .get_next_task = update_clone_get_next_task,
+               .start_failure = update_clone_start_failure,
+               .task_finished = update_clone_task_finished,
+               .data = &suc,
+       };
 
        suc.update_data = update_data;
-       run_processes_parallel_tr2(suc.update_data->max_jobs, update_clone_get_next_task,
-                                  update_clone_start_failure,
-                                  update_clone_task_finished, &suc, "submodule",
-                                  "parallel/update");
+       run_processes_parallel(&opts);
 
        /*
         * We saved the output and put it out all at once now.
diff --git a/hook.c b/hook.c
index a493939a4fc5901d85a9ad08ca10669641598389..a4fa1031f287652eb734b276d9d6c98df40d9a08 100644 (file)
--- a/hook.c
+++ b/hook.c
@@ -114,8 +114,20 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)
                .options = options,
        };
        const char *const hook_path = find_hook(hook_name);
-       int jobs = 1;
        int ret = 0;
+       const struct run_process_parallel_opts opts = {
+               .tr2_category = "hook",
+               .tr2_label = hook_name,
+
+               .processes = 1,
+               .ungroup = 1,
+
+               .get_next_task = pick_next_hook,
+               .start_failure = notify_start_failure,
+               .task_finished = notify_hook_finished,
+
+               .data = &cb_data,
+       };
 
        if (!options)
                BUG("a struct run_hooks_opt must be provided to run_hooks");
@@ -137,14 +149,7 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)
                cb_data.hook_path = abs_path.buf;
        }
 
-       run_processes_parallel_ungroup = 1;
-       run_processes_parallel_tr2(jobs,
-                                  pick_next_hook,
-                                  notify_start_failure,
-                                  notify_hook_finished,
-                                  &cb_data,
-                                  "hook",
-                                  hook_name);
+       run_processes_parallel(&opts);
        ret = cb_data.rc;
 cleanup:
        strbuf_release(&abs_path);
index 5ec3a46dccf959bd54af42fbeaaf4027dc64996a..c772acd74319698c57db3a6f3399f2922840af13 100644 (file)
@@ -1496,16 +1496,8 @@ enum child_state {
        GIT_CP_WAIT_CLEANUP,
 };
 
-int run_processes_parallel_ungroup;
 struct parallel_processes {
-       void *data;
-
-       int max_processes;
-       int nr_processes;
-
-       get_next_task_fn get_next_task;
-       start_failure_fn start_failure;
-       task_finished_fn task_finished;
+       size_t nr_processes;
 
        struct {
                enum child_state state;
@@ -1520,81 +1512,60 @@ struct parallel_processes {
        struct pollfd *pfd;
 
        unsigned shutdown : 1;
-       unsigned ungroup : 1;
 
-       int output_owner;
+       size_t output_owner;
        struct strbuf buffered_output; /* of finished children */
 };
 
-static int default_start_failure(struct strbuf *out,
-                                void *pp_cb,
-                                void *pp_task_cb)
-{
-       return 0;
-}
+struct parallel_processes_for_signal {
+       const struct run_process_parallel_opts *opts;
+       const struct parallel_processes *pp;
+};
 
-static int default_task_finished(int result,
-                                struct strbuf *out,
-                                void *pp_cb,
-                                void *pp_task_cb)
+static void kill_children(const struct parallel_processes *pp,
+                         const struct run_process_parallel_opts *opts,
+                         int signo)
 {
-       return 0;
+       for (size_t i = 0; i < opts->processes; i++)
+               if (pp->children[i].state == GIT_CP_WORKING)
+                       kill(pp->children[i].process.pid, signo);
 }
 
-static void kill_children(struct parallel_processes *pp, int signo)
+static void kill_children_signal(const struct parallel_processes_for_signal *pp_sig,
+                                int signo)
 {
-       int i, n = pp->max_processes;
-
-       for (i = 0; i < n; i++)
-               if (pp->children[i].state == GIT_CP_WORKING)
-                       kill(pp->children[i].process.pid, signo);
+       kill_children(pp_sig->pp, pp_sig->opts, signo);
 }
 
-static struct parallel_processes *pp_for_signal;
+static struct parallel_processes_for_signal *pp_for_signal;
 
 static void handle_children_on_signal(int signo)
 {
-       kill_children(pp_for_signal, signo);
+       kill_children_signal(pp_for_signal, signo);
        sigchain_pop(signo);
        raise(signo);
 }
 
 static void pp_init(struct parallel_processes *pp,
-                   int n,
-                   get_next_task_fn get_next_task,
-                   start_failure_fn start_failure,
-                   task_finished_fn task_finished,
-                   void *data, int ungroup)
+                   const struct run_process_parallel_opts *opts,
+                   struct parallel_processes_for_signal *pp_sig)
 {
-       int i;
+       const size_t n = opts->processes;
 
-       if (n < 1)
-               n = online_cpus();
+       if (!n)
+               BUG("you must provide a non-zero number of processes!");
 
-       pp->max_processes = n;
+       trace_printf("run_processes_parallel: preparing to run up to %"PRIuMAX" tasks",
+                    (uintmax_t)n);
 
-       trace_printf("run_processes_parallel: preparing to run up to %d tasks", n);
-
-       pp->data = data;
-       if (!get_next_task)
+       if (!opts->get_next_task)
                BUG("you need to specify a get_next_task function");
-       pp->get_next_task = get_next_task;
-
-       pp->start_failure = start_failure ? start_failure : default_start_failure;
-       pp->task_finished = task_finished ? task_finished : default_task_finished;
 
-       pp->nr_processes = 0;
-       pp->output_owner = 0;
-       pp->shutdown = 0;
-       pp->ungroup = ungroup;
        CALLOC_ARRAY(pp->children, n);
-       if (pp->ungroup)
-               pp->pfd = NULL;
-       else
+       if (!opts->ungroup)
                CALLOC_ARRAY(pp->pfd, n);
-       strbuf_init(&pp->buffered_output, 0);
 
-       for (i = 0; i < n; i++) {
+       for (size_t i = 0; i < n; i++) {
                strbuf_init(&pp->children[i].err, 0);
                child_process_init(&pp->children[i].process);
                if (pp->pfd) {
@@ -1603,16 +1574,17 @@ static void pp_init(struct parallel_processes *pp,
                }
        }
 
-       pp_for_signal = pp;
+       pp_sig->pp = pp;
+       pp_sig->opts = opts;
+       pp_for_signal = pp_sig;
        sigchain_push_common(handle_children_on_signal);
 }
 
-static void pp_cleanup(struct parallel_processes *pp)
+static void pp_cleanup(struct parallel_processes *pp,
+                      const struct run_process_parallel_opts *opts)
 {
-       int i;
-
        trace_printf("run_processes_parallel: done");
-       for (i = 0; i < pp->max_processes; i++) {
+       for (size_t i = 0; i < opts->processes; i++) {
                strbuf_release(&pp->children[i].err);
                child_process_clear(&pp->children[i].process);
        }
@@ -1637,39 +1609,45 @@ static void pp_cleanup(struct parallel_processes *pp)
  * <0 no new job was started, user wishes to shutdown early. Use negative code
  *    to signal the children.
  */
-static int pp_start_one(struct parallel_processes *pp)
+static int pp_start_one(struct parallel_processes *pp,
+                       const struct run_process_parallel_opts *opts)
 {
-       int i, code;
+       size_t i;
+       int code;
 
-       for (i = 0; i < pp->max_processes; i++)
+       for (i = 0; i < opts->processes; i++)
                if (pp->children[i].state == GIT_CP_FREE)
                        break;
-       if (i == pp->max_processes)
+       if (i == opts->processes)
                BUG("bookkeeping is hard");
 
-       code = pp->get_next_task(&pp->children[i].process,
-                                pp->ungroup ? NULL : &pp->children[i].err,
-                                pp->data,
-                                &pp->children[i].data);
+       code = opts->get_next_task(&pp->children[i].process,
+                                  opts->ungroup ? NULL : &pp->children[i].err,
+                                  opts->data,
+                                  &pp->children[i].data);
        if (!code) {
-               if (!pp->ungroup) {
+               if (!opts->ungroup) {
                        strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
                        strbuf_reset(&pp->children[i].err);
                }
                return 1;
        }
-       if (!pp->ungroup) {
+       if (!opts->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->ungroup ? NULL :
-                                        &pp->children[i].err,
-                                        pp->data,
-                                        pp->children[i].data);
-               if (!pp->ungroup) {
+               if (opts->start_failure)
+                       code = opts->start_failure(opts->ungroup ? NULL :
+                                                  &pp->children[i].err,
+                                                  opts->data,
+                                                  pp->children[i].data);
+               else
+                       code = 0;
+
+               if (!opts->ungroup) {
                        strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
                        strbuf_reset(&pp->children[i].err);
                }
@@ -1685,19 +1663,21 @@ static int pp_start_one(struct parallel_processes *pp)
        return 0;
 }
 
-static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout)
+static void pp_buffer_stderr(struct parallel_processes *pp,
+                            const struct run_process_parallel_opts *opts,
+                            int output_timeout)
 {
        int i;
 
-       while ((i = poll(pp->pfd, pp->max_processes, output_timeout)) < 0) {
+       while ((i = poll(pp->pfd, opts->processes, output_timeout) < 0)) {
                if (errno == EINTR)
                        continue;
-               pp_cleanup(pp);
+               pp_cleanup(pp, opts);
                die_errno("poll");
        }
 
        /* Buffer output from all pipes. */
-       for (i = 0; i < pp->max_processes; i++) {
+       for (size_t i = 0; i < opts->processes; i++) {
                if (pp->children[i].state == GIT_CP_WORKING &&
                    pp->pfd[i].revents & (POLLIN | POLLHUP)) {
                        int n = strbuf_read_once(&pp->children[i].err,
@@ -1712,9 +1692,9 @@ static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout)
        }
 }
 
-static void pp_output(struct parallel_processes *pp)
+static void pp_output(const struct parallel_processes *pp)
 {
-       int i = pp->output_owner;
+       size_t i = pp->output_owner;
 
        if (pp->children[i].state == GIT_CP_WORKING &&
            pp->children[i].err.len) {
@@ -1723,24 +1703,28 @@ static void pp_output(struct parallel_processes *pp)
        }
 }
 
-static int pp_collect_finished(struct parallel_processes *pp)
+static int pp_collect_finished(struct parallel_processes *pp,
+                              const struct run_process_parallel_opts *opts)
 {
-       int i, code;
-       int n = pp->max_processes;
+       int code;
+       size_t i;
        int result = 0;
 
        while (pp->nr_processes > 0) {
-               for (i = 0; i < pp->max_processes; i++)
+               for (i = 0; i < opts->processes; i++)
                        if (pp->children[i].state == GIT_CP_WAIT_CLEANUP)
                                break;
-               if (i == pp->max_processes)
+               if (i == opts->processes)
                        break;
 
                code = finish_command(&pp->children[i].process);
 
-               code = pp->task_finished(code, pp->ungroup ? NULL :
-                                        &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, opts->data,
+                                                  pp->children[i].data);
+               else
+                       code = 0;
 
                if (code)
                        result = code;
@@ -1753,12 +1737,14 @@ static int pp_collect_finished(struct parallel_processes *pp)
                        pp->pfd[i].fd = -1;
                child_process_init(&pp->children[i].process);
 
-               if (pp->ungroup) {
+               if (opts->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 {
+                       const size_t n = opts->processes;
+
                        strbuf_write(&pp->children[i].err, stderr);
                        strbuf_reset(&pp->children[i].err);
 
@@ -1783,76 +1769,60 @@ static int pp_collect_finished(struct parallel_processes *pp)
        return result;
 }
 
-int run_processes_parallel(int n,
-                          get_next_task_fn get_next_task,
-                          start_failure_fn start_failure,
-                          task_finished_fn task_finished,
-                          void *pp_cb)
+void run_processes_parallel(const struct run_process_parallel_opts *opts)
 {
        int i, code;
        int output_timeout = 100;
        int spawn_cap = 4;
-       int ungroup = run_processes_parallel_ungroup;
-       struct parallel_processes pp;
-
-       /* 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);
+       struct parallel_processes_for_signal pp_sig;
+       struct parallel_processes pp = {
+               .buffered_output = STRBUF_INIT,
+       };
+       /* options */
+       const char *tr2_category = opts->tr2_category;
+       const char *tr2_label = opts->tr2_label;
+       const int do_trace2 = tr2_category && tr2_label;
+
+       if (do_trace2)
+               trace2_region_enter_printf(tr2_category, tr2_label, NULL,
+                                          "max:%d", opts->processes);
+
+       pp_init(&pp, opts, &pp_sig);
        while (1) {
                for (i = 0;
                    i < spawn_cap && !pp.shutdown &&
-                   pp.nr_processes < pp.max_processes;
+                   pp.nr_processes < opts->processes;
                    i++) {
-                       code = pp_start_one(&pp);
+                       code = pp_start_one(&pp, opts);
                        if (!code)
                                continue;
                        if (code < 0) {
                                pp.shutdown = 1;
-                               kill_children(&pp, -code);
+                               kill_children(&pp, opts, -code);
                        }
                        break;
                }
                if (!pp.nr_processes)
                        break;
-               if (ungroup) {
-                       int i;
-
-                       for (i = 0; i < pp.max_processes; i++)
+               if (opts->ungroup) {
+                       for (size_t i = 0; i < opts->processes; i++)
                                pp.children[i].state = GIT_CP_WAIT_CLEANUP;
                } else {
-                       pp_buffer_stderr(&pp, output_timeout);
+                       pp_buffer_stderr(&pp, opts, output_timeout);
                        pp_output(&pp);
                }
-               code = pp_collect_finished(&pp);
+               code = pp_collect_finished(&pp, opts);
                if (code) {
                        pp.shutdown = 1;
                        if (code < 0)
-                               kill_children(&pp, -code);
+                               kill_children(&pp, opts,-code);
                }
        }
 
-       pp_cleanup(&pp);
-       return 0;
-}
-
-int run_processes_parallel_tr2(int n, get_next_task_fn get_next_task,
-                              start_failure_fn start_failure,
-                              task_finished_fn task_finished, void *pp_cb,
-                              const char *tr2_category, const char *tr2_label)
-{
-       int result;
+       pp_cleanup(&pp, opts);
 
-       trace2_region_enter_printf(tr2_category, tr2_label, NULL, "max:%d",
-                                  ((n < 1) ? online_cpus() : n));
-
-       result = run_processes_parallel(n, get_next_task, start_failure,
-                                       task_finished, pp_cb);
-
-       trace2_region_leave(tr2_category, tr2_label, NULL);
-
-       return result;
+       if (do_trace2)
+               trace2_region_leave(tr2_category, tr2_label, NULL);
 }
 
 int run_auto_maintenance(int quiet)
index 0e85e5846a568d12472e24958860b11598d93599..e3e1ea01ad9dde63eaa87d0f102955c36000d2f0 100644 (file)
@@ -459,17 +459,64 @@ typedef int (*task_finished_fn)(int result,
                                void *pp_task_cb);
 
 /**
- * Runs up to n processes at the same time. Whenever a process can be
- * started, the callback get_next_task_fn is called to obtain the data
+ * Option used by run_processes_parallel(), { 0 }-initialized means no
+ * options.
+ */
+struct run_process_parallel_opts
+{
+       /**
+        * tr2_category & tr2_label: sets the trace2 category and label for
+        * logging. These must either be unset, or both of them must be set.
+        */
+       const char *tr2_category;
+       const char *tr2_label;
+
+       /**
+        * processes: see 'processes' in run_processes_parallel() below.
+        */
+       size_t processes;
+
+       /**
+        * ungroup: see 'ungroup' in run_processes_parallel() below.
+        */
+       unsigned int ungroup:1;
+
+       /**
+        * get_next_task: See get_next_task_fn() above. This must be
+        * specified.
+        */
+       get_next_task_fn get_next_task;
+
+       /**
+        * start_failure: See start_failure_fn() above. This can be
+        * NULL to omit any special handling.
+        */
+       start_failure_fn start_failure;
+
+       /**
+        * task_finished: See task_finished_fn() above. This can be
+        * NULL to omit any special handling.
+        */
+       task_finished_fn task_finished;
+
+       /**
+        * data: user data, will be passed as "pp_cb" to the callback
+        * parameters.
+        */
+       void *data;
+};
+
+/**
+ * Options are passed via the "struct run_process_parallel_opts" above.
+ *
+ * Runs N 'processes' at the same time. Whenever a process can be
+ * started, the callback opts.get_next_task is called to obtain the data
  * required to start another child process.
  *
  * The children started via this function run in parallel. Their output
  * (both stdout and stderr) is routed to stderr in a manner that output
  * from different tasks does not interleave (but see "ungroup" below).
  *
- * start_failure_fn and task_finished_fn can be NULL to omit any
- * special handling.
- *
  * If the "ungroup" option isn't specified, the API will set the
  * "stdout_to_stderr" parameter in "struct child_process" and provide
  * the callbacks with a "struct strbuf *out" parameter to write output
@@ -479,20 +526,8 @@ typedef int (*task_finished_fn)(int result,
  * NULL "struct strbuf *out" parameter, and are responsible for
  * emitting their own output, including dealing with any race
  * conditions due to writing in parallel to stdout and stderr.
- * The "ungroup" option can be enabled by setting the global
- * "run_processes_parallel_ungroup" to "1" before invoking
- * run_processes_parallel(), it will be set back to "0" as soon as the
- * API reads that setting.
  */
-extern int run_processes_parallel_ungroup;
-int run_processes_parallel(int n,
-                          get_next_task_fn,
-                          start_failure_fn,
-                          task_finished_fn,
-                          void *pp_cb);
-int run_processes_parallel_tr2(int n, get_next_task_fn, start_failure_fn,
-                              task_finished_fn, void *pp_cb,
-                              const char *tr2_category, const char *tr2_label);
+void run_processes_parallel(const struct run_process_parallel_opts *opts);
 
 /**
  * Convenience function which prepares env for a command to be run in a
index cd7ee236a120bc99d91ec615e94a6cd4240937f0..4dc61b3a78a2916d737edf613af0f9c0e03d39c8 100644 (file)
@@ -303,6 +303,8 @@ int parse_submodule_fetchjobs(const char *var, const char *value)
        int fetchjobs = git_config_int(var, value);
        if (fetchjobs < 0)
                die(_("negative values not allowed for submodule.fetchJobs"));
+       if (!fetchjobs)
+               fetchjobs = online_cpus();
        return fetchjobs;
 }
 
index bf7a2c79183e17eb3b6c4c8487938de6c01be565..f7c71f1f4b12504dc3082fc6d10210337cf02791 100644 (file)
@@ -1819,6 +1819,17 @@ int fetch_submodules(struct repository *r,
 {
        int i;
        struct submodule_parallel_fetch spf = SPF_INIT;
+       const struct run_process_parallel_opts opts = {
+               .tr2_category = "submodule",
+               .tr2_label = "parallel/fetch",
+
+               .processes = max_parallel_jobs,
+
+               .get_next_task = get_next_submodule,
+               .start_failure = fetch_start_failure,
+               .task_finished = fetch_finish,
+               .data = &spf,
+       };
 
        spf.r = r;
        spf.command_line_option = command_line_option;
@@ -1840,12 +1851,7 @@ int fetch_submodules(struct repository *r,
 
        calculate_changed_submodule_paths(r, &spf.changed_submodule_names);
        string_list_sort(&spf.changed_submodule_names);
-       run_processes_parallel_tr2(max_parallel_jobs,
-                                  get_next_submodule,
-                                  fetch_start_failure,
-                                  fetch_finish,
-                                  &spf,
-                                  "submodule", "parallel/fetch");
+       run_processes_parallel(&opts);
 
        if (spf.submodules_with_errors.len > 0)
                fprintf(stderr, _("Errors during submodule fetch:\n%s"),
index c9283b47afafdccf67fa6784c877518a404c868f..3ecb830f4a8cd196f20ff0c371108c8f5579f3cd 100644 (file)
@@ -136,7 +136,7 @@ static const char * const testsuite_usage[] = {
 static int testsuite(int argc, const char **argv)
 {
        struct testsuite suite = TESTSUITE_INIT;
-       int max_jobs = 1, i, ret;
+       int max_jobs = 1, i, ret = 0;
        DIR *dir;
        struct dirent *d;
        struct option options[] = {
@@ -152,6 +152,12 @@ static int testsuite(int argc, const char **argv)
                         "write JUnit-style XML files"),
                OPT_END()
        };
+       struct run_process_parallel_opts opts = {
+               .get_next_task = next_test,
+               .start_failure = test_failed,
+               .task_finished = test_finished,
+               .data = &suite,
+       };
 
        argc = parse_options(argc, argv, NULL, options,
                        testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);
@@ -192,8 +198,8 @@ static int testsuite(int argc, const char **argv)
        fprintf(stderr, "Running %"PRIuMAX" tests (%d at a time)\n",
                (uintmax_t)suite.tests.nr, max_jobs);
 
-       ret = run_processes_parallel(max_jobs, next_test, test_failed,
-                                    test_finished, &suite);
+       opts.processes = max_jobs;
+       run_processes_parallel(&opts);
 
        if (suite.failed.nr > 0) {
                ret = 1;
@@ -206,7 +212,7 @@ static int testsuite(int argc, const char **argv)
        string_list_clear(&suite.tests, 0);
        string_list_clear(&suite.failed, 0);
 
-       return !!ret;
+       return ret;
 }
 
 static uint64_t my_random_next = 1234;
@@ -381,13 +387,17 @@ int cmd__run_command(int argc, const char **argv)
 {
        struct child_process proc = CHILD_PROCESS_INIT;
        int jobs;
+       int ret;
+       struct run_process_parallel_opts opts = {
+               .data = &proc,
+       };
 
        if (argc > 1 && !strcmp(argv[1], "testsuite"))
-               exit(testsuite(argc - 1, argv + 1));
+               return testsuite(argc - 1, argv + 1);
        if (!strcmp(argv[1], "inherited-handle"))
-               exit(inherit_handle(argv[0]));
+               return inherit_handle(argv[0]);
        if (!strcmp(argv[1], "inherited-handle-child"))
-               exit(inherit_handle_child());
+               return inherit_handle_child();
 
        if (argc >= 2 && !strcmp(argv[1], "quote-stress-test"))
                return !!quote_stress_test(argc - 1, argv + 1);
@@ -404,41 +414,52 @@ int cmd__run_command(int argc, const char **argv)
                argv += 2;
                argc -= 2;
        }
-       if (argc < 3)
-               return 1;
+       if (argc < 3) {
+               ret = 1;
+               goto cleanup;
+       }
        strvec_pushv(&proc.args, (const char **)argv + 2);
 
        if (!strcmp(argv[1], "start-command-ENOENT")) {
-               if (start_command(&proc) < 0 && errno == ENOENT)
-                       return 0;
+               if (start_command(&proc) < 0 && errno == ENOENT) {
+                       ret = 0;
+                       goto cleanup;
+               }
                fprintf(stderr, "FAIL %s\n", argv[1]);
                return 1;
        }
-       if (!strcmp(argv[1], "run-command"))
-               exit(run_command(&proc));
+       if (!strcmp(argv[1], "run-command")) {
+               ret = run_command(&proc);
+               goto cleanup;
+       }
 
        if (!strcmp(argv[1], "--ungroup")) {
                argv += 1;
                argc -= 1;
-               run_processes_parallel_ungroup = 1;
+               opts.ungroup = 1;
        }
 
        jobs = atoi(argv[2]);
        strvec_clear(&proc.args);
        strvec_pushv(&proc.args, (const char **)argv + 3);
 
-       if (!strcmp(argv[1], "run-command-parallel"))
-               exit(run_processes_parallel(jobs, parallel_next,
-                                           NULL, NULL, &proc));
-
-       if (!strcmp(argv[1], "run-command-abort"))
-               exit(run_processes_parallel(jobs, parallel_next,
-                                           NULL, task_finished, &proc));
-
-       if (!strcmp(argv[1], "run-command-no-jobs"))
-               exit(run_processes_parallel(jobs, no_job,
-                                           NULL, task_finished, &proc));
-
-       fprintf(stderr, "check usage\n");
-       return 1;
+       if (!strcmp(argv[1], "run-command-parallel")) {
+               opts.get_next_task = parallel_next;
+       } else if (!strcmp(argv[1], "run-command-abort")) {
+               opts.get_next_task = parallel_next;
+               opts.task_finished = task_finished;
+       } else if (!strcmp(argv[1], "run-command-no-jobs")) {
+               opts.get_next_task = no_job;
+               opts.task_finished = task_finished;
+       } else {
+               ret = 1;
+               fprintf(stderr, "check usage\n");
+               goto cleanup;
+       }
+       opts.processes = jobs;
+       run_processes_parallel(&opts);
+       ret = 0;
+cleanup:
+       child_process_clear(&proc);
+       return ret;
 }
index 3c44f1961220b376a0156f020588788ab986e131..75da8acf8f436f5a50908f8b3a9e3fe194d1d440 100755 (executable)
@@ -715,7 +715,13 @@ test_expect_success 'fetching submodules respects parallel settings' '
                GIT_TRACE=$(pwd)/trace.out git fetch &&
                grep "8 tasks" trace.out &&
                GIT_TRACE=$(pwd)/trace.out git fetch --jobs 9 &&
-               grep "9 tasks" trace.out
+               grep "9 tasks" trace.out &&
+               >trace.out &&
+
+               GIT_TRACE=$(pwd)/trace.out git -c submodule.fetchJobs=0 fetch &&
+               grep "preparing to run up to [0-9]* tasks" trace.out &&
+               ! grep "up to 0 tasks" trace.out &&
+               >trace.out
        )
 '