git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v4 0/6] submodule: drop the top-level requirement
@ 2013-06-16 14:18 John Keeping
  2013-06-16 14:18 ` [PATCH v4 1/6] t7401: make indentation consistent John Keeping
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: John Keeping @ 2013-06-16 14:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Nieder, Jens Lehmann, Johannes Sixt,
	John Keeping

Changes since v3:

* There are four new patches, three of which are style fixes for
  existing tests and one fixes an existing error message to return a
  more accurate path when recursing.

* You now cannot run "git submodule add <relative URL>" from a
  subdirectory.  Because the interpretation of the URL changes depending
  on whether or not remote.origin.url is configured, I have decided to
  just ban this for now.  If someone comes up with a sensible way to
  handle this then we can lift this restriction later.

* The "path" variable exported in "submodule foreach" now uses the
  relative path and matches the "sm_path" variable.

* I audited the code again and fixed a few more cases that weren't
  printing relative paths (notably "submodule init" and "submodule
  foreach").

* More tests.

John Keeping (6):
  t7401: make indentation consistent
  t7403: modernize style
  t7403: add missing && chaining
  submodule: show full path in error message
  rev-parse: add --prefix option
  submodule: drop the top-level requirement

 Documentation/git-rev-parse.txt |  16 ++
 builtin/rev-parse.c             |  24 ++-
 git-submodule.sh                | 135 ++++++++++----
 t/t1513-rev-parse-prefix.sh     |  96 ++++++++++
 t/t7400-submodule-basic.sh      |  80 +++++++++
 t/t7401-submodule-summary.sh    | 116 +++++++-----
 t/t7403-submodule-sync.sh       | 388 ++++++++++++++++++++++++++--------------
 t/t7406-submodule-update.sh     |  15 ++
 t/t7407-submodule-foreach.sh    |  16 ++
 9 files changed, 673 insertions(+), 213 deletions(-)
 create mode 100755 t/t1513-rev-parse-prefix.sh

-- 
1.8.3.779.g691e267

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

* [PATCH v4 1/6] t7401: make indentation consistent
  2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
@ 2013-06-16 14:18 ` John Keeping
  2013-06-16 14:18 ` [PATCH v4 2/6] t7403: modernize style John Keeping
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: John Keeping @ 2013-06-16 14:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Nieder, Jens Lehmann, Johannes Sixt,
	John Keeping

Only leading whitespace is changed in this patch.

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 t/t7401-submodule-summary.sh | 80 ++++++++++++++++++++++----------------------
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index 30b429e..c328726 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -76,8 +76,8 @@ head3=$(
 )
 
 test_expect_success 'modified submodule(backward)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head2...$head3 (2):
   < Add foo3
   < Add foo2
@@ -89,8 +89,8 @@ EOF
 head4=$(add_file sm1 foo4 foo5) &&
 head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD)
 test_expect_success 'modified submodule(backward and forward)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head2...$head4 (4):
   > Add foo5
   > Add foo4
@@ -102,15 +102,15 @@ EOF
 "
 
 test_expect_success '--summary-limit' "
-    git submodule summary -n 3 >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary -n 3 >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head2...$head4 (4):
   > Add foo5
   > Add foo4
   < Add foo3
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 commit_file sm1 &&
@@ -122,8 +122,8 @@ rm -f sm1 &&
 mv sm1-bak sm1
 
 test_expect_success 'typechanged submodule(submodule->blob), --cached' "
-    git submodule summary --cached >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary --cached >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head4(submodule)->$head5(blob) (3):
   < Add foo5
 
@@ -132,59 +132,59 @@ EOF
 "
 
 test_expect_success 'typechanged submodule(submodule->blob), --files' "
-    git submodule summary --files >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary --files >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head5(blob)->$head4(submodule) (3):
   > Add foo5
 
 EOF
-    test_i18ncmp actual expected
+	test_i18ncmp actual expected
 "
 
 rm -rf sm1 &&
 git checkout-index sm1
 test_expect_success 'typechanged submodule(submodule->blob)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head4(submodule)->$head5(blob):
 
 EOF
-    test_i18ncmp actual expected
+	test_i18ncmp actual expected
 "
 
 rm -f sm1 &&
 test_create_repo sm1 &&
 head6=$(add_file sm1 foo6 foo7)
 test_expect_success 'nonexistent commit' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head4...$head6:
   Warn: sm1 doesn't contain commit $head4_full
 
 EOF
-    test_i18ncmp actual expected
+	test_i18ncmp actual expected
 "
 
 commit_file
 test_expect_success 'typechanged submodule(blob->submodule)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head5(blob)->$head6(submodule) (2):
   > Add foo7
 
 EOF
-    test_i18ncmp expected actual
+	test_i18ncmp expected actual
 "
 
 commit_file sm1 &&
 rm -rf sm1
 test_expect_success 'deleted submodule' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head6...0000000:
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 test_create_repo sm2 &&
@@ -192,43 +192,43 @@ head7=$(add_file sm2 foo8 foo9) &&
 git add sm2
 
 test_expect_success 'multiple submodules' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head6...0000000:
 
 * sm2 0000000...$head7 (2):
   > Add foo9
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 test_expect_success 'path filter' "
-    git submodule summary sm2 >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary sm2 >actual &&
+	cat >expected <<-EOF &&
 * sm2 0000000...$head7 (2):
   > Add foo9
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 commit_file sm2
 test_expect_success 'given commit' "
-    git submodule summary HEAD^ >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary HEAD^ >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head6...0000000:
 
 * sm2 0000000...$head7 (2):
   > Add foo9
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 test_expect_success '--for-status' "
-    git submodule summary --for-status HEAD^ >actual &&
-    test_i18ncmp actual - <<EOF
+	git submodule summary --for-status HEAD^ >actual &&
+	test_i18ncmp actual - <<EOF
 # Submodule changes to be committed:
 #
 # * sm1 $head6...0000000:
@@ -240,14 +240,14 @@ EOF
 "
 
 test_expect_success 'fail when using --files together with --cached' "
-    test_must_fail git submodule summary --files --cached
+	test_must_fail git submodule summary --files --cached
 "
 
 test_expect_success 'should not fail in an empty repo' "
-    git init xyzzy &&
-    cd xyzzy &&
-    git submodule summary >output 2>&1 &&
-    test_cmp output /dev/null
+	git init xyzzy &&
+	cd xyzzy &&
+	git submodule summary >output 2>&1 &&
+	test_cmp output /dev/null
 "
 
 test_done
-- 
1.8.3.779.g691e267

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

* [PATCH v4 2/6] t7403: modernize style
  2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
  2013-06-16 14:18 ` [PATCH v4 1/6] t7401: make indentation consistent John Keeping
