git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling
@ 2009-08-19  1:45 Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 1/6] git submodule: Cleanup usage string and add option parsing to cmd_foreach() Johan Herland
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19  1:45 UTC (permalink / raw)
  To: git; +Cc: Johan Herland, gitster, mlevedahl, hjemli

Hi,

This patch series attempts to expand 'git submodule' command in two
regards:

1. Clean up, selftest, and enhance the 'git submodule foreach' command.
2. Provide better handling for nested submodules where the user want to
   operate on _all_ submodules simultenously.

The first 3 patches in the series are fairly trivial and straightforward.
The last 3 patches are slightly more RFC in nature, although their
implementation is still fairly straighforward.

Patch 3/6 is a resend of a patch that I sent stand-alone on 2009-08-16.


Have fun! :)

...Johan


Johan Herland (6):
  git submodule: Cleanup usage string and add option parsing to cmd_foreach()
  Add selftest for 'git submodule foreach'
  git submodule foreach: Provide access to submodule name, as '$name'
  git submodule foreach: Add --recursive to recurse into nested submodules
  git submodule update: Introduce --recursive to update nested submodules
  git submodule status: Add --recursive to recurse into nested submodules

 Documentation/git-submodule.txt |   23 ++++-
 git-submodule.sh                |   79 ++++++++++++--
 t/t7407-submodule-foreach.sh    |  223 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 313 insertions(+), 12 deletions(-)
 create mode 100755 t/t7407-submodule-foreach.sh

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC/PATCH 1/6] git submodule: Cleanup usage string and add option parsing to cmd_foreach()
  2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
@ 2009-08-19  1:45 ` Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 2/6] Add selftest for 'git submodule foreach' Johan Herland
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19  1:45 UTC (permalink / raw)
  To: git; +Cc: Johan Herland, gitster, mlevedahl, hjemli

Signed-off-by: Johan Herland <johan@herland.net>
---
 git-submodule.sh |   28 +++++++++++++++++++++++++---
 1 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 9bdd6ea..c58eca4 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -4,9 +4,14 @@
 #
 # Copyright (c) 2007 Lars Hjemli
 
-USAGE="[--quiet] [--cached|--files] \
-[add [-b branch] <repo> <path>]|[status|init|update [-i|--init] [-N|--no-fetch] [--rebase|--merge]|summary [-n|--summary-limit <n>] [<commit>]] \
-[--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
+dashless=$(basename "$0" | sed -e 's/-/ /')
+USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> <path>
+   or: $dashless [--quiet] status [--cached] [--] [<path>...]
+   or: $dashless [--quiet] init [--] [<path>...]
+   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--] [<path>...]
+   or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
+   or: $dashless [--quiet] foreach <command>
+   or: $dashless [--quiet] sync [--] [<path>...]"
 OPTIONS_SPEC=
 . git-sh-setup
 . git-parse-remote
@@ -238,6 +243,23 @@ cmd_add()
 #
 cmd_foreach()
 {
+	# parse $args after "submodule ... foreach".
+	while test $# -ne 0
+	do
+		case "$1" in
+		-q|--quiet)
+			GIT_QUIET=1
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
 	module_list |
 	while read mode sha1 stage path
 	do
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC/PATCH 2/6] Add selftest for 'git submodule foreach'
  2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 1/6] git submodule: Cleanup usage string and add option parsing to cmd_foreach() Johan Herland
@ 2009-08-19  1:45 ` Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 3/6] git submodule foreach: Provide access to submodule name, as '$name' Johan Herland
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19  1:45 UTC (permalink / raw)
  To: git; +Cc: Johan Herland, gitster, mlevedahl, hjemli

The selftest verifies that:
- only checked out submodules are visited by 'git submodule foreach'
- the $path, and $sha1 variables are set correctly for each submodule

Signed-off-by: Johan Herland <johan@herland.net>
---
 t/t7407-submodule-foreach.sh |   79 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 79 insertions(+), 0 deletions(-)
 create mode 100755 t/t7407-submodule-foreach.sh

diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
new file mode 100755
index 0000000..76e0734
--- /dev/null
+++ b/t/t7407-submodule-foreach.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Johan Herland
+#
+
+test_description='Test "git submodule foreach"
+
+This test verifies that "git submodule foreach" correctly visits all submodules
+that are currently checked out.
+'
+
+. ./test-lib.sh
+
+
+test_expect_success 'setup a submodule tree' '
+	echo file > file &&
+	git add file &&
+	test_tick &&
+	git commit -m upstream
+	git clone . super &&
+	git clone super submodule &&
+	(
+		cd super &&
+		git submodule add ../submodule sub1 &&
+		git submodule add ../submodule sub2 &&
+		git submodule add ../submodule sub3 &&
+		git config -f .gitmodules --rename-section \
+			submodule.sub1 submodule.foo1 &&
+		git config -f .gitmodules --rename-section \
+			submodule.sub2 submodule.foo2 &&
+		git config -f .gitmodules --rename-section \
+			submodule.sub3 submodule.foo3 &&
+		git add .gitmodules
+		test_tick &&
+		git commit -m "submodules" &&
+		git submodule init sub1 &&
+		git submodule init sub2 &&
+		git submodule init sub3
+	) &&
+	(
+		cd submodule &&
+		echo different > file &&
+		git add file &&
+		test_tick &&
+		git commit -m "different"
+	) &&
+	(
+		cd super &&
+		(
+			cd sub3 &&
+			git pull
+		) &&
+		git add sub3 &&
+		test_tick &&
+		git commit -m "update sub3"
+	)
+'
+
+sub1sha1=$(cd super/sub1 && git rev-parse HEAD)
+sub3sha1=$(cd super/sub3 && git rev-parse HEAD)
+
+cat > expect <<EOF
+Entering 'sub1'
+sub1-$sub1sha1
+Entering 'sub3'
+sub3-$sub3sha1
+EOF
+
+test_expect_success 'test basic "submodule foreach" usage' '
+	git clone super clone &&
+	(
+		cd clone &&
+		git submodule update --init -- sub1 sub3 &&
+		git submodule foreach "echo \$path-\$sha1" > ../actual
+	) &&
+	test_cmp expect actual
+'
+
+test_done
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC/PATCH 3/6] git submodule foreach: Provide access to submodule name, as '$name'
  2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 1/6] git submodule: Cleanup usage string and add option parsing to cmd_foreach() Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 2/6] Add selftest for 'git submodule foreach' Johan Herland
