diff mbox series

[v2,3/3] submodule--helper.c: add branch to foreach

Message ID 65504cb780a3a596163d8c8a3b39cb208380de72.1589697023.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series submodule--helper.c: add only-active to foreach | expand

Commit Message

Johannes Schindelin via GitGitGadget May 17, 2020, 6:30 a.m. UTC
From: Guillaume Galeazzi <guillaume.galeazzi@gmail.com>

On a repository with some submodules tracking different branch, one
may need to run a command only for submodule tracking one of specified
branch. This change, add flags `-b <branch>` and --branch <branch>` to
subcommand `foreach` of `git submodule--helper`.

Signed-off-by: Guillaume Galeazzi <guillaume.galeazzi@gmail.com>
---
 builtin/submodule--helper.c  | 21 +++++++++++++++++++--
 t/t7407-submodule-foreach.sh | 15 +++++++++++++++
 2 files changed, 34 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index eb17e8c5293..066d1974605 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -452,11 +452,13 @@  struct foreach_cb {
 	int recursive;
 	int active_only;
 	int populated_only;
+	struct string_list remote_branch_filter;
 };
 
 #define FOREACH_BOOL_FILTER_NOT_SET -1
 
-#define FOREACH_CB_INIT { .active_only = FOREACH_BOOL_FILTER_NOT_SET, .populated_only = 1 }
+#define FOREACH_CB_INIT { .active_only = FOREACH_BOOL_FILTER_NOT_SET, \
+	.populated_only = 1, .remote_branch_filter = STRING_LIST_INIT_NODUP }
 
 static void runcommand_in_submodule(const struct cache_entry *list_item,
 				    struct foreach_cb *info)
@@ -555,12 +557,15 @@  static void runcommand_in_submodule(const struct cache_entry *list_item,
 	free(displaypath);
 }
 
+static const char *remote_submodule_branch(const char *path);
+
 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;
+	const char *branch;
 
 	if (info->active_only != FOREACH_BOOL_FILTER_NOT_SET) {
 		is_active = is_submodule_active(the_repository, path);
@@ -571,6 +576,14 @@  static void runcommand_in_submodule_filtered_cb(const struct cache_entry *list_i
 	if (info->populated_only != is_submodule_populated_gently(path, NULL))
 		return;
 
+	if (info->remote_branch_filter.nr) {
+		branch = remote_submodule_branch(path);
+		if (!branch)
+			return;
+		if (!unsorted_string_list_has_string(&info->remote_branch_filter, branch))
+			return;
+	}
+
 	runcommand_in_submodule(list_item, info);
 }
 
@@ -588,11 +601,13 @@  static int module_foreach(int argc, const char **argv, const char *prefix)
 			 N_("Call command depending on submodule active state")),
 		OPT_BOOL(0, "populated", &info.populated_only,
 			 N_("Call command depending on submodule populated state")),
+		OPT_STRING_LIST('b', "branch", &info.remote_branch_filter,
+			 N_("branch"), N_("Call command only if submodule remote branch is one of <branch> given")),
 		OPT_END()
 	};
 
 	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper foreach [--quiet] [--recursive] [--[no-]active] [--[no-]populated] [--] <command>"),
+		N_("git submodule--helper foreach [--quiet] [--recursive] [--[no-]active] [--[no-]populated] [-b|--branch <branch>] [--] <command>"),
 		NULL
 	};
 
@@ -608,6 +623,8 @@  static int module_foreach(int argc, const char **argv, const char *prefix)
 
 	for_each_listed_submodule(&list, runcommand_in_submodule_filtered_cb, &info);
 
+	string_list_clear(&info.remote_branch_filter, 0);
+
 	return 0;
 }
 
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index be6cd80d464..2da19ac54ce 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -125,6 +125,21 @@  test_expect_success 'test "submodule--helper foreach --no-active" usage' '
 	test_i18ncmp expect actual
 '
 
+cat > expect <<EOF
+Entering 'sub1'
+$pwd/clone-foo1-sub1-$sub1sha1
+EOF
+
+test_expect_success 'test "submodule--helper foreach --branch" usage' '
+	test_when_finished "git -C clone config  -f .gitmodules --unset submodule.foo1.branch" &&
+	(
+		cd clone &&
+		git config -f .gitmodules --add submodule.foo1.branch test &&
+		git submodule--helper foreach --branch test "echo \$toplevel-\$name-\$path-\$sha1" > ../actual
+	) &&
+	test_i18ncmp expect actual
+'
+
 cat >expect <<EOF
 Entering '../sub1'
 $pwd/clone-foo1-sub1-../sub1-$sub1sha1