@ 2013-06-16 14:18 ` John Keeping
  2013-06-16 14:18 ` [PATCH v4 3/6] t7403: add missing && chaining John Keeping
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: John Keeping @ 2013-06-16 14:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Nieder, Jens Lehmann, Johannes Sixt,
	John Keeping

Change the indentation to use tabs consistently and start content on the
line after the paren opening a subshell.

Also don't put a space in ">file" and remove ":" from ": >file" to be
consistent with the majority of tests elsewhere.

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 t/t7403-submodule-sync.sh | 316 +++++++++++++++++++++++++++-------------------
 1 file changed, 183 insertions(+), 133 deletions(-)

diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index 94e26c4..38f6cc4 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,216 +11,266 @@ These tests exercise the "git submodule sync" subcommand.
 . ./test-lib.sh
 
 test_expect_success setup '
-	echo file > file &&
+	echo file >file &&
 	git add file &&
 	test_tick &&
 	git commit -m upstream &&
 	git clone . super &&
 	git clone super submodule &&
-	(cd submodule &&
-	 git submodule add ../submodule sub-submodule &&
-	 test_tick &&
-	 git commit -m "sub-submodule"
+	(
+		cd submodule &&
+		git submodule add ../submodule sub-submodule &&
+		test_tick &&
+		git commit -m "sub-submodule"
 	) &&
-	(cd super &&
-	 git submodule add ../submodule submodule &&
-	 test_tick &&
-	 git commit -m "submodule"
+	(
+		cd super &&
+		git submodule add ../submodule submodule &&
+		test_tick &&
+		git commit -m "submodule"
 	) &&
 	git clone super super-clone &&
-	(cd super-clone && git submodule update --init --recursive) &&
+	(
+		cd super-clone &&
+		git submodule update --init --recursive
+	) &&
 	git clone super empty-clone &&
-	(cd empty-clone && git submodule init) &&
+	(
+		cd empty-clone &&
+		git submodule init
+	) &&
 	git clone super top-only-clone &&
 	git clone super relative-clone &&
-	(cd relative-clone && git submodule update --init --recursive) &&
+	(
+		cd relative-clone &&
+		git submodule update --init --recursive
+	) &&
 	git clone super recursive-clone &&
-	(cd recursive-clone && git submodule update --init --recursive)
+	(
+		cd recursive-clone &&
+		git submodule update --init --recursive
+	)
 '
 
 test_expect_success 'change submodule' '
-	(cd submodule &&
-	 echo second line >> file &&
-	 test_tick &&
-	 git commit -a -m "change submodule"
+	(
+		cd submodule &&
+		echo second line >>file &&
+		test_tick &&
+		git commit -a -m "change submodule"
 	)
 '
 
 test_expect_success 'change submodule url' '
-	(cd super &&
-	 cd submodule &&
-	 git checkout master &&
-	 git pull
+	(
+		cd super &&
+		cd submodule &&
+		git checkout master &&
+		git pull
 	) &&
 	mv submodule moved-submodule &&
-	(cd moved-submodule &&
-	 git config -f .gitmodules submodule.sub-submodule.url ../moved-submodule &&
-	 test_tick &&
-	 git commit -a -m moved-sub-submodule
+	(
+		cd moved-submodule &&
+		git config -f .gitmodules submodule.sub-submodule.url ../moved-submodule &&
+		test_tick &&
+		git commit -a -m moved-sub-submodule
 	) &&
-	(cd super &&
-	 git config -f .gitmodules submodule.submodule.url ../moved-submodule &&
-	 test_tick &&
-	 git commit -a -m moved-submodule
+	(
+		cd super &&
+		git config -f .gitmodules submodule.submodule.url ../moved-submodule &&
+		test_tick &&
+		git commit -a -m moved-submodule
 	)
 '
 
 test_expect_success '"git submodule sync" should update submodule URLs' '
-	(cd super-clone &&
-	 git pull --no-recurse-submodules &&
-	 git submodule sync
+	(
+		cd super-clone &&
+		git pull --no-recurse-submodules &&
+		git submodule sync
 	) &&
-	test -d "$(cd super-clone/submodule &&
-	 git config remote.origin.url
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
 	)" &&
-	test ! -d "$(cd super-clone/submodule/sub-submodule &&
-	 git config remote.origin.url
+	test ! -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
 	)" &&
-	(cd super-clone/submodule &&
-	 git checkout master &&
-	 git pull
+	(
+		cd super-clone/submodule &&
+		git checkout master &&
+		git pull
 	) &&
-	(cd super-clone &&
-	 test -d "$(git config submodule.submodule.url)"
+	(
+		cd super-clone &&
+		test -d "$(git config submodule.submodule.url)"
 	)
 '
 
 test_expect_success '"git submodule sync --recursive" should update all submodule URLs' '
-	(cd super-clone &&
-	 (cd submodule &&
-	  git pull --no-recurse-submodules
-	 ) &&
-	 git submodule sync --recursive
+	(
+		cd super-clone &&
+		(
+			cd submodule &&
+			git pull --no-recurse-submodules
+		) &&
+		git submodule sync --recursive
 	) &&
-	test -d "$(cd super-clone/submodule &&
-	 git config remote.origin.url
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
 	)" &&
-	test -d "$(cd super-clone/submodule/sub-submodule &&
-	 git config remote.origin.url
+	test -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
 	)" &&
-	(cd super-clone/submodule/sub-submodule &&
-	 git checkout master &&
-	 git pull
+	(
+		cd super-clone/submodule/sub-submodule &&
+		git checkout master &&
+		git pull
 	)
 '
 
 test_expect_success '"git submodule sync" should update known submodule URLs' '
-	(cd empty-clone &&
-	 git pull &&
-	 git submodule sync &&
-	 test -d "$(git config submodule.submodule.url)"
+	(
+		cd empty-clone &&
+		git pull &&
+		git submodule sync &&
+		test -d "$(git config submodule.submodule.url)"
 	)
 '
 
 test_expect_success '"git submodule sync" should not vivify uninteresting submodule' '
-	(cd top-only-clone &&
-	 git pull &&
-	 git submodule sync &&
-	 test -z "$(git config submodule.submodule.url)" &&
-	 git submodule sync submodule &&
-	 test -z "$(git config submodule.submodule.url)"
+	(
+		cd top-only-clone &&
+		git pull &&
+		git submodule sync &&
+		test -z "$(git config submodule.submodule.url)" &&
+		git submodule sync submodule &&
+		test -z "$(git config submodule.submodule.url)"
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form foo' '
-	(cd relative-clone &&
-	 git remote set-url origin foo &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual fails with: "cannot strip off url foo
-	 test "$(git config remote.origin.url)" = "../submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin foo &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual fails with: "cannot strip off url foo
+			test "$(git config remote.origin.url)" = "../submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form foo/bar' '
-	(cd relative-clone &&
-	 git remote set-url origin foo/bar &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual foo/submodule
-	 test "$(git config remote.origin.url)" = "../foo/submodule"
-	)
-	(cd submodule/sub-submodule &&
-	 test "$(git config remote.origin.url)" != "../../foo/submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin foo/bar &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual foo/submodule
+			test "$(git config remote.origin.url)" = "../foo/submodule"
+		)
+		(
+			cd submodule/sub-submodule &&
+			test "$(git config remote.origin.url)" != "../../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync --recursive" propagates changes in origin' '
-	(cd recursive-clone &&
-	 git remote set-url origin foo/bar &&
-	 git submodule sync --recursive &&
-	(cd submodule &&
-	 #actual foo/submodule
-	 test "$(git config remote.origin.url)" = "../foo/submodule"
-	)
-	(cd submodule/sub-submodule &&
-	 test "$(git config remote.origin.url)" = "../../foo/submodule"
-	)
+	(
+		cd recursive-clone &&
+		git remote set-url origin foo/bar &&
+		git submodule sync --recursive &&
+		(
+			cd submodule &&
+			#actual foo/submodule
+			test "$(git config remote.origin.url)" = "../foo/submodule"
+		)
+		(
+			cd submodule/sub-submodule &&
+			test "$(git config remote.origin.url)" = "../../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ./foo' '
-	(cd relative-clone &&
-	 git remote set-url origin ./foo &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ./submodule
-	 test "$(git config remote.origin.url)" = "../submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ./foo &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ./submodule
+			test "$(git config remote.origin.url)" = "../submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ./foo/bar' '
-	(cd relative-clone &&
-	 git remote set-url origin ./foo/bar &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ./foo/submodule
-	 test "$(git config remote.origin.url)" = "../foo/submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ./foo/bar &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ./foo/submodule
+			test "$(git config remote.origin.url)" = "../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ../foo' '
-	(cd relative-clone &&
-	 git remote set-url origin ../foo &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ../submodule
-	 test "$(git config remote.origin.url)" = "../../submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ../foo &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ../submodule
+			test "$(git config remote.origin.url)" = "../../submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ../foo/bar' '
-	(cd relative-clone &&
-	 git remote set-url origin ../foo/bar &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ../foo/submodule
-	 test "$(git config remote.origin.url)" = "../../foo/submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ../foo/bar &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ../foo/submodule
+			test "$(git config remote.origin.url)" = "../../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ../foo/bar with deeply nested submodule' '
-	(cd relative-clone &&
-	 git remote set-url origin ../foo/bar &&
-	 mkdir -p a/b/c &&
-	 ( cd a/b/c &&
-	   git init &&
-	   :> .gitignore &&
-	   git add .gitignore &&
-	   test_tick &&
-	   git commit -m "initial commit" ) &&
-	 git submodule add ../bar/a/b/c ./a/b/c &&
-	 git submodule sync &&
-	(cd a/b/c &&
-	 #actual ../foo/bar/a/b/c
-	 test "$(git config remote.origin.url)" = "../../../../foo/bar/a/b/c"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ../foo/bar &&
+		mkdir -p a/b/c &&
+		(
+			cd a/b/c &&
+			git init &&
+			>.gitignore &&
+			git add .gitignore &&
+			test_tick &&
+			git commit -m "initial commit"
+		) &&
+		git submodule add ../bar/a/b/c ./a/b/c &&
+		git submodule sync &&
+		(
+			cd a/b/c &&
+			#actual ../foo/bar/a/b/c
+			test "$(git config remote.origin.url)" = "../../../../foo/bar/a/b/c"
+		)
 	)
 '
 
-- 
1.8.3.779.g691e267

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

* [PATCH v4 3/6] t7403: add missing && chaining
  2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
  2013-06-16 14:18 ` [PATCH v4 1/6] t7401: make indentation consistent John Keeping
  2013-06-16 14:18 ` [PATCH v4 2/6] t7403: modernize style John Keeping
@ 2013-06-16 14:18 ` John Keeping
  2013-06-16 14:18 ` [PATCH v4 4/6] submodule: show full path in error message John Keeping
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: John Keeping @ 2013-06-16 14:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Nieder, Jens Lehmann, Johannes Sixt,
	John Keeping

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 t/t7403-submodule-sync.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index 38f6cc4..bf90098 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -174,7 +174,7 @@ test_expect_success '"git submodule sync" handles origin URL of the form foo/bar
 			cd submodule &&
 			#actual foo/submodule
 			test "$(git config remote.origin.url)" = "../foo/submodule"
-		)
+		) &&
 		(
 			cd submodule/sub-submodule &&
 			test "$(git config remote.origin.url)" != "../../foo/submodule"
@@ -191,7 +191,7 @@ test_expect_success '"git submodule sync --recursive" propagates changes in orig
 			cd submodule &&
 			#actual foo/submodule
 			test "$(git config remote.origin.url)" = "../foo/submodule"
-		)
+		) &&
 		(
 			cd submodule/sub-submodule &&
 			test "$(git config remote.origin.url)" = "../../foo/submodule"
-- 
1.8.3.779.g691e267

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

* [PATCH v4 4/6] submodule: show full path in error message
  2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
                   ` (2 preceding siblings ...)
  2013-06-16 14:18 ` [PATCH v4 3/6] t7403: add missing && chaining John Keeping
@ 2013-06-16 14:18 ` John Keeping
  2013-06-16 14:18 ` [PATCH v4 5/6] rev-parse: add --prefix option John Keeping
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: John Keeping @ 2013-06-16 14:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Nieder, Jens Lehmann, Johannes Sixt,
	John Keeping

When --recursive was added to "submodule foreach" in commit 15fc56a (git
submodule foreach: Add --recursive to recurse into nested submodules,
2009-08-19), the error message when the script returns a non-zero status
was not updated to contain $prefix to show the full path.  Fix this.

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 git-submodule.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index 79bfaac..bdb438b 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -485,7 +485,7 @@ cmd_foreach()
 					cmd_foreach "--recursive" "$@"
 				fi
 			) <&3 3<&- ||
-			die "$(eval_gettext "Stopping at '\$sm_path'; script returned non-zero status.")"
+			die "$(eval_gettext "Stopping at '\$prefix\$sm_path'; script returned non-zero status.")"
 		fi
 	done
 }
-- 
1.8.3.779.g691e267

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

* [PATCH v4 5/6] rev-parse: add --prefix option
  2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
                   ` (3 preceding siblings ...)
  2013-06-16 14:18 ` [PATCH v4 4/6] submodule: show full path in error message John Keeping
@ 2013-06-16 14:18 ` John Keeping
  2013-06-16 14:18 ` [PATCH v4 6/6] submodule: drop the top-level requirement John Keeping
  2013-06-17 20:41 ` [PATCH v4 0/6] " Jens Lehmann
  6 siblings, 0 replies; 8+ messages in thread
From: John Keeping @ 2013-06-16 14:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Nieder, Jens Lehmann, Johannes Sixt,
	John Keeping

This makes 'git rev-parse' behave as if it were invoked from the
specified subdirectory of a repository, with the difference that any
file paths which it prints are prefixed with the full path from the top
of the working tree.

This is useful for shell scripts where we may want to cd to the top of
the working tree but need to handle relative paths given by the user on
the command line.

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 Documentation/git-rev-parse.txt | 16 +++++++
 builtin/rev-parse.c             | 24 ++++++++---
 t/t1513-rev-parse-prefix.sh     | 96 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+), 5 deletions(-)
 create mode 100755 t/t1513-rev-parse-prefix.sh

diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 947d62f..993903c 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -59,6 +59,22 @@ OPTIONS
 	If there is no parameter given by the user, use `<arg>`
 	instead.
 
+--prefix <arg>::
+	Behave as if 'git rev-parse' was invoked from the `<arg>`
+	subdirectory of the working tree.  Any relative filenames are
+	resolved as if they are prefixed by `<arg>` and will be printed
+	in that form.
++
+This can be used to convert arguments to a command run in a subdirectory
+so that they can still be used after moving to the top-level of the
+repository.  For example:
++
+----
+prefix=$(git rev-parse --show-prefix)
+cd "$(git rev-parse --show-toplevel)"
+eval "set -- $(git rev-parse --sq --prefix "$prefix" "$@")"
+----
+
 --verify::
 	Verify that exactly one parameter is provided, and that it
 	can be turned into a raw 20-byte SHA-1 that can be used to
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index f267a1d..de894c7 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -212,11 +212,17 @@ static void show_datestring(const char *flag, const char *datestr)
 	show(buffer);
 }
 
-static int show_file(const char *arg)
+static int show_file(const char *arg, int output_prefix)
 {
 	show_default();
 	if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) {
-		show(arg);
+		if (output_prefix) {
+			const char *prefix = startup_info->prefix;
+			show(prefix_filename(prefix,
+					     prefix ? strlen(prefix) : 0,
+					     arg));
+		} else
+			show(arg);
 		return 1;
 	}
 	return 0;
@@ -470,6 +476,7 @@ N_("git rev-parse --parseopt [options] -- [<args>...]\n"
 int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 {
 	int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
+	int output_prefix = 0;
 	unsigned char sha1[20];
 	const char *name = NULL;
 
@@ -503,7 +510,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 		const char *arg = argv[i];
 
 		if (as_is) {
-			if (show_file(arg) && as_is < 2)
+			if (show_file(arg, output_prefix) && as_is < 2)
 				verify_filename(prefix, arg, 0);
 			continue;
 		}
@@ -527,7 +534,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				as_is = 2;
 				/* Pass on the "--" if we show anything but files.. */
 				if (filter & (DO_FLAGS | DO_REVS))
-					show_file(arg);
+					show_file(arg, 0);
 				continue;
 			}
 			if (!strcmp(arg, "--default")) {
@@ -535,6 +542,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				i++;
 				continue;
 			}
+			if (!strcmp(arg, "--prefix")) {
+				prefix = argv[i+1];
+				startup_info->prefix = prefix;
+				output_prefix = 1;
+				i++;
+				continue;
+			}
 			if (!strcmp(arg, "--revs-only")) {
 				filter &= ~DO_NOREV;
 				continue;
@@ -754,7 +768,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 		if (verify)
 			die_no_single_rev(quiet);
 		as_is = 1;
-		if (!show_file(arg))
+		if (!show_file(arg, output_prefix))
 			continue;
 		verify_filename(prefix, arg, 1);
 	}
diff --git a/t/t1513-rev-parse-prefix.sh b/t/t1513-rev-parse-prefix.sh
new file mode 100755
index 0000000..87ec3ae
--- /dev/null
+++ b/t/t1513-rev-parse-prefix.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+test_description='Tests for rev-parse --prefix'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	mkdir -p sub1/sub2 &&
+	echo top >top &&
+	echo file1 >sub1/file1 &&
+	echo file2 >sub1/sub2/file2 &&
+	git add top sub1/file1 sub1/sub2/file2 &&
+	git commit -m commit
+'
+
+test_expect_success 'empty prefix -- file' '
+	git rev-parse --prefix "" -- top sub1/file1 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	top
+	sub1/file1
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix -- file' '
+	git rev-parse --prefix sub1/ -- file1 sub2/file2 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	sub1/file1
+	sub1/sub2/file2
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix -- ../file' '
+	git rev-parse --prefix sub1/ -- ../top sub2/file2 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	sub1/../top
+	sub1/sub2/file2
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'empty prefix HEAD:./path' '
+	git rev-parse --prefix "" HEAD:./top >actual &&
+	git rev-parse HEAD:top >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix HEAD:./path' '
+	git rev-parse --prefix sub1/ HEAD:./file1 >actual &&
+	git rev-parse HEAD:sub1/file1 >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix HEAD:../path' '
+	git rev-parse --prefix sub1/ HEAD:../top >actual &&
+	git rev-parse HEAD:top >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'prefix ignored with HEAD:top' '
+	git rev-parse --prefix sub1/ HEAD:top >actual &&
+	git rev-parse HEAD:top >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'disambiguate path with valid prefix' '
+	git rev-parse --prefix sub1/ file1 >actual &&
+	cat <<-\EOF >expected &&
+	sub1/file1
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'file and refs with prefix' '
+	git rev-parse --prefix sub1/ master file1 >actual &&
+	cat <<-EOF >expected &&
+	$(git rev-parse master)
+	sub1/file1
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'two-levels deep' '
+	git rev-parse --prefix sub1/sub2/ -- file2 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	sub1/sub2/file2
+	EOF
+	test_cmp expected actual
+'
+
+test_done
-- 
1.8.3.779.g691e267

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

* [PATCH v4 6/6] submodule: drop the top-level requirement
  2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
                   ` (4 preceding siblings ...)
  2013-06-16 14:18 ` [PATCH v4 5/6] rev-parse: add --prefix option John Keeping
@ 2013-06-16 14:18 ` John Keeping
  2013-06-17 20:41 ` [PATCH v4 0/6] " Jens Lehmann
  6 siblings, 0 replies; 8+ messages in thread
From: John Keeping @ 2013-06-16 14:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Nieder, Jens Lehmann, Johannes Sixt,
	John Keeping

Use the new rev-parse --prefix option to process all paths given to the
submodule command, dropping the requirement that it be run from the
top-level of the repository.

Since the interpretation of a relative submodule URL depends on whether
or not "remote.origin.url" is configured, explicitly block relative URLs
in "git submodule add" when not at the top level of the working tree.

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 git-submodule.sh             | 135 ++++++++++++++++++++++++++++++++-----------
 t/t7400-submodule-basic.sh   |  80 +++++++++++++++++++++++++
 t/t7401-submodule-summary.sh |  36 ++++++++++++
 t/t7403-submodule-sync.sh    |  72 +++++++++++++++++++++++
 t/t7406-submodule-update.sh  |  15 +++++
 t/t7407-submodule-foreach.sh |  16 +++++
 6 files changed, 319 insertions(+), 35 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index bdb438b..7756d81 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -14,10 +14,13 @@ USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
 OPTIONS_SPEC=
+SUBDIRECTORY_OK=Yes
 . git-sh-setup
 . git-sh-i18n
 . git-parse-remote
 require_work_tree
+wt_prefix=$(git rev-parse --show-prefix)
+cd_to_toplevel
 
 command=
 branch=
@@ -106,12 +109,48 @@ resolve_relative_url ()
 	echo "${is_relative:+${up_path}}${remoteurl#./}"
 }
 
+# Resolve a path to be relative to another path.  This is intended for
+# converting submodule paths when git-submodule is run in a subdirectory
+# and only handles paths where the directory separator is '/'.
+#
+# The output is the first argument as a path relative to the second argument,
+# which defaults to $wt_prefix if it is omitted.
+relative_path ()
+{
+	local target curdir result
+	target=$1
+	curdir=${2-$wt_prefix}
+	curdir=${curdir%/}
+	result=
+
+	while test -n "$curdir"
+	do
+		case "$target" in
+		"$curdir/"*)
+			target=${target#"$curdir"/}
+			break
+			;;
+		esac
+
+		result="${result}../"
+		if test "$curdir" = "${curdir%/*}"
+		then
+			curdir=
+		else
+			curdir="${curdir%/*}"
+		fi
+	done
+
+	echo "$result$target"
+}
+
 #
 # Get submodule info for registered submodules
 # $@ = path to limit submodule list
 #
 module_list()
 {
+	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
 	(
 		git ls-files --error-unmatch --stage -- "$@" ||
 		echo "unmatched pathspec exists"
@@ -282,6 +321,7 @@ isnumber()
 cmd_add()
 {
 	# parse $args after "submodule ... add".
+	reference_path=
 	while test $# -ne 0
 	do
 		case "$1" in
@@ -298,11 +338,11 @@ cmd_add()
 			;;
 		--reference)
 			case "$2" in '') usage ;; esac
-			reference="--reference=$2"
+			reference_path=$2
 			shift
 			;;
 		--reference=*)
-			reference="$1"
+			reference_path="${1#--reference=}"
 			;;
 		--name)
 			case "$2" in '') usage ;; esac
@@ -323,6 +363,14 @@ cmd_add()
 		shift
 	done
 
+	if test -n "$reference_path"
+	then
+		is_absolute_path "$reference_path" ||
+		reference_path="$wt_prefix$reference_path"
+
+		reference="--reference=$reference_path"
+	fi
+
 	repo=$1
 	sm_path=$2
 
@@ -335,9 +383,14 @@ cmd_add()
 		usage
 	fi
 
+	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
+
 	# assure repo is absolute or relative to parent
 	case "$repo" in
 	./*|../*)
+		test -z "$wt_prefix" ||
+		die "$(gettext "Relative path can only be used from the toplevel of the working tree")"
+
 		# dereference source url relative to parent's url
 		realrepo=$(resolve_relative_url "$repo") || exit
 		;;
@@ -471,21 +524,23 @@ cmd_foreach()
 		die_if_unmatched "$mode"
 		if test -e "$sm_path"/.git
 		then
-			say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
+			displaypath=$(relative_path "$sm_path")
+			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
 			name=$(module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
 				clear_local_git_env
-				# we make $path available to scripts ...
-				path=$sm_path
 				cd "$sm_path" &&
+				sm_path=$(relative_path "$sm_path") &&
+				# we make $path available to scripts ...
+				path=$sm_path &&
 				eval "$@" &&
 				if test -n "$recursive"
 				then
 					cmd_foreach "--recursive" "$@"
 				fi
 			) <&3 3<&- ||
-			die "$(eval_gettext "Stopping at '\$prefix\$sm_path'; script returned non-zero status.")"
+			die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
 		fi
 	done
 }
@@ -524,12 +579,14 @@ cmd_init()
 		die_if_unmatched "$mode"
 		name=$(module_name "$sm_path") || exit
 
+		displaypath=$(relative_path "$sm_path")
+
 		# Copy url setting when it is not set yet
 		if test -z "$(git config "submodule.$name.url")"
 		then
 			url=$(git config -f .gitmodules submodule."$name".url)
 			test -z "$url" &&
-			die "$(eval_gettext "No url found for submodule path '\$sm_path' in .gitmodules")"
+			die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")"
 
 			# Possibly a url relative to parent
 			case "$url" in
@@ -538,9 +595,9 @@ cmd_init()
 				;;
 			esac
 			git config submodule."$name".url "$url" ||
-			die "$(eval_gettext "Failed to register url for submodule path '\$sm_path'")"
+			die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")"
 
-			say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
+			say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")"
 		fi
 
 		# Copy "update" setting when it is not set yet
@@ -548,7 +605,7 @@ cmd_init()
 		test -z "$upd" ||
 		test -n "$(git config submodule."$name".update)" ||
 		git config submodule."$name".update "$upd" ||
-		die "$(eval_gettext "Failed to register update mode for submodule path '\$sm_path'")"
+		die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
 	done
 }
 
@@ -594,27 +651,29 @@ cmd_deinit()
 		die_if_unmatched "$mode"
 		name=$(module_name "$sm_path") || exit
 
+		displaypath=$(relative_path "$sm_path")
+
 		# Remove the submodule work tree (unless the user already did it)
 		if test -d "$sm_path"
 		then
 			# Protect submodules containing a .git directory
 			if test -d "$sm_path/.git"
 			then
-				echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")"
+				echo >&2 "$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")"
 				die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
 			fi
 
 			if test -z "$force"
 			then
 				git rm -qn "$sm_path" ||
-				die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
+				die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
 			fi
 			rm -rf "$sm_path" &&
-			say "$(eval_gettext "Cleared directory '\$sm_path'")" ||
-			say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")"
+			say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
+			say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
 		fi
 
-		mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")"
+		mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
 
 		# Remove the .git/config entries (unless the user already did it)
 		if test -n "$(git config --get-regexp submodule."$name\.")"
@@ -623,7 +682,7 @@ cmd_deinit()
 			# the user later decides to init this submodule again
 			url=$(git config submodule."$name".url)
 			git config --remove-section submodule."$name" 2>/dev/null &&
-			say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$sm_path'")"
+			say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
 		fi
 	done
 }
@@ -717,9 +776,11 @@ cmd_update()
 			update_module=$(git config submodule."$name".update)
 		fi
 
+		displaypath=$(relative_path "$prefix$sm_path")
+
 		if test "$update_module" = "none"
 		then
-			echo "Skipping submodule '$prefix$sm_path'"
+			echo "Skipping submodule '$displaypath'"
 			continue
 		fi
 
@@ -728,7 +789,7 @@ cmd_update()
 			# Only mention uninitialized submodules when its
 			# path have been specified
 			test "$#" != "0" &&
-			say "$(eval_gettext "Submodule path '\$prefix\$sm_path' not initialized
+			say "$(eval_gettext "Submodule path '\$displaypath' not initialized
 Maybe you want to use 'update --init'?")"
 			continue
 		fi
@@ -741,7 +802,7 @@ Maybe you want to use 'update --init'?")"
 		else
 			subsha1=$(clear_local_git_env; cd "$sm_path" &&
 				git rev-parse --verify HEAD) ||
-			die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")"
+			die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
 		fi
 
 		if test -n "$remote"
@@ -774,7 +835,7 @@ Maybe you want to use 'update --init'?")"
 				(clear_local_git_env; cd "$sm_path" &&
 					( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
 					 test -z "$rev") || git-fetch)) ||
-				die "$(eval_gettext "Unable to fetch in submodule path '\$prefix\$sm_path'")"
+				die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
 			fi
 
 			# Is this something we just cloned?
@@ -788,20 +849,20 @@ Maybe you want to use 'update --init'?")"
 			case "$update_module" in
 			rebase)
 				command="git rebase"
-				die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$prefix\$sm_path'")"
-				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': rebased into '\$sha1'")"
+				die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
+				say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
 				must_die_on_failure=yes
 				;;
 			merge)
 				command="git merge"
-				die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$prefix\$sm_path'")"
-				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': merged in '\$sha1'")"
+				die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
+				say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
 				must_die_on_failure=yes
 				;;
 			*)
 				command="git checkout $subforce -q"
-				die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$prefix\$sm_path'")"
-				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': checked out '\$sha1'")"
+				die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
+				say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
 				;;
 			esac
 
@@ -828,7 +889,7 @@ Maybe you want to use 'update --init'?")"
 			res=$?
 			if test $res -gt 0
 			then
-				die_msg="$(eval_gettext "Failed to recurse into submodule path '\$prefix\$sm_path'")"
+				die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
 				if test $res -eq 1
 				then
 					err="${err};$die_msg"
@@ -942,6 +1003,7 @@ cmd_summary() {
 	fi
 
 	cd_to_toplevel
+	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
 	# Get modified modules cared by user
 	modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
 		sane_egrep '^:([0-7]* )?160000' |
@@ -991,16 +1053,18 @@ cmd_summary() {
 		! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
 		missing_dst=t
 
+		display_name=$(relative_path "$name")
+
 		total_commits=
 		case "$missing_src,$missing_dst" in
 		t,)
-			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_src")"
+			errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_src")"
 			;;
 		,t)
-			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_dst")"
+			errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_dst")"
 			;;
 		t,t)
-			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
+			errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"
 			;;
 		*)
 			errmsg=
@@ -1029,12 +1093,12 @@ cmd_summary() {
 			submodule="$(gettext "submodule")"
 			if test $mod_dst = 160000
 			then
-				echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
+				echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
 			else
-				echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
+				echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
 			fi
 		else
-			echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
+			echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
 		fi
 		if test -n "$errmsg"
 		then
@@ -1118,7 +1182,7 @@ cmd_status()
 		die_if_unmatched "$mode"
 		name=$(module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
-		displaypath="$prefix$sm_path"
+		displaypath=$(relative_path "$prefix$sm_path")
 		if test "$stage" = U
 		then
 			say "U$sha1 $displaypath"
@@ -1213,7 +1277,8 @@ cmd_sync()
 
 		if git config "submodule.$name.url" >/dev/null 2>/dev/null
 		then
-			say "$(eval_gettext "Synchronizing submodule url for '\$prefix\$sm_path'")"
+			displaypath=$(relative_path "$prefix$sm_path")
+			say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"
 			git config submodule."$name".url "$super_config_url"
 
 			if test -e "$sm_path"/.git
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index ff26535..a38fd92 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -212,6 +212,32 @@ test_expect_success 'submodule add with ./, /.. and // in path' '
 	test_cmp empty untracked
 '
 
+test_expect_success 'submodule add in subdirectory' '
+	echo "refs/heads/master" >expect &&
+	>empty &&
+
+	mkdir addtest/sub &&
+	(
+		cd addtest/sub &&
+		git submodule add "$submodurl" ../realsubmod3 &&
+		git submodule init
+	) &&
+
+	rm -f heads head untracked &&
+	inspect addtest/realsubmod3 ../.. &&
+	test_cmp expect heads &&
+	test_cmp expect head &&
+	test_cmp empty untracked
+'
+
+test_expect_success 'submodule add in subdirectory with relative path should fail' '
+	(
+		cd addtest/sub &&
+		test_must_fail git submodule add ../../ submod3 2>../../output.err
+	) &&
+	test_i18ngrep toplevel output.err
+'
+
 test_expect_success 'setup - add an example entry to .gitmodules' '
 	GIT_CONFIG=.gitmodules \
 	git config submodule.example.url git://example.com/init.git
@@ -319,6 +345,26 @@ test_expect_success 'status should be "up-to-date" after update' '
 	grep "^ $rev1" list
 '
 
+test_expect_success 'status "up-to-date" from subdirectory' '
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule status >../list
+	) &&
+	grep "^ $rev1" list &&
+	grep "\\.\\./init" list
+'
+
+test_expect_success 'status "up-to-date" from subdirectory with path' '
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule status ../init >../list
+	) &&
+	grep "^ $rev1" list &&
+	grep "\\.\\./init" list
+'
+
 test_expect_success 'status should be "modified" after submodule commit' '
 	(
 		cd init &&
@@ -399,6 +445,25 @@ test_expect_success 'update --init' '
 	git rev-parse --resolve-git-dir init/.git
 '
 
+test_expect_success 'update --init from subdirectory' '
+	mv init init2 &&
+	git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
+	git config --remove-section submodule.example &&
+	test_must_fail git config submodule.example.url &&
+
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule update ../init >update.out &&
+		cat update.out &&
+		test_i18ngrep "not initialized" update.out &&
+		test_must_fail git rev-parse --resolve-git-dir ../init/.git &&
+
+		git submodule update --init ../init
+	) &&
+	git rev-parse --resolve-git-dir init/.git
+'
+
 test_expect_success 'do not add files from a submodule' '
 
 	git reset --hard &&
@@ -772,6 +837,21 @@ test_expect_success 'submodule deinit should remove the whole submodule section
 	rmdir init
 '
 
+test_expect_success 'submodule deinit from subdirectory' '
+	git submodule update --init &&
+	git config submodule.example.foo bar &&
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule deinit ../init >../output
+	) &&
+	grep "\\.\\./init" output &&
+	test -z "$(git config --get-regexp "submodule\.example\.")" &&
+	test -n "$(git config --get-regexp "submodule\.example2\.")" &&
+	test -f example2/.git &&
+	rmdir init
+'
+
 test_expect_success 'submodule deinit . deinits all initialized submodules' '
 	git submodule update --init &&
 	git config submodule.example.foo bar &&
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index c328726..ac2434c 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -45,6 +45,42 @@ EOF
 	test_cmp expected actual
 "
 
+test_expect_success 'added submodule (subdirectory)' "
+	mkdir sub &&
+	(
+		cd sub &&
+		git submodule summary >../actual
+	) &&
+	cat >expected <<-EOF &&
+* ../sm1 0000000...$head1 (2):
+  > Add foo2
+
+EOF
+	test_cmp expected actual
+"
+
+test_expect_success 'added submodule (subdirectory only)' "
+	(
+		cd sub &&
+		git submodule summary . >../actual
+	) &&
+	>expected &&
+	test_cmp expected actual
+"
+
+test_expect_success 'added submodule (subdirectory with explicit path)' "
+	(
+		cd sub &&
+		git submodule summary ../sm1 >../actual
+	) &&
+	cat >expected <<-EOF &&
+* ../sm1 0000000...$head1 (2):
+  > Add foo2
+
+EOF
+	test_cmp expected actual
+"
+
 commit_file sm1 &&
 head2=$(add_file sm1 foo3)
 
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index bf90098..79bc135 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -61,6 +61,19 @@ test_expect_success 'change submodule' '
 	)
 '
 
+reset_submodule_urls () {
+	local root
+	root=$(pwd) &&
+	(
+		cd super-clone/submodule &&
+		git config remote.origin.url "$root/submodule"
+	) &&
+	(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url "$root/submodule"
+	)
+}
+
 test_expect_success 'change submodule url' '
 	(
 		cd super &&
@@ -132,6 +145,65 @@ test_expect_success '"git submodule sync --recursive" should update all submodul
 	)
 '
 
+test_expect_success 'reset submodule URLs' '
+	reset_submodule_urls super-clone
+'
+
+test_expect_success '"git submodule sync" should update submodule URLs - subdirectory' '
+	(
+		cd super-clone &&
+		git pull --no-recurse-submodules &&
+		mkdir -p sub &&
+		cd sub &&
+		git submodule sync >../../output
+	) &&
+	grep "\\.\\./submodule" output &&
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
+	)" &&
+	test ! -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
+	)" &&
+	(
+		cd super-clone/submodule &&
+		git checkout master &&
+		git pull
+	) &&
+	(
+		cd super-clone &&
+		test -d "$(git config submodule.submodule.url)"
+	)
+'
+
+test_expect_success '"git submodule sync --recursive" should update all submodule URLs - subdirectory' '
+	(
+		cd super-clone &&
+		(
+			cd submodule &&
+			git pull --no-recurse-submodules
+		) &&
+		mkdir -p sub &&
+		cd sub &&
+		git submodule sync --recursive >../../output
+	) &&
+	grep "\\.\\./submodule/sub-submodule" output &&
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
+	)" &&
+	test -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
+	)" &&
+	(
+		cd super-clone/submodule/sub-submodule &&
+		git checkout master &&
+		git pull
+	)
+'
+
 test_expect_success '"git submodule sync" should update known submodule URLs' '
 	(
 		cd empty-clone &&
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index a4ffea0..cdb0538 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -80,6 +80,21 @@ test_expect_success 'submodule update detaching the HEAD ' '
 	)
 '
 
+test_expect_success 'submodule update from subdirectory' '
+	(cd super/submodule &&
+	 git reset --hard HEAD~1
+	) &&
+	mkdir super/sub &&
+	(cd super/sub &&
+	 (cd ../submodule &&
+	  compare_head
+	 ) &&
+	 git submodule update ../submodule &&
+	 cd ../submodule &&
+	 ! compare_head
+	)
+'
+
 apos="'";
 test_expect_success 'submodule update does not fetch already present commits' '
 	(cd submodule &&
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 107b4b7..91d4fd1 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -80,6 +80,22 @@ test_expect_success 'test basic "submodule foreach" usage' '
 	test_i18ncmp expect actual
 '
 
+cat >expect <<EOF
+Entering '../sub1'
+$pwd/clone-foo1-../sub1-$sub1sha1
+Entering '../sub3'
+$pwd/clone-foo3-../sub3-$sub3sha1
+EOF
+
+test_expect_success 'test "submodule foreach" from subdirectory' '
+	mkdir clone/sub &&
+	(
+		cd clone/sub &&
+		git submodule foreach "echo \$toplevel-\$name-\$sm_path-\$sha1" >../../actual
+	) &&
+	test_i18ncmp expect actual
+'
+
 test_expect_success 'setup nested submodules' '
 	git clone submodule nested1 &&
 	git clone submodule nested2 &&
-- 
1.8.3.779.g691e267

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

* Re: [PATCH v4 0/6] submodule: drop the top-level requirement
  2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
                   ` (5 preceding siblings ...)
  2013-06-16 14:18 ` [PATCH v4 6/6] submodule: drop the top-level requirement John Keeping
@ 2013-06-17 20:41 ` Jens Lehmann
  6 siblings, 0 replies; 8+ messages in thread
From: Jens Lehmann @ 2013-06-17 20:41 UTC (permalink / raw)
  To: John Keeping; +Cc: git, Junio C Hamano, Jonathan Nieder, Johannes Sixt

Am 16.06.2013 16:18, schrieb John Keeping:
> Changes since v3:
> 
> * There are four new patches, three of which are style fixes for
>   existing tests and one fixes an existing error message to return a
>   more accurate path when recursing.
> 
> * You now cannot run "git submodule add <relative URL>" from a
>   subdirectory.  Because the interpretation of the URL changes depending
>   on whether or not remote.origin.url is configured, I have decided to
>   just ban this for now.  If someone comes up with a sensible way to
>   handle this then we can lift this restriction later.
> 
> * The "path" variable exported in "submodule foreach" now uses the
>   relative path and matches the "sm_path" variable.
> 
> * I audited the code again and fixed a few more cases that weren't
>   printing relative paths (notably "submodule init" and "submodule
>   foreach").
> 
> * More tests.

Thanks for working on this! This series is looking good to me.

> John Keeping (6):
>   t7401: make indentation consistent
>   t7403: modernize style
>   t7403: add missing && chaining
>   submodule: show full path in error message
>   rev-parse: add --prefix option
>   submodule: drop the top-level requirement
> 
>  Documentation/git-rev-parse.txt |  16 ++
>  builtin/rev-parse.c             |  24 ++-
>  git-submodule.sh                | 135 ++++++++++----
>  t/t1513-rev-parse-prefix.sh     |  96 ++++++++++
>  t/t7400-submodule-basic.sh      |  80 +++++++++
>  t/t7401-submodule-summary.sh    | 116 +++++++-----
>  t/t7403-submodule-sync.sh       | 388 ++++++++++++++++++++++++++--------------
>  t/t7406-submodule-update.sh     |  15 ++
>  t/t7407-submodule-foreach.sh    |  16 ++
>  9 files changed, 673 insertions(+), 213 deletions(-)
>  create mode 100755 t/t1513-rev-parse-prefix.sh
> 

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

end of thread, other threads:[~2013-06-17 20:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-16 14:18 [PATCH v4 0/6] submodule: drop the top-level requirement John Keeping
2013-06-16 14:18 ` [PATCH v4 1/6] t7401: make indentation consistent John Keeping
2013-06-16 14:18 ` [PATCH v4 2/6] t7403: modernize style John Keeping
2013-06-16 14:18 ` [PATCH v4 3/6] t7403: add missing && chaining John Keeping
2013-06-16 14:18 ` [PATCH v4 4/6] submodule: show full path in error message John Keeping
2013-06-16 14:18 ` [PATCH v4 5/6] rev-parse: add --prefix option John Keeping
2013-06-16 14:18 ` [PATCH v4 6/6] submodule: drop the top-level requirement John Keeping
2013-06-17 20:41 ` [PATCH v4 0/6] " Jens Lehmann

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).