@ 2009-08-19  1:45 ` Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 4/6] git submodule foreach: Add --recursive to recurse into nested submodules Johan Herland
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19  1:45 UTC (permalink / raw)
  To: git; +Cc: Johan Herland, gitster, mlevedahl, hjemli

The argument to 'git submodule foreach' already has access to the variables
'$path' (the path to the submodule, relative to the superproject) and '$sha1'
(the submodule commit recorded by the superproject).

This patch adds another variable - '$name' - which contains the name of the
submodule, as recorded in the superproject's .gitmodules file.

Verification of the behaviour of '$name' is also added to the git submodule
foreach selftest.

Signed-off-by: Johan Herland <johan@herland.net>
---

This patch was initially sent stand-alone on 2009-08-16.


...Johan


 Documentation/git-submodule.txt |    3 ++-
 git-submodule.sh                |    1 +
 t/t7407-submodule-foreach.sh    |    6 +++---
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index bb7d159..cfa8d73 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -135,7 +135,8 @@ summary::
 
 foreach::
 	Evaluates an arbitrary shell command in each checked out submodule.
-	The command has access to the variables $path and $sha1:
+	The command has access to the variables $name, $path and $sha1:
+	$name is the name of the relevant submodule section in .gitmodules,
 	$path is the name of the submodule directory relative to the
 	superproject, and $sha1 is the commit as recorded in the superproject.
 	Any submodules defined in the superproject but not checked out are
diff --git a/git-submodule.sh b/git-submodule.sh
index c58eca4..6163d01 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -266,6 +266,7 @@ cmd_foreach()
 		if test -e "$path"/.git
 		then
 			say "Entering '$path'"
+			name=$(module_name "$path")
 			(cd "$path" && eval "$@") ||
 			die "Stopping at '$path'; script returned non-zero status."
 		fi
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 76e0734..991aa80 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -61,9 +61,9 @@ sub3sha1=$(cd super/sub3 && git rev-parse HEAD)
 
 cat > expect <<EOF
 Entering 'sub1'
-sub1-$sub1sha1
+foo1-sub1-$sub1sha1
 Entering 'sub3'
-sub3-$sub3sha1
+foo3-sub3-$sub3sha1
 EOF
 
 test_expect_success 'test basic "submodule foreach" usage' '
@@ -71,7 +71,7 @@ test_expect_success 'test basic "submodule foreach" usage' '
 	(
 		cd clone &&
 		git submodule update --init -- sub1 sub3 &&
-		git submodule foreach "echo \$path-\$sha1" > ../actual
+		git submodule foreach "echo \$name-\$path-\$sha1" > ../actual
 	) &&
 	test_cmp expect actual
 '
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC/PATCH 4/6] git submodule foreach: Add --recursive to recurse into nested submodules
  2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
                   ` (2 preceding siblings ...)
  2009-08-19  1:45 ` [RFC/PATCH 3/6] git submodule foreach: Provide access to submodule name, as '$name' Johan Herland
@ 2009-08-19  1:45 ` Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 5/6] git submodule update: Introduce --recursive to update " Johan Herland
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19  1:45 UTC (permalink / raw)
  To: git; +Cc: Johan Herland, gitster, mlevedahl, hjemli

In very large and hierarchically structured projects, one may encounter
nested submodules. In these situations, it is valuable to not only operate
on all the submodules in the current repo (which is what is currently done
by 'git submodule foreach'), but also to operate on all submodules at all
levels (i.e. recursing into nested submodules as well).

This patch teaches the new --recursive option to the 'git submodule foreach'
command. The patch also includes documentation and selftests.

Signed-off-by: Johan Herland <johan@herland.net>
---
 Documentation/git-submodule.txt |   10 ++++-
 git-submodule.sh                |   19 ++++++-
 t/t7407-submodule-foreach.sh    |   99 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index cfa8d73..c604550 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -16,7 +16,7 @@ SYNOPSIS
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
 	      [--reference <repository>] [--merge] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
-'git submodule' [--quiet] foreach <command>
+'git submodule' [--quiet] foreach [--recursive] <command>
 'git submodule' [--quiet] sync [--] [<path>...]
 
 
@@ -142,6 +142,8 @@ foreach::
 	Any submodules defined in the superproject but not checked out are
 	ignored by this command. Unless given --quiet, foreach prints the name
 	of each submodule before evaluating the command.
+	If --recursive is given, submodules are traversed recursively (i.e.
+	the given shell command is evaluated in nested submodules as well).
 	A non-zero return from the command in any submodule causes
 	the processing to terminate. This can be overridden by adding '|| :'
 	to the end of the command.
@@ -219,6 +221,12 @@ OPTIONS
 *NOTE*: Do *not* use this option unless you have read the note
 for linkgit:git-clone[1]'s --reference and --shared options carefully.
 
+--recursive::
+	This option is only valid for the foreach command.
+	Traverse submodules recursively. The operation is performed not
+	only in the submodules of the current repo, but also
+	in any nested submodules inside those submodules (and so on).
+
 <path>...::
 	Paths to submodule(s). When specified this will restrict the command
 	to only operate on the submodules found at the specified paths.
diff --git a/git-submodule.sh b/git-submodule.sh
index 6163d01..dbfc483 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -10,7 +10,7 @@ USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> <p
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--] [<path>...]
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
-   or: $dashless [--quiet] foreach <command>
+   or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--] [<path>...]"
 OPTIONS_SPEC=
 . git-sh-setup
@@ -24,6 +24,7 @@ cached=
 files=
 nofetch=
 update=
