On Thu, Nov 03 2022, Glen Choo wrote: > Ævar Arnfjörð Bjarmason <avarab@xxxxxxxxx> writes: > [...] >> + struct option options[] = { >> + OPT_SUBCOMMAND("clone", &fn, module_clone), >> + OPT_SUBCOMMAND("add", &fn, module_add), >> + OPT_SUBCOMMAND("update", &fn, module_update), >> + OPT_SUBCOMMAND("foreach", &fn, module_foreach), >> + OPT_SUBCOMMAND("init", &fn, module_init), >> + OPT_SUBCOMMAND("status", &fn, module_status), >> + OPT_SUBCOMMAND("sync", &fn, module_sync), >> + OPT_SUBCOMMAND("deinit", &fn, module_deinit), >> + OPT_SUBCOMMAND("summary", &fn, module_summary), >> + OPT_SUBCOMMAND("push-check", &fn, push_check), >> + OPT_SUBCOMMAND("absorbgitdirs", &fn, absorb_git_dirs), >> + OPT_SUBCOMMAND("set-url", &fn, module_set_url), >> + OPT_SUBCOMMAND("set-branch", &fn, module_set_branch), >> + OPT_SUBCOMMAND("create-branch", &fn, module_create_branch), >> + OPT_END() >> + }; >> + argc = parse_options(argc, argv, prefix, options, usage, 0); >> + subcmd = argv[0]; >> + >> + if (strcmp(subcmd, "clone") && strcmp(subcmd, "update") && >> + strcmp(subcmd, "foreach") && strcmp(subcmd, "status") && >> + strcmp(subcmd, "sync") && strcmp(subcmd, "absorbgitdirs") && >> + get_super_prefix()) >> + /* >> + * xstrfmt() rather than "%s %s" to keep the translated >> + * string identical to git.c's. >> + */ >> + die(_("%s doesn't support --super-prefix"), >> + xstrfmt("'%s %s'", cmd, subcmd)); > > FYI I'm preparing a series to get rid of the SUPPORT_SUPER_PREFIX checks > in both the top level and in submodule--helper (i.e. revisiting my > complaints from [1]), but I haven't sent it out yet because I haven't > found the right way to motivate that change. Feel free to chime in on > that series when it comes out. > > [1] https://lore.kernel.org/git/20220630221147.45689-5-chooglen@xxxxxxxxxx/ Maybe you have different plans, but keep at the WIP re-roll of what I have after this, I've also removed all of that. Basically, ending up with: --- a/builtin.h +++ b/builtin.h @@ -224,7 +224,14 @@ int cmd_sparse_checkout(int argc, const char **argv, const char *prefix); int cmd_status(int argc, const char **argv, const char *prefix); int cmd_stash(int argc, const char **argv, const char *prefix); int cmd_stripspace(int argc, const char **argv, const char *prefix); +int cmd_submodule(int argc, const char **argv, const char *prefix); int cmd_submodule__helper(int argc, const char **argv, const char *prefix); +int cmd_submodule__helper_clone(int argc, const char **argv, const char *prefix); +int cmd_submodule_absorbgitdirs(int argc, const char **argv, const char *prefix); +int cmd_submodule_foreach(int argc, const char **argv, const char *prefix); +int cmd_submodule_status(int argc, const char **argv, const char *prefix); +int cmd_submodule_sync(int argc, const char **argv, const char *prefix); +int cmd_submodule_update(int argc, const char **argv, const char *prefix); int cmd_switch(int argc, const char **argv, const char *prefix); int cmd_symbolic_ref(int argc, const char **argv, const char *prefix); int cmd_tag(int argc, const char **argv, const char *prefix); And changes like: @@ -366,7 +365,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item, strvec_pushl(&cpr.args, "--super-prefix", NULL); strvec_pushf(&cpr.args, "%s/", displaypath); - strvec_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive", + strvec_pushl(&cpr.args, "submodule--helper-foreach", "--recursive", NULL); if (info->quiet) I.e. when we call "foreach" we dispatch to cmd_submodule_foreach(), but when "foreach" needs to recurse it doesn't invoke a "git submodule foreach", instead it invokes "git submodule--helper-foreach". The reason for doing that is that we can't promote the helper to a built-in without also leaking implementation detail that we support the now internal-only --super-prefix in the command itself. So this code becomes: @@ -3352,43 +3304,17 @@ static int module_add(int argc, const char **argv, const char *prefix) int cmd_submodule__helper(int argc, const char **argv, const char *prefix) { - const char *cmd = argv[0]; - const char *subcmd; parse_opt_subcommand_fn *fn = NULL; const char *const usage[] = { N_("git submodule--helper <command>"), NULL }; struct option options[] = { - OPT_SUBCOMMAND("clone", &fn, module_clone), - OPT_SUBCOMMAND("add", &fn, module_add), - OPT_SUBCOMMAND("update", &fn, module_update), - OPT_SUBCOMMAND("foreach", &fn, module_foreach), - OPT_SUBCOMMAND("init", &fn, module_init), - OPT_SUBCOMMAND("status", &fn, module_status), - OPT_SUBCOMMAND("sync", &fn, module_sync), - OPT_SUBCOMMAND("deinit", &fn, module_deinit), - OPT_SUBCOMMAND("summary", &fn, module_summary), - OPT_SUBCOMMAND("push-check", &fn, push_check), - OPT_SUBCOMMAND("absorbgitdirs", &fn, absorb_git_dirs), - OPT_SUBCOMMAND("set-url", &fn, module_set_url), - OPT_SUBCOMMAND("set-branch", &fn, module_set_branch), - OPT_SUBCOMMAND("create-branch", &fn, module_create_branch), + OPT_SUBCOMMAND("push-check", &fn, cmd_submodule_push_check), + OPT_SUBCOMMAND("create-branch", &fn, cmd_submodule_create_branch), OPT_END() }; argc = parse_options(argc, argv, prefix, options, usage, 0); - subcmd = argv[0]; - - if (strcmp(subcmd, "clone") && strcmp(subcmd, "update") && - strcmp(subcmd, "foreach") && strcmp(subcmd, "status") && - strcmp(subcmd, "sync") && strcmp(subcmd, "absorbgitdirs") && - get_super_prefix()) - /* - * xstrfmt() rather than "%s %s" to keep the translated - * string identical to git.c's. - */ - die(_("%s doesn't support --super-prefix"), - xstrfmt("'%s %s'", cmd, subcmd)); return fn(argc, argv, prefix); } I.e. for all the "super-prefix" ones we dispatch directly (and maybe I should just do that too for those two stragglers). It's ugly, but it's only ugly on the inside, but if you can think of a better way to do it...