git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH/RFC] Changing submodule foreach --recursive to be depth-first, --parent option to execute command in supermodule as well

From
ECEric Cousineau <eacousineau@gmail.com>
Date
Mar 4, 2013, 08:41 UTC
Message-ID
<CA+aSAWuoxZkSnRybhefnFr9ngs3tHmt6hAH4o0ebjYKvjJ-vpw@mail.gmail.com>

In this patch, foreach --recursive acts depth-first, much like the default behavior described in the patch by Imram Yousuf in this post <http://marc.info/?l=git&m=121066084508631&w=2>. Changes were made so that the submodule "Entering ..." message was right next to the output generated by the command too. It also adds the --parent option for executing the command in the supermodule as well.

I began by adding a --depth option, to preserve the original --recursive behavior, and the --parent option, and trying to get that to work. However, I pretty much confused myself for a while trying to straighten that out, so I just ended up modifying the --recursive behavior. If the --recursive behavior should be preserved, I could add the --depth option back and only have --parent affect non-recursive and --depth recursive behavior.

I had kind-of implemented this behavior with aliases / bash functions (posted to pastebin <http://pastebin.com/yLHe9XWy> , spurned by a question I asked in StackOverflow <http://stackoverflow.com/q/14846967/170413>), however I would always run into issues with escaping characters when passing from the bash functions to git aliases (i.e., putting "'ello" as an test commit message). I also tried out mb14's method from the StackOverflow post, but I ran into the same issues. Figured the best way to avoid that was to cut out the extra layers.

I've attached a test script to generate the tree that VonC suggested with output showing the iteration.

From 851d65fcfb8f49131428a57fc318af7b56416430 Mon Sep 17 00:00:00 2001
From: eacousineau <eacousineau@gmail.com>
Date: Mon, 4 Mar 2013 01:08:07 -0600
Subject: [PATCH] area: submodules Make foreach --recursive do depth-first.
 Make foreach --parent [--recursive] execute command in toplevel supermodule
Signed-off-by: Eric Cousineau <eacousineau@gmail.com>
---
 git-submodule.sh | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/git-submodule.sh b/git-submodule.sh
index 004c034..721c959 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -434,6 +434,9 @@ Use -f if you really want to add it." >&2
 cmd_foreach()
 {
 	# parse $args after "submodule ... foreach".
+	# Gratuitous local's to prevent recursive bleeding
+	local parent=
+	local recursive=
 	while test $# -ne 0
 	do
 		case "$1" in
@@ -443,6 +446,10 @@ cmd_foreach()
 		--recursive)
 			recursive=1
 			;;
+		--parent)
+			# Execute command in parent, after children commands are executed
+			parent=1
+			;;
 		-*)
 			usage
 			;;
@@ -464,8 +471,8 @@ cmd_foreach()
 	do
 		die_if_unmatched "$mode"
 		if test -e "$sm_path"/.git
-		then
-			say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
+		then 
+			local message="$(eval_gettext "Entering '\$prefix\$sm_path'")"
 			name=$(module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
@@ -473,15 +480,29 @@ cmd_foreach()
 				# we make $path available to scripts ...
 				path=$sm_path
 				cd "$sm_path" &&
-				eval "$@" &&
 				if test -n "$recursive"
 				then
 					cmd_foreach "--recursive" "$@"
-				fi
+				fi &&
+				(
+					# Put message here so it stays somewhat tidy -- hopefully OK since prefixes are included
+					say "$message"
+					eval "$@"
+				)
 			) <&3 3<&- ||
 			die "$(eval_gettext "Stopping at '\$sm_path'; script returned non-zero status.")"
 		fi
-	done
+	done &&
+	(
+		if test -n "$parent"
+		then
+			name=$(basename "$toplevel")
+			clear_local_git_env
+			path=.
+			say "$(eval_gettext "Entering '\$name'")" # Not sure of proper thing here
+			eval "$@" || die "$(eval_gettext "Stopping at supermodule; script returned non-zero status.")"
+		fi
+	)
 }
 
 #
-- 
1.8.2.rc1.24.g06d67b8
Next: Jens Lehmann
Message 1 of 25 in “Changing submodule foreach --recursive to be depth-first, --parent option to execute command in supermodule as well”
  1. Changing submodule foreach --recursive to be depth-first, --parent option to execute command in supermodule as wellEric Cousineau, Mar 4, 2013
  2. Jens LehmannMar 4, 2013
  3. Junio C HamanoMar 4, 2013
  4. Eric CousineauMar 5, 2013
  5. Heiko VoigtMar 5, 2013
  6. Junio C HamanoMar 5, 2013
  7. Eric CousineauMar 5, 2013
  8. Junio C HamanoMar 5, 2013
  9. Jens LehmannMar 5, 2013
  10. Phil HordMar 5, 2013
  11. Jens LehmannMar 9, 2013
  12. Heiko VoigtMar 11, 2013
  13. Phil HordMar 12, 2013
  14. Eric CousineauMar 14, 2013
  15. Jens LehmannMar 18, 2013
  16. Eric CousineauMar 26, 2013
  17. Jens LehmannApr 2, 2013
  18. submodule foreach: Added in --post-order=<command> and adjusted code per Jens Lehmann's suggestionseacousineau, Apr 13, 2013
  19. Jens LehmannApr 14, 2013
  20. Jens LehmannMar 18, 2013
  21. Eric CousineauMar 26, 2013
  22. Eric CousineauMar 26, 2013
  23. Junio C HamanoMar 26, 2013
  24. Junio C HamanoMar 26, 2013
  25. Eric CousineauApr 13, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.