+prefix=
 
 # Resolve relative url by appending to parent's url
 resolve_relative_url ()
@@ -250,6 +251,9 @@ cmd_foreach()
 		-q|--quiet)
 			GIT_QUIET=1
 			;;
+		--recursive)
+			recursive=1
+			;;
 		-*)
 			usage
 			;;
@@ -265,9 +269,18 @@ cmd_foreach()
 	do
 		if test -e "$path"/.git
 		then
-			say "Entering '$path'"
+			say "Entering '$prefix$path'"
 			name=$(module_name "$path")
-			(cd "$path" && eval "$@") ||
+			(
+				prefix="$prefix$path/"
+				unset GIT_DIR
+				cd "$path" &&
+				eval "$@" &&
+				if test -n "$recursive"
+				then
+					cmd_foreach "--recursive" "$@"
+				fi
+			) ||
 			die "Stopping at '$path'; script returned non-zero status."
 		fi
 	done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 991aa80..be122c7 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -76,4 +76,103 @@ test_expect_success 'test basic "submodule foreach" usage' '
 	test_cmp expect actual
 '
 
+test_expect_success 'setup nested submodules' '
+	git clone submodule nested1 &&
+	git clone submodule nested2 &&
+	git clone submodule nested3 &&
+	(
+		cd nested3 &&
+		git submodule add ../submodule submodule &&
+		test_tick &&
+		git commit -m "submodule" &&
+		git submodule init submodule
+	) &&
+	(
+		cd nested2 &&
+		git submodule add ../nested3 nested3 &&
+		test_tick &&
+		git commit -m "nested3" &&
+		git submodule init nested3
+	) &&
+	(
+		cd nested1 &&
+		git submodule add ../nested2 nested2 &&
+		test_tick &&
+		git commit -m "nested2" &&
+		git submodule init nested2
+	) &&
+	(
+		cd super &&
+		git submodule add ../nested1 nested1 &&
+		test_tick &&
+		git commit -m "nested1" &&
+		git submodule init nested1
+	)
+'
+
+test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' '
+	git clone super clone2 &&
+	(
+		cd clone2 &&
+		test ! -d sub1/.git &&
+		test ! -d sub2/.git &&
+		test ! -d sub3/.git &&
+		test ! -d nested1/.git &&
+		git submodule update --init &&
+		test -d sub1/.git &&
+		test -d sub2/.git &&
+		test -d sub3/.git &&
+		test -d nested1/.git &&
+		test ! -d nested1/nested2/.git &&
+		git submodule foreach "git submodule update --init" &&
+		test -d nested1/nested2/.git &&
+		test ! -d nested1/nested2/nested3/.git
+	)
+'
+
+test_expect_success 'use "foreach --recursive" to checkout all submodules' '
+	(
+		cd clone2 &&
+		git submodule foreach --recursive "git submodule update --init" &&
+		test -d nested1/nested2/nested3/.git &&
+		test -d nested1/nested2/nested3/submodule/.git
+	)
+'
+
+cat > expect <<EOF
+Entering 'nested1'
+Entering 'nested1/nested2'
+Entering 'nested1/nested2/nested3'
+Entering 'nested1/nested2/nested3/submodule'
+Entering 'sub1'
+Entering 'sub2'
+Entering 'sub3'
+EOF
+
+test_expect_success 'test messages from "foreach --recursive"' '
+	(
+		cd clone2 &&
+		git submodule foreach --recursive "true" > ../actual
+	) &&
+	test_cmp expect actual
+'
+
+cat > expect <<EOF
+nested1-nested1
+nested2-nested2
+nested3-nested3
+submodule-submodule
+foo1-sub1
+foo2-sub2
+foo3-sub3
+EOF
+
+test_expect_success 'test "foreach --quiet --recursive"' '
+	(
+		cd clone2 &&
+		git submodule foreach -q --recursive "echo \$name-\$path" > ../actual
+	) &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC/PATCH 5/6] git submodule update: Introduce --recursive to update nested submodules
  2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
                   ` (3 preceding siblings ...)
  2009-08-19  1:45 ` [RFC/PATCH 4/6] git submodule foreach: Add --recursive to recurse into nested submodules Johan Herland
