From: Guillaume Galeazzi <guillaume.galeazzi@xxxxxxxxx> On a repository with some submodules not active, one may need to run a command only for an active submodule or vice-versa. To achieve this, one may use: git submodule foreach 'git -C $toplevel submodule--helper is-active \ $sm_path && pwd || :' Simplify this expression to make it more readable and easy-to-use by adding the flat `--[no-]active` to subcommand `foreach` of `git submodule`. Thus, simplifying the above command to: git submodule--helper foreach --active pwd Signed-off-by: Guillaume Galeazzi <guillaume.galeazzi@xxxxxxxxx> --- builtin/submodule--helper.c | 33 +++++++++++++++++++++++++++------ t/t7407-submodule-foreach.sh | 30 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 1a4b391c882..4b17e3b3b11 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -450,13 +450,16 @@ struct foreach_cb { const char *prefix; int quiet; int recursive; + int active_only; }; -#define FOREACH_CB_INIT { 0 } -static void runcommand_in_submodule_cb(const struct cache_entry *list_item, - void *cb_data) +#define FOREACH_BOOL_FILTER_NOT_SET -1 + +#define FOREACH_CB_INIT { .active_only=FOREACH_BOOL_FILTER_NOT_SET } + +static void runcommand_in_submodule(const struct cache_entry *list_item, + struct foreach_cb *info) { - struct foreach_cb *info = cb_data; const char *path = list_item->name; const struct object_id *ce_oid = &list_item->oid; @@ -555,6 +558,22 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item, free(displaypath); } +static void runcommand_in_submodule_filtered_cb(const struct cache_entry *list_item, + void *cb_data) +{ + const char *path = list_item->name; + struct foreach_cb *info = cb_data; + int is_active; + + if (info->active_only != FOREACH_BOOL_FILTER_NOT_SET) { + is_active = is_submodule_active(the_repository, path); + if (is_active != info->active_only) + return; + } + + runcommand_in_submodule(list_item, info); +} + static int module_foreach(int argc, const char **argv, const char *prefix) { struct foreach_cb info = FOREACH_CB_INIT; @@ -565,11 +584,13 @@ static int module_foreach(int argc, const char **argv, const char *prefix) OPT__QUIET(&info.quiet, N_("Suppress output of entering each submodule command")), OPT_BOOL(0, "recursive", &info.recursive, N_("Recurse into nested submodules")), + OPT_BOOL(0, "active", &info.active_only, + N_("Call command depending on submodule active state")), OPT_END() }; const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper foreach [--quiet] [--recursive] [--] <command>"), + N_("git submodule--helper foreach [--quiet] [--recursive] [--[no-]active] [--] <command>"), NULL }; @@ -583,7 +604,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix) info.argv = argv; info.prefix = prefix; - for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info); + for_each_listed_submodule(&list, runcommand_in_submodule_filtered_cb, &info); return 0; } diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index 6b2aa917e11..57c5ae70c8d 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -80,6 +80,36 @@ test_expect_success 'test basic "submodule foreach" usage' ' test_i18ncmp expect actual ' +cat > expect <<EOF +Entering 'sub3' +$pwd/clone-foo3-sub3-$sub3sha1 +EOF + +test_expect_success 'test "submodule--helper foreach --active" usage' ' + test_when_finished "git -C clone config --unset submodule.foo1.active" && + ( + cd clone && + git config --bool submodule.foo1.active "false" && + git submodule--helper foreach --active "echo \$toplevel-\$name-\$path-\$sha1" > ../actual + ) && + test_i18ncmp expect actual +' + +cat > expect <<EOF +Entering 'sub1' +$pwd/clone-foo1-sub1-$sub1sha1 +EOF + +test_expect_success 'test "submodule--helper foreach --no-active" usage' ' + test_when_finished "git -C clone config --unset submodule.foo1.active" && + ( + cd clone && + git config --bool submodule.foo1.active "false" && + git submodule--helper foreach --no-active "echo \$toplevel-\$name-\$path-\$sha1" > ../actual + ) && + test_i18ncmp expect actual +' + cat >expect <<EOF Entering '../sub1' $pwd/clone-foo1-sub1-../sub1-$sub1sha1 -- gitgitgadget