Our tests scream at this patch, it's just to show what I plan to do. Essentially moving the content of the loop into the get_next_task callback from the run_processes_parallel. Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> --- builtin/submodule--helper.c | 181 +++++++++++++++++++++++++++++--------------- 1 file changed, 119 insertions(+), 62 deletions(-) diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index fa8c008..c66aa53 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -289,65 +289,40 @@ static void fill_clone_command(struct child_process *cp, int quiet, argv_array_push(&cp->args, depth); } -static int module_list_or_clone(int argc, const char **argv, const char *prefix) -{ - int i; - int quiet; - char *reference = NULL, *depth = NULL; - char *update = NULL; +struct submodule_list_or_clone { struct pathspec pathspec; - struct module_list list = MODULE_LIST_INIT; - struct string_list projectlines = STRING_LIST_INIT_DUP; - struct string_list_item *item; - - struct option module_list_options[] = { - OPT_STRING(0, "prefix", &prefix, - N_("path"), - N_("alternative anchor for relative paths")), - OPT_STRING(0, "update", &update, - N_("string"), - N_("update command for submodules")), - OPT_STRING(0, "reference", &reference, "<repository>", - N_("Use the local reference repository " - "instead of a full clone")), - OPT_STRING(0, "depth", &depth, "<depth>", - N_("Create a shallow clone truncated to the " - "specified number of revisions")), - OPT__QUIET(&quiet, N_("do't print cloning progress")), - OPT_END() - }; - - const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper list [--prefix=<path>] [<path>...]"), - NULL - }; - - argc = parse_options(argc, argv, prefix, module_list_options, - git_submodule_helper_usage, 0); - - if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) { - printf("#unmatched\n"); - return 1; - } + struct module_list list; + struct string_list projectlines; + int count; + int quiet; + char *reference; + char *depth; + char *update; + char *env_prefix; + const char *prefix; + int print_unmatched; +}; - gitmodules_config(); - /* Overlay the parsed .gitmodules file with .git/config */ - git_config(git_submodule_config, NULL); +static int get_next_task(void **pp_task_cb, + struct child_process *cp, + struct strbuf *err, + void *pp_cb) +{ + struct submodule_list_or_clone *pp = pp_cb; - for (i = 0; i < list.nr; i++) { + for (; pp->count < pp->list.nr; pp->count++) { const struct submodule *sub = NULL; const char *displaypath = NULL; - const struct cache_entry *ce = list.entries[i]; + const struct cache_entry *ce = pp->list.entries[pp->count]; struct strbuf sb = STRBUF_INIT; const char *update_module = NULL; const char *url = NULL; int just_cloned = 0; - char *env_prefix = getenv("prefix"); if (ce_stage(ce)) { - if (env_prefix) + if (pp->env_prefix) fprintf(stderr, "Skipping unmerged submodule %s/%s\n", - env_prefix, ce->name); + pp->env_prefix, ce->name); else fprintf(stderr, "Skipping unmerged submodule %s\n", ce->name); @@ -355,13 +330,13 @@ static int module_list_or_clone(int argc, const char **argv, const char *prefix) } sub = submodule_from_path(null_sha1, ce->name); - if (env_prefix) - displaypath = relative_path(env_prefix, ce->name, &sb); + if (pp->env_prefix) + displaypath = relative_path(pp->env_prefix, ce->name, &sb); else displaypath = ce->name; - if (update) - update_module = update; + if (pp->update) + update_module = pp->update; if (!update_module) update_module = sub->update; if (!update_module) @@ -385,7 +360,7 @@ static int module_list_or_clone(int argc, const char **argv, const char *prefix) * Only mention uninitialized submodules when its * path have been specified */ - if (pathspec.nr) + if (pp->pathspec.nr) fprintf(stderr, _("Submodule path '%s' not initialized\n" "Maybe you want to use 'update --init'?"), displaypath); continue; @@ -396,23 +371,105 @@ static int module_list_or_clone(int argc, const char **argv, const char *prefix) just_cloned = !file_exists(sb.buf); if (just_cloned) { - struct child_process cp = CHILD_PROCESS_INIT; - fill_clone_command(&cp, quiet, prefix, ce->name, - sub->name, url, reference, depth); - - if (run_command(&cp)) { - printf("#unmatched\n"); - return 1; - } + fill_clone_command(cp, pp->quiet, pp->prefix, ce->name, + sub->name, url, pp->reference, pp->depth); + return 1; } strbuf_reset(&sb); strbuf_addf(&sb, "%06o %s %d %d\t%s\n", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce), just_cloned, ce->name); - string_list_append(&projectlines, sb.buf); + string_list_append(&pp->projectlines, sb.buf); + } + return 0; +} + +static int start_failure(struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void *pp_task_cb) +{ + struct submodule_list_or_clone *pp = pp_cb; + + pp->print_unmatched = 1; + + return 1; +} + +static int task_finished(int result, + struct child_process *cp, + struct strbuf *err, + void *pp_cb, + void *pp_task_cb) +{ + struct submodule_list_or_clone *pp = pp_cb; + + if (!result) + return 0; + else { + pp->print_unmatched = 1; + return 1; + } +} + +static int module_list_or_clone(int argc, const char **argv, const char *prefix) +{ + struct submodule_list_or_clone pp; + struct string_list_item *item; + + struct option module_list_options[] = { + OPT_STRING(0, "prefix", &pp.prefix, + N_("path"), + N_("alternative anchor for relative paths")), + OPT_STRING(0, "update", &pp.update, + N_("string"), + N_("update command for submodules")), + OPT_STRING(0, "reference", &pp.reference, "<repository>", + N_("Use the local reference repository " + "instead of a full clone")), + OPT_STRING(0, "depth", &pp.depth, "<depth>", + N_("Create a shallow clone truncated to the " + "specified number of revisions")), + OPT__QUIET(&pp.quiet, N_("do't print cloning progress")), + OPT_END() + }; + + const char *const git_submodule_helper_usage[] = { + N_("git submodule--helper list [--prefix=<path>] [<path>...]"), + NULL + }; + + pp.prefix = NULL; + pp.list.entries = NULL; + pp.list.alloc = 0; + pp.list.nr = 0; + string_list_init(&pp.projectlines, 1); + pp.count = 0; + pp.reference = NULL; + pp.depth = NULL; + pp.update = NULL; + pp.env_prefix = getenv("prefix"); + pp.print_unmatched = 0; + + argc = parse_options(argc, argv, prefix, module_list_options, + git_submodule_helper_usage, 0); + + if (module_list_compute(argc, argv, pp.prefix, &pp.pathspec, &pp.list) < 0) { + printf("#unmatched\n"); + return 1; + } + + gitmodules_config(); + /* Overlay the parsed .gitmodules file with .git/config */ + git_config(git_submodule_config, NULL); + + run_processes_parallel(1, get_next_task, start_failure, task_finished, &pp); + if (pp.print_unmatched) { + printf("#unmatched\n"); + return 1; } - for_each_string_list_item(item, &projectlines) { + for_each_string_list_item(item, &pp.projectlines) { utf8_fprintf(stdout, "%s", item->string); } return 0; -- 2.5.0.277.gfdc362b.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html