@ 2009-08-19  1:45 ` Johan Herland
  2009-08-19  1:45 ` [RFC/PATCH 6/6] git submodule status: Add --recursive to recurse into " Johan Herland
  2009-08-19 23:07 ` [RFC/PATCH 7/6] git clone: Add --recursive to automatically checkout (nested) submodules Johan Herland
  6 siblings, 0 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19  1:45 UTC (permalink / raw)
  To: git; +Cc: Johan Herland, gitster, mlevedahl, hjemli

In very large and hierarchically structured projects, one may encounter
nested submodules. In these situations, it is valuable to not only update
the submodules in the current repo (which is what is currently done by
'git submodule update'), but also to operate on all submodules at all
levels (i.e. recursing into nested submodules as well).

This patch teaches the new --recursive option to the 'git submodule update'
command. The patch also includes documentation and selftests.

Signed-off-by: Johan Herland <johan@herland.net>
---
 Documentation/git-submodule.txt |    7 +++++--
 git-submodule.sh                |   13 ++++++++++++-
 t/t7407-submodule-foreach.sh    |   19 +++++++++++++++++++
 3 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index c604550..cd74da9 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -14,7 +14,7 @@ SYNOPSIS
 'git submodule' [--quiet] status [--cached] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
-	      [--reference <repository>] [--merge] [--] [<path>...]
+	      [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
 'git submodule' [--quiet] foreach [--recursive] <command>
 'git submodule' [--quiet] sync [--] [<path>...]
@@ -122,6 +122,9 @@ update::
 If the submodule is not yet initialized, and you just want to use the
 setting as stored in .gitmodules, you can automatically initialize the
 submodule with the --init option.
++
+If '--recursive' is specified, this command will recurse into the
+registered submodules, and update any nested submodules within.
 
 summary::
 	Show commit summary between the given commit (defaults to HEAD) and
@@ -222,7 +225,7 @@ OPTIONS
 for linkgit:git-clone[1]'s --reference and --shared options carefully.
 
 --recursive::
-	This option is only valid for the foreach command.
+	This option is only valid for foreach and update commands.
 	Traverse submodules recursively. The operation is performed not
 	only in the submodules of the current repo, but also
 	in any nested submodules inside those submodules (and so on).
diff --git a/git-submodule.sh b/git-submodule.sh
index dbfc483..e48c309 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> <path>
    or: $dashless [--quiet] status [--cached] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
-   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--] [<path>...]
+   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--] [<path>...]"
@@ -353,6 +353,7 @@ cmd_init()
 cmd_update()
 {
 	# parse $args after "submodule ... update".
+	orig_args="$@"
 	while test $# -ne 0
 	do
 		case "$1" in
@@ -385,6 +386,10 @@ cmd_update()
 			shift
 			update="merge"
 			;;
+		--recursive)
+			shift
+			recursive=1
+			;;
 		--)
 			shift
 			break
@@ -471,6 +476,12 @@ cmd_update()
 			die "Unable to $action '$sha1' in submodule path '$path'"
 			say "Submodule path '$path': $msg '$sha1'"
 		fi
+
+		if test -n "$recursive"
+		then
+			(unset GIT_DIR; cd "$path" && cmd_update $orig_args) ||
+			die "Failed to recurse into submodule path '$path'"
+		fi
 	done
 }
 
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index be122c7..9122bfe 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -175,4 +175,23 @@ test_expect_success 'test "foreach --quiet --recursive"' '
 	test_cmp expect actual
 '
 
+test_expect_success 'use "update --recursive" to checkout all submodules' '
+	git clone super clone3 &&
+	(
+		cd clone3 &&
+		test ! -d sub1/.git &&
+		test ! -d sub2/.git &&
+		test ! -d sub3/.git &&
+		test ! -d nested1/.git &&
+		git submodule update --init --recursive &&
+		test -d sub1/.git &&
+		test -d sub2/.git &&
+		test -d sub3/.git &&
+		test -d nested1/.git &&
+		test -d nested1/nested2/.git &&
+		test -d nested1/nested2/nested3/.git &&
+		test -d nested1/nested2/nested3/submodule/.git
+	)
+'
+
 test_done
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC/PATCH 6/6] git submodule status: Add --recursive to recurse into nested submodules
  2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
                   ` (4 preceding siblings ...)
  2009-08-19  1:45 ` [RFC/PATCH 5/6] git submodule update: Introduce --recursive to update " Johan Herland
@ 2009-08-19  1:45 ` Johan Herland
  2009-08-19 23:07 ` [RFC/PATCH 7/6] git clone: Add --recursive to automatically checkout (nested) submodules Johan Herland
  6 siblings, 0 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19  1:45 UTC (permalink / raw)
  To: git; +Cc: Johan Herland, gitster, mlevedahl, hjemli

In very large and hierarchically structured projects, one may encounter
nested submodules. In these situations, it is valuable to not only show
status for all the submodules in the current repo (which is what is
currently done by 'git submodule status'), but also to show status for
all submodules at all levels (i.e. recursing into nested submodules as
well).

This patch teaches the new --recursive option to the 'git submodule status'
command. The patch also includes documentation and selftests.

Signed-off-by: Johan Herland <johan@herland.net>
---
 Documentation/git-submodule.txt |    7 +++++--
 git-submodule.sh                |   24 ++++++++++++++++++++----
 t/t7407-submodule-foreach.sh    |   26 ++++++++++++++++++++++++++
 3 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index cd74da9..5ccdd18 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -11,7 +11,7 @@ SYNOPSIS
 [verse]
 'git submodule' [--quiet] add [-b branch]
 	      [--reference <repository>] [--] <repository> <path>
-'git submodule' [--quiet] status [--cached] [--] [<path>...]
+'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
 	      [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
@@ -100,6 +100,9 @@ status::
 	initialized and `+` if the currently checked out submodule commit
 	does not match the SHA-1 found in the index of the containing
 	repository. This command is the default command for 'git-submodule'.
++
+If '--recursive' is specified, this command will recurse into nested
+submodules, and show their status as well.
 
 init::
 	Initialize the submodules, i.e. register each submodule name
@@ -225,7 +228,7 @@ OPTIONS
 for linkgit:git-clone[1]'s --reference and --shared options carefully.
 
 --recursive::
-	This option is only valid for foreach and update commands.
+	This option is only valid for foreach, update and status commands.
 	Traverse submodules recursively. The operation is performed not
 	only in the submodules of the current repo, but also
 	in any nested submodules inside those submodules (and so on).
diff --git a/git-submodule.sh b/git-submodule.sh
index e48c309..bfbd36b 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -6,7 +6,7 @@
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> <path>
-   or: $dashless [--quiet] status [--cached] [--] [<path>...]
+   or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
@@ -703,6 +703,7 @@ cmd_summary() {
 cmd_status()
 {
 	# parse $args after "submodule ... status".
+	orig_args="$@"
 	while test $# -ne 0
 	do
 		case "$1" in
@@ -712,6 +713,9 @@ cmd_status()
 		--cached)
 			cached=1
 			;;
+		--recursive)
+			recursive=1
+			;;
 		--)
 			shift
 			break
@@ -731,22 +735,34 @@ cmd_status()
 	do
 		name=$(module_name "$path") || exit
 		url=$(git config submodule."$name".url)
+		displaypath="$prefix$path"
 		if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
 		then
-			say "-$sha1 $path"
+			say "-$sha1 $displaypath"
 			continue;
 		fi
 		set_name_rev "$path" "$sha1"
 		if git diff-files --quiet -- "$path"
 		then
-			say " $sha1 $path$revname"
+			say " $sha1 $displaypath$revname"
 		else
 			if test -z "$cached"
 			then
 				sha1=$(unset GIT_DIR; cd "$path" && git rev-parse --verify HEAD)
 				set_name_rev "$path" "$sha1"
 			fi
-			say "+$sha1 $path$revname"
+			say "+$sha1 $displaypath$revname"
+		fi
+
+		if test -n "$recursive"
+		then
+			(
+				prefix="$displaypath/"
+				unset GIT_DIR
+				cd "$path" &&
+				cmd_status $orig_args
+			) ||
+			die "Failed to recurse into submodule path '$path'"
 		fi
 	done
 }
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 9122bfe..de1730d 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -194,4 +194,30 @@ test_expect_success 'use "update --recursive" to checkout all submodules' '
 	)
 '
 
+nested1sha1=$(cd clone3/nested1 && git rev-parse HEAD)
+nested2sha1=$(cd clone3/nested1/nested2 && git rev-parse HEAD)
+nested3sha1=$(cd clone3/nested1/nested2/nested3 && git rev-parse HEAD)
+submodulesha1=$(cd clone3/nested1/nested2/nested3/submodule && git rev-parse HEAD)
+sub1sha1=$(cd clone3/sub1 && git rev-parse HEAD)
+sub2sha1=$(cd clone3/sub2 && git rev-parse HEAD)
+sub3sha1=$(cd clone3/sub3 && git rev-parse HEAD)
+
+cat > expect <<EOF
+ $nested1sha1 nested1 (heads/master)
+ $nested2sha1 nested1/nested2 (heads/master)
+ $nested3sha1 nested1/nested2/nested3 (heads/master)
+ $submodulesha1 nested1/nested2/nested3/submodule (heads/master)
+ $sub1sha1 sub1 (${sub1sha1:0:7})
+ $sub2sha1 sub2 (${sub1sha1:0:7})
+ $sub3sha1 sub3 (heads/master)
+EOF
+
+test_expect_success 'test "status --recursive"' '
+	(
+		cd clone3 &&
+		git submodule status --recursive > ../actual
+	) &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC/PATCH 7/6] git clone: Add --recursive to automatically checkout (nested) submodules
  2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
                   ` (5 preceding siblings ...)
  2009-08-19  1:45 ` [RFC/PATCH 6/6] git submodule status: Add --recursive to recurse into " Johan Herland
@ 2009-08-19 23:07 ` Johan Herland
  6 siblings, 0 replies; 8+ messages in thread
From: Johan Herland @ 2009-08-19 23:07 UTC (permalink / raw)
  To: git; +Cc: gitster, johan, barkalow

Many projects using submodules expect all submodules to be checked out
in order to build/work correctly. A common command sequence for
developers on such projects is:

	git clone url/to/project
	cd project
	git submodule update --init (--recursive)

This patch introduces the --recursive option to git-clone. The new
option causes git-clone to recursively clone and checkout all
submodules of the cloned project. Hence, the above command sequence
can be reduced to:

	git clone --recursive url/to/project

--recursive is ignored if no checkout is done by the git-clone.

The patch also includes documentation and a selftest.

Signed-off-by: Johan Herland <johan@herland.net>
---

Hi,

It just hit me today that yesterday's patch series missed the last part
of the puzzle...

I'm not at all married to the '--recursive' name for this option, but
I wasn't able to think of anything better that wasn't too long.


Have fun! :)

...Johan


 Documentation/git-clone.txt  |   10 +++++++++-
 builtin-clone.c              |   11 ++++++++++-
 t/t7407-submodule-foreach.sh |   12 ++++++++++++
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 2c63a0f..88ea272 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -12,7 +12,7 @@ SYNOPSIS
 'git clone' [--template=<template_directory>]
 	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
 	  [-o <name>] [-u <upload-pack>] [--reference <repository>]
-	  [--depth <depth>] [--] <repository> [<directory>]
+	  [--depth <depth>] [--recursive] [--] <repository> [<directory>]
 
 DESCRIPTION
 -----------
@@ -147,6 +147,14 @@ objects from the source repository into a pack in the cloned repository.
 	with a long history, and would want to send in fixes
 	as patches.
 
+--recursive::
+	After the clone is created, initialize all submodules within,
+	using their default settings. This is equivalent to running
+	'git submodule update --init --recursive' immediately after
+	the clone is finished. This option is ignored if the cloned
+	repository does not have a worktree/checkout (i.e. if any of
+	`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)
+
 <repository>::
 	The (possibly remote) repository to clone from.  See the
 	<<URLS,URLS>> section below for more information on specifying
diff --git a/builtin-clone.c b/builtin-clone.c
index 32dea74..0d2b4a8 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -38,7 +38,7 @@ static const char * const builtin_clone_usage[] = {
 };
 
 static int option_quiet, option_no_checkout, option_bare, option_mirror;
-static int option_local, option_no_hardlinks, option_shared;
+static int option_local, option_no_hardlinks, option_shared, option_recursive;
 static char *option_template, *option_reference, *option_depth;
 static char *option_origin = NULL;
 static char *option_upload_pack = "git-upload-pack";
@@ -59,6 +59,8 @@ static struct option builtin_clone_options[] = {
 		    "don't use local hardlinks, always copy"),
 	OPT_BOOLEAN('s', "shared", &option_shared,
 		    "setup as shared repository"),
+	OPT_BOOLEAN(0, "recursive", &option_recursive,
+		    "setup as shared repository"),
 	OPT_STRING(0, "template", &option_template, "path",
 		   "path the template repository"),
 	OPT_STRING(0, "reference", &option_reference, "repo",
@@ -73,6 +75,10 @@ static struct option builtin_clone_options[] = {
 	OPT_END()
 };
 
+static const char *argv_submodule[] = {
+	"submodule", "update", "--init", "--recursive", NULL
+};
+
 static char *get_repo_path(const char *repo, int *is_bundle)
 {
 	static char *suffix[] = { "/.git", ".git", "" };
@@ -608,6 +614,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 		err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
 				sha1_to_hex(remote_head->old_sha1), "1", NULL);
+
+		if (!err && option_recursive)
+			err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
 	}
 
 	strbuf_release(&reflog_msg);
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index de1730d..25ec281 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -220,4 +220,16 @@ test_expect_success 'test "status --recursive"' '
 	test_cmp expect actual
 '
 
+test_expect_success 'use "git clone --recursive" to checkout all submodules' '
+	git clone --recursive super clone4 &&
+	test -d clone4/.git &&
+	test -d clone4/sub1/.git &&
+	test -d clone4/sub2/.git &&
+	test -d clone4/sub3/.git &&
+	test -d clone4/nested1/.git &&
+	test -d clone4/nested1/nested2/.git &&
+	test -d clone4/nested1/nested2/nested3/.git &&
+	test -d clone4/nested1/nested2/nested3/submodule/.git
+'
+
 test_done
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-08-19 23:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-19  1:45 [RFC/PATCH 0/6] Git submodule: 'foreach' enhancements and nested submodule handling Johan Herland
2009-08-19  1:45 ` [RFC/PATCH 1/6] git submodule: Cleanup usage string and add option parsing to cmd_foreach() Johan Herland
2009-08-19  1:45 ` [RFC/PATCH 2/6] Add selftest for 'git submodule foreach' Johan Herland
2009-08-19  1:45 ` [RFC/PATCH 3/6] git submodule foreach: Provide access to submodule name, as '$name' Johan Herland
2009-08-19  1:45 ` [RFC/PATCH 4/6] git submodule foreach: Add --recursive to recurse into nested submodules Johan Herland
2009-08-19  1:45 ` [RFC/PATCH 5/6] git submodule update: Introduce --recursive to update " Johan Herland
2009-08-19  1:45 ` [RFC/PATCH 6/6] git submodule status: Add --recursive to recurse into " Johan Herland
2009-08-19 23:07 ` [RFC/PATCH 7/6] git clone: Add --recursive to automatically checkout (nested) submodules Johan Herland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).