{"thread":{"id":"34164","subject":"[PATCH v4 0/6] submodule: drop the top-level requirement","startedAt":"2013-06-16T14:18:12Z","lastAt":"2013-06-17T20:41:51Z","messageCount":8,"participants":["John Keeping","Jens Lehmann"],"isPatch":true,"patchVersion":4,"patchTotal":6},"messages":[{"id":"220999","messageId":"cover.1371391740.git.john@keeping.me.uk","threadId":"34164","inReplyTo":null,"subject":"[PATCH v4 0/6] submodule: drop the top-level requirement","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-06-16T14:18:12Z","receivedAt":"2013-06-16T14:18:12Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Changes since v3:\n\n* There are four new patches, three of which are style fixes for\n  existing tests and one fixes an existing error message to return a\n  more accurate path when recursing.\n\n* You now cannot run \"git submodule add <relative URL>\" from a\n  subdirectory.  Because the interpretation of the URL changes depending\n  on whether or not remote.origin.url is configured, I have decided to\n  just ban this for now.  If someone comes up with a sensible way to\n  handle this then we can lift this restriction later.\n\n* The \"path\" variable exported in \"submodule foreach\" now uses the\n  relative path and matches the \"sm_path\" variable.\n\n* I audited the code again and fixed a few more cases that weren't\n  printing relative paths (notably \"submodule init\" and \"submodule\n  foreach\").\n\n* More tests.\n\nJohn Keeping (6):\n  t7401: make indentation consistent\n  t7403: modernize style\n  t7403: add missing && chaining\n  submodule: show full path in error message\n  rev-parse: add --prefix option\n  submodule: drop the top-level requirement\n\n Documentation/git-rev-parse.txt |  16 ++\n builtin/rev-parse.c             |  24 ++-\n git-submodule.sh                | 135 ++++++++++----\n t/t1513-rev-parse-prefix.sh     |  96 ++++++++++\n t/t7400-submodule-basic.sh      |  80 +++++++++\n t/t7401-submodule-summary.sh    | 116 +++++++-----\n t/t7403-submodule-sync.sh       | 388 ++++++++++++++++++++++++++--------------\n t/t7406-submodule-update.sh     |  15 ++\n t/t7407-submodule-foreach.sh    |  16 ++\n 9 files changed, 673 insertions(+), 213 deletions(-)\n create mode 100755 t/t1513-rev-parse-prefix.sh\n\n-- \n1.8.3.779.g691e267\n"},{"id":"221000","messageId":"30d8ca8ceafca970c9028b751761393f3e2ded90.1371391740.git.john@keeping.me.uk","threadId":"34164","inReplyTo":"cover.1371391740.git.john@keeping.me.uk","subject":"[PATCH v4 1/6] t7401: make indentation consistent","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-06-16T14:18:13Z","receivedAt":"2013-06-16T14:18:13Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Only leading whitespace is changed in this patch.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\n t/t7401-submodule-summary.sh | 80 ++++++++++++++++++++++----------------------\n 1 file changed, 40 insertions(+), 40 deletions(-)\n\ndiff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh\nindex 30b429e..c328726 100755\n--- a/t/t7401-submodule-summary.sh\n+++ b/t/t7401-submodule-summary.sh\n@@ -76,8 +76,8 @@ head3=$(\n )\n \n test_expect_success 'modified submodule(backward)' \"\n-    git submodule summary >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head2...$head3 (2):\n   < Add foo3\n   < Add foo2\n@@ -89,8 +89,8 @@ EOF\n head4=$(add_file sm1 foo4 foo5) &&\n head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD)\n test_expect_success 'modified submodule(backward and forward)' \"\n-    git submodule summary >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head2...$head4 (4):\n   > Add foo5\n   > Add foo4\n@@ -102,15 +102,15 @@ EOF\n \"\n \n test_expect_success '--summary-limit' \"\n-    git submodule summary -n 3 >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary -n 3 >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head2...$head4 (4):\n   > Add foo5\n   > Add foo4\n   < Add foo3\n \n EOF\n-    test_cmp expected actual\n+\ttest_cmp expected actual\n \"\n \n commit_file sm1 &&\n@@ -122,8 +122,8 @@ rm -f sm1 &&\n mv sm1-bak sm1\n \n test_expect_success 'typechanged submodule(submodule->blob), --cached' \"\n-    git submodule summary --cached >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary --cached >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head4(submodule)->$head5(blob) (3):\n   < Add foo5\n \n@@ -132,59 +132,59 @@ EOF\n \"\n \n test_expect_success 'typechanged submodule(submodule->blob), --files' \"\n-    git submodule summary --files >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary --files >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head5(blob)->$head4(submodule) (3):\n   > Add foo5\n \n EOF\n-    test_i18ncmp actual expected\n+\ttest_i18ncmp actual expected\n \"\n \n rm -rf sm1 &&\n git checkout-index sm1\n test_expect_success 'typechanged submodule(submodule->blob)' \"\n-    git submodule summary >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head4(submodule)->$head5(blob):\n \n EOF\n-    test_i18ncmp actual expected\n+\ttest_i18ncmp actual expected\n \"\n \n rm -f sm1 &&\n test_create_repo sm1 &&\n head6=$(add_file sm1 foo6 foo7)\n test_expect_success 'nonexistent commit' \"\n-    git submodule summary >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head4...$head6:\n   Warn: sm1 doesn't contain commit $head4_full\n \n EOF\n-    test_i18ncmp actual expected\n+\ttest_i18ncmp actual expected\n \"\n \n commit_file\n test_expect_success 'typechanged submodule(blob->submodule)' \"\n-    git submodule summary >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head5(blob)->$head6(submodule) (2):\n   > Add foo7\n \n EOF\n-    test_i18ncmp expected actual\n+\ttest_i18ncmp expected actual\n \"\n \n commit_file sm1 &&\n rm -rf sm1\n test_expect_success 'deleted submodule' \"\n-    git submodule summary >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head6...0000000:\n \n EOF\n-    test_cmp expected actual\n+\ttest_cmp expected actual\n \"\n \n test_create_repo sm2 &&\n@@ -192,43 +192,43 @@ head7=$(add_file sm2 foo8 foo9) &&\n git add sm2\n \n test_expect_success 'multiple submodules' \"\n-    git submodule summary >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head6...0000000:\n \n * sm2 0000000...$head7 (2):\n   > Add foo9\n \n EOF\n-    test_cmp expected actual\n+\ttest_cmp expected actual\n \"\n \n test_expect_success 'path filter' \"\n-    git submodule summary sm2 >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary sm2 >actual &&\n+\tcat >expected <<-EOF &&\n * sm2 0000000...$head7 (2):\n   > Add foo9\n \n EOF\n-    test_cmp expected actual\n+\ttest_cmp expected actual\n \"\n \n commit_file sm2\n test_expect_success 'given commit' \"\n-    git submodule summary HEAD^ >actual &&\n-    cat >expected <<-EOF &&\n+\tgit submodule summary HEAD^ >actual &&\n+\tcat >expected <<-EOF &&\n * sm1 $head6...0000000:\n \n * sm2 0000000...$head7 (2):\n   > Add foo9\n \n EOF\n-    test_cmp expected actual\n+\ttest_cmp expected actual\n \"\n \n test_expect_success '--for-status' \"\n-    git submodule summary --for-status HEAD^ >actual &&\n-    test_i18ncmp actual - <<EOF\n+\tgit submodule summary --for-status HEAD^ >actual &&\n+\ttest_i18ncmp actual - <<EOF\n # Submodule changes to be committed:\n #\n # * sm1 $head6...0000000:\n@@ -240,14 +240,14 @@ EOF\n \"\n \n test_expect_success 'fail when using --files together with --cached' \"\n-    test_must_fail git submodule summary --files --cached\n+\ttest_must_fail git submodule summary --files --cached\n \"\n \n test_expect_success 'should not fail in an empty repo' \"\n-    git init xyzzy &&\n-    cd xyzzy &&\n-    git submodule summary >output 2>&1 &&\n-    test_cmp output /dev/null\n+\tgit init xyzzy &&\n+\tcd xyzzy &&\n+\tgit submodule summary >output 2>&1 &&\n+\ttest_cmp output /dev/null\n \"\n \n test_done\n-- \n1.8.3.779.g691e267\n"},{"id":"221001","messageId":"0bd17d5cf3c001d1271ba7d36299ea20881ca122.1371391740.git.john@keeping.me.uk","threadId":"34164","inReplyTo":"cover.1371391740.git.john@keeping.me.uk","subject":"[PATCH v4 2/6] t7403: modernize style","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-06-16T14:18:14Z","receivedAt":"2013-06-16T14:18:14Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Change the indentation to use tabs consistently and start content on the\nline after the paren opening a subshell.\n\nAlso don't put a space in \">file\" and remove \":\" from \": >file\" to be\nconsistent with the majority of tests elsewhere.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\n t/t7403-submodule-sync.sh | 316 +++++++++++++++++++++++++++-------------------\n 1 file changed, 183 insertions(+), 133 deletions(-)\n\ndiff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh\nindex 94e26c4..38f6cc4 100755\n--- a/t/t7403-submodule-sync.sh\n+++ b/t/t7403-submodule-sync.sh\n@@ -11,216 +11,266 @@ These tests exercise the \"git submodule sync\" subcommand.\n . ./test-lib.sh\n \n test_expect_success setup '\n-\techo file > file &&\n+\techo file >file &&\n \tgit add file &&\n \ttest_tick &&\n \tgit commit -m upstream &&\n \tgit clone . super &&\n \tgit clone super submodule &&\n-\t(cd submodule &&\n-\t git submodule add ../submodule sub-submodule &&\n-\t test_tick &&\n-\t git commit -m \"sub-submodule\"\n+\t(\n+\t\tcd submodule &&\n+\t\tgit submodule add ../submodule sub-submodule &&\n+\t\ttest_tick &&\n+\t\tgit commit -m \"sub-submodule\"\n \t) &&\n-\t(cd super &&\n-\t git submodule add ../submodule submodule &&\n-\t test_tick &&\n-\t git commit -m \"submodule\"\n+\t(\n+\t\tcd super &&\n+\t\tgit submodule add ../submodule submodule &&\n+\t\ttest_tick &&\n+\t\tgit commit -m \"submodule\"\n \t) &&\n \tgit clone super super-clone &&\n-\t(cd super-clone && git submodule update --init --recursive) &&\n+\t(\n+\t\tcd super-clone &&\n+\t\tgit submodule update --init --recursive\n+\t) &&\n \tgit clone super empty-clone &&\n-\t(cd empty-clone && git submodule init) &&\n+\t(\n+\t\tcd empty-clone &&\n+\t\tgit submodule init\n+\t) &&\n \tgit clone super top-only-clone &&\n \tgit clone super relative-clone &&\n-\t(cd relative-clone && git submodule update --init --recursive) &&\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit submodule update --init --recursive\n+\t) &&\n \tgit clone super recursive-clone &&\n-\t(cd recursive-clone && git submodule update --init --recursive)\n+\t(\n+\t\tcd recursive-clone &&\n+\t\tgit submodule update --init --recursive\n+\t)\n '\n \n test_expect_success 'change submodule' '\n-\t(cd submodule &&\n-\t echo second line >> file &&\n-\t test_tick &&\n-\t git commit -a -m \"change submodule\"\n+\t(\n+\t\tcd submodule &&\n+\t\techo second line >>file &&\n+\t\ttest_tick &&\n+\t\tgit commit -a -m \"change submodule\"\n \t)\n '\n \n test_expect_success 'change submodule url' '\n-\t(cd super &&\n-\t cd submodule &&\n-\t git checkout master &&\n-\t git pull\n+\t(\n+\t\tcd super &&\n+\t\tcd submodule &&\n+\t\tgit checkout master &&\n+\t\tgit pull\n \t) &&\n \tmv submodule moved-submodule &&\n-\t(cd moved-submodule &&\n-\t git config -f .gitmodules submodule.sub-submodule.url ../moved-submodule &&\n-\t test_tick &&\n-\t git commit -a -m moved-sub-submodule\n+\t(\n+\t\tcd moved-submodule &&\n+\t\tgit config -f .gitmodules submodule.sub-submodule.url ../moved-submodule &&\n+\t\ttest_tick &&\n+\t\tgit commit -a -m moved-sub-submodule\n \t) &&\n-\t(cd super &&\n-\t git config -f .gitmodules submodule.submodule.url ../moved-submodule &&\n-\t test_tick &&\n-\t git commit -a -m moved-submodule\n+\t(\n+\t\tcd super &&\n+\t\tgit config -f .gitmodules submodule.submodule.url ../moved-submodule &&\n+\t\ttest_tick &&\n+\t\tgit commit -a -m moved-submodule\n \t)\n '\n \n test_expect_success '\"git submodule sync\" should update submodule URLs' '\n-\t(cd super-clone &&\n-\t git pull --no-recurse-submodules &&\n-\t git submodule sync\n+\t(\n+\t\tcd super-clone &&\n+\t\tgit pull --no-recurse-submodules &&\n+\t\tgit submodule sync\n \t) &&\n-\ttest -d \"$(cd super-clone/submodule &&\n-\t git config remote.origin.url\n+\ttest -d \"$(\n+\t\tcd super-clone/submodule &&\n+\t\tgit config remote.origin.url\n \t)\" &&\n-\ttest ! -d \"$(cd super-clone/submodule/sub-submodule &&\n-\t git config remote.origin.url\n+\ttest ! -d \"$(\n+\t\tcd super-clone/submodule/sub-submodule &&\n+\t\tgit config remote.origin.url\n \t)\" &&\n-\t(cd super-clone/submodule &&\n-\t git checkout master &&\n-\t git pull\n+\t(\n+\t\tcd super-clone/submodule &&\n+\t\tgit checkout master &&\n+\t\tgit pull\n \t) &&\n-\t(cd super-clone &&\n-\t test -d \"$(git config submodule.submodule.url)\"\n+\t(\n+\t\tcd super-clone &&\n+\t\ttest -d \"$(git config submodule.submodule.url)\"\n \t)\n '\n \n test_expect_success '\"git submodule sync --recursive\" should update all submodule URLs' '\n-\t(cd super-clone &&\n-\t (cd submodule &&\n-\t  git pull --no-recurse-submodules\n-\t ) &&\n-\t git submodule sync --recursive\n+\t(\n+\t\tcd super-clone &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\tgit pull --no-recurse-submodules\n+\t\t) &&\n+\t\tgit submodule sync --recursive\n \t) &&\n-\ttest -d \"$(cd super-clone/submodule &&\n-\t git config remote.origin.url\n+\ttest -d \"$(\n+\t\tcd super-clone/submodule &&\n+\t\tgit config remote.origin.url\n \t)\" &&\n-\ttest -d \"$(cd super-clone/submodule/sub-submodule &&\n-\t git config remote.origin.url\n+\ttest -d \"$(\n+\t\tcd super-clone/submodule/sub-submodule &&\n+\t\tgit config remote.origin.url\n \t)\" &&\n-\t(cd super-clone/submodule/sub-submodule &&\n-\t git checkout master &&\n-\t git pull\n+\t(\n+\t\tcd super-clone/submodule/sub-submodule &&\n+\t\tgit checkout master &&\n+\t\tgit pull\n \t)\n '\n \n test_expect_success '\"git submodule sync\" should update known submodule URLs' '\n-\t(cd empty-clone &&\n-\t git pull &&\n-\t git submodule sync &&\n-\t test -d \"$(git config submodule.submodule.url)\"\n+\t(\n+\t\tcd empty-clone &&\n+\t\tgit pull &&\n+\t\tgit submodule sync &&\n+\t\ttest -d \"$(git config submodule.submodule.url)\"\n \t)\n '\n \n test_expect_success '\"git submodule sync\" should not vivify uninteresting submodule' '\n-\t(cd top-only-clone &&\n-\t git pull &&\n-\t git submodule sync &&\n-\t test -z \"$(git config submodule.submodule.url)\" &&\n-\t git submodule sync submodule &&\n-\t test -z \"$(git config submodule.submodule.url)\"\n+\t(\n+\t\tcd top-only-clone &&\n+\t\tgit pull &&\n+\t\tgit submodule sync &&\n+\t\ttest -z \"$(git config submodule.submodule.url)\" &&\n+\t\tgit submodule sync submodule &&\n+\t\ttest -z \"$(git config submodule.submodule.url)\"\n \t)\n '\n \n test_expect_success '\"git submodule sync\" handles origin URL of the form foo' '\n-\t(cd relative-clone &&\n-\t git remote set-url origin foo &&\n-\t git submodule sync &&\n-\t(cd submodule &&\n-\t #actual fails with: \"cannot strip off url foo\n-\t test \"$(git config remote.origin.url)\" = \"../submodule\"\n-\t)\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit remote set-url origin foo &&\n+\t\tgit submodule sync &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\t#actual fails with: \"cannot strip off url foo\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../submodule\"\n+\t\t)\n \t)\n '\n \n test_expect_success '\"git submodule sync\" handles origin URL of the form foo/bar' '\n-\t(cd relative-clone &&\n-\t git remote set-url origin foo/bar &&\n-\t git submodule sync &&\n-\t(cd submodule &&\n-\t #actual foo/submodule\n-\t test \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n-\t)\n-\t(cd submodule/sub-submodule &&\n-\t test \"$(git config remote.origin.url)\" != \"../../foo/submodule\"\n-\t)\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit remote set-url origin foo/bar &&\n+\t\tgit submodule sync &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\t#actual foo/submodule\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n+\t\t)\n+\t\t(\n+\t\t\tcd submodule/sub-submodule &&\n+\t\t\ttest \"$(git config remote.origin.url)\" != \"../../foo/submodule\"\n+\t\t)\n \t)\n '\n \n test_expect_success '\"git submodule sync --recursive\" propagates changes in origin' '\n-\t(cd recursive-clone &&\n-\t git remote set-url origin foo/bar &&\n-\t git submodule sync --recursive &&\n-\t(cd submodule &&\n-\t #actual foo/submodule\n-\t test \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n-\t)\n-\t(cd submodule/sub-submodule &&\n-\t test \"$(git config remote.origin.url)\" = \"../../foo/submodule\"\n-\t)\n+\t(\n+\t\tcd recursive-clone &&\n+\t\tgit remote set-url origin foo/bar &&\n+\t\tgit submodule sync --recursive &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\t#actual foo/submodule\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n+\t\t)\n+\t\t(\n+\t\t\tcd submodule/sub-submodule &&\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../../foo/submodule\"\n+\t\t)\n \t)\n '\n \n test_expect_success '\"git submodule sync\" handles origin URL of the form ./foo' '\n-\t(cd relative-clone &&\n-\t git remote set-url origin ./foo &&\n-\t git submodule sync &&\n-\t(cd submodule &&\n-\t #actual ./submodule\n-\t test \"$(git config remote.origin.url)\" = \"../submodule\"\n-\t)\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit remote set-url origin ./foo &&\n+\t\tgit submodule sync &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\t#actual ./submodule\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../submodule\"\n+\t\t)\n \t)\n '\n \n test_expect_success '\"git submodule sync\" handles origin URL of the form ./foo/bar' '\n-\t(cd relative-clone &&\n-\t git remote set-url origin ./foo/bar &&\n-\t git submodule sync &&\n-\t(cd submodule &&\n-\t #actual ./foo/submodule\n-\t test \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n-\t)\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit remote set-url origin ./foo/bar &&\n+\t\tgit submodule sync &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\t#actual ./foo/submodule\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n+\t\t)\n \t)\n '\n \n test_expect_success '\"git submodule sync\" handles origin URL of the form ../foo' '\n-\t(cd relative-clone &&\n-\t git remote set-url origin ../foo &&\n-\t git submodule sync &&\n-\t(cd submodule &&\n-\t #actual ../submodule\n-\t test \"$(git config remote.origin.url)\" = \"../../submodule\"\n-\t)\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit remote set-url origin ../foo &&\n+\t\tgit submodule sync &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\t#actual ../submodule\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../../submodule\"\n+\t\t)\n \t)\n '\n \n test_expect_success '\"git submodule sync\" handles origin URL of the form ../foo/bar' '\n-\t(cd relative-clone &&\n-\t git remote set-url origin ../foo/bar &&\n-\t git submodule sync &&\n-\t(cd submodule &&\n-\t #actual ../foo/submodule\n-\t test \"$(git config remote.origin.url)\" = \"../../foo/submodule\"\n-\t)\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit remote set-url origin ../foo/bar &&\n+\t\tgit submodule sync &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\t#actual ../foo/submodule\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../../foo/submodule\"\n+\t\t)\n \t)\n '\n \n test_expect_success '\"git submodule sync\" handles origin URL of the form ../foo/bar with deeply nested submodule' '\n-\t(cd relative-clone &&\n-\t git remote set-url origin ../foo/bar &&\n-\t mkdir -p a/b/c &&\n-\t ( cd a/b/c &&\n-\t   git init &&\n-\t   :> .gitignore &&\n-\t   git add .gitignore &&\n-\t   test_tick &&\n-\t   git commit -m \"initial commit\" ) &&\n-\t git submodule add ../bar/a/b/c ./a/b/c &&\n-\t git submodule sync &&\n-\t(cd a/b/c &&\n-\t #actual ../foo/bar/a/b/c\n-\t test \"$(git config remote.origin.url)\" = \"../../../../foo/bar/a/b/c\"\n-\t)\n+\t(\n+\t\tcd relative-clone &&\n+\t\tgit remote set-url origin ../foo/bar &&\n+\t\tmkdir -p a/b/c &&\n+\t\t(\n+\t\t\tcd a/b/c &&\n+\t\t\tgit init &&\n+\t\t\t>.gitignore &&\n+\t\t\tgit add .gitignore &&\n+\t\t\ttest_tick &&\n+\t\t\tgit commit -m \"initial commit\"\n+\t\t) &&\n+\t\tgit submodule add ../bar/a/b/c ./a/b/c &&\n+\t\tgit submodule sync &&\n+\t\t(\n+\t\t\tcd a/b/c &&\n+\t\t\t#actual ../foo/bar/a/b/c\n+\t\t\ttest \"$(git config remote.origin.url)\" = \"../../../../foo/bar/a/b/c\"\n+\t\t)\n \t)\n '\n \n-- \n1.8.3.779.g691e267\n"},{"id":"221002","messageId":"1f972ee320a1d59c516a962adb853561233c17f7.1371391740.git.john@keeping.me.uk","threadId":"34164","inReplyTo":"cover.1371391740.git.john@keeping.me.uk","subject":"[PATCH v4 3/6] t7403: add missing && chaining","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-06-16T14:18:15Z","receivedAt":"2013-06-16T14:18:15Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Signed-off-by: John Keeping <john@keeping.me.uk>\n---\n t/t7403-submodule-sync.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh\nindex 38f6cc4..bf90098 100755\n--- a/t/t7403-submodule-sync.sh\n+++ b/t/t7403-submodule-sync.sh\n@@ -174,7 +174,7 @@ test_expect_success '\"git submodule sync\" handles origin URL of the form foo/bar\n \t\t\tcd submodule &&\n \t\t\t#actual foo/submodule\n \t\t\ttest \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n-\t\t)\n+\t\t) &&\n \t\t(\n \t\t\tcd submodule/sub-submodule &&\n \t\t\ttest \"$(git config remote.origin.url)\" != \"../../foo/submodule\"\n@@ -191,7 +191,7 @@ test_expect_success '\"git submodule sync --recursive\" propagates changes in orig\n \t\t\tcd submodule &&\n \t\t\t#actual foo/submodule\n \t\t\ttest \"$(git config remote.origin.url)\" = \"../foo/submodule\"\n-\t\t)\n+\t\t) &&\n \t\t(\n \t\t\tcd submodule/sub-submodule &&\n \t\t\ttest \"$(git config remote.origin.url)\" = \"../../foo/submodule\"\n-- \n1.8.3.779.g691e267\n"},{"id":"221003","messageId":"eec9274fcda272904c625fe3d8e68b34490671cf.1371391740.git.john@keeping.me.uk","threadId":"34164","inReplyTo":"cover.1371391740.git.john@keeping.me.uk","subject":"[PATCH v4 4/6] submodule: show full path in error message","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-06-16T14:18:16Z","receivedAt":"2013-06-16T14:18:16Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"When --recursive was added to \"submodule foreach\" in commit 15fc56a (git\nsubmodule foreach: Add --recursive to recurse into nested submodules,\n2009-08-19), the error message when the script returns a non-zero status\nwas not updated to contain $prefix to show the full path.  Fix this.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\n git-submodule.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 79bfaac..bdb438b 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -485,7 +485,7 @@ cmd_foreach()\n \t\t\t\t\tcmd_foreach \"--recursive\" \"$@\"\n \t\t\t\tfi\n \t\t\t) <&3 3<&- ||\n-\t\t\tdie \"$(eval_gettext \"Stopping at '\\$sm_path'; script returned non-zero status.\")\"\n+\t\t\tdie \"$(eval_gettext \"Stopping at '\\$prefix\\$sm_path'; script returned non-zero status.\")\"\n \t\tfi\n \tdone\n }\n-- \n1.8.3.779.g691e267\n"},{"id":"221004","messageId":"ce84ea4a18d862363772edc57286572ee272ab43.1371391740.git.john@keeping.me.uk","threadId":"34164","inReplyTo":"cover.1371391740.git.john@keeping.me.uk","subject":"[PATCH v4 5/6] rev-parse: add --prefix option","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-06-16T14:18:17Z","receivedAt":"2013-06-16T14:18:17Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"This makes 'git rev-parse' behave as if it were invoked from the\nspecified subdirectory of a repository, with the difference that any\nfile paths which it prints are prefixed with the full path from the top\nof the working tree.\n\nThis is useful for shell scripts where we may want to cd to the top of\nthe working tree but need to handle relative paths given by the user on\nthe command line.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\n Documentation/git-rev-parse.txt | 16 +++++++\n builtin/rev-parse.c             | 24 ++++++++---\n t/t1513-rev-parse-prefix.sh     | 96 +++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 131 insertions(+), 5 deletions(-)\n create mode 100755 t/t1513-rev-parse-prefix.sh\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex 947d62f..993903c 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -59,6 +59,22 @@ OPTIONS\n \tIf there is no parameter given by the user, use `<arg>`\n \tinstead.\n \n+--prefix <arg>::\n+\tBehave as if 'git rev-parse' was invoked from the `<arg>`\n+\tsubdirectory of the working tree.  Any relative filenames are\n+\tresolved as if they are prefixed by `<arg>` and will be printed\n+\tin that form.\n++\n+This can be used to convert arguments to a command run in a subdirectory\n+so that they can still be used after moving to the top-level of the\n+repository.  For example:\n++\n+----\n+prefix=$(git rev-parse --show-prefix)\n+cd \"$(git rev-parse --show-toplevel)\"\n+eval \"set -- $(git rev-parse --sq --prefix \"$prefix\" \"$@\")\"\n+----\n+\n --verify::\n \tVerify that exactly one parameter is provided, and that it\n \tcan be turned into a raw 20-byte SHA-1 that can be used to\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex f267a1d..de894c7 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -212,11 +212,17 @@ static void show_datestring(const char *flag, const char *datestr)\n \tshow(buffer);\n }\n \n-static int show_file(const char *arg)\n+static int show_file(const char *arg, int output_prefix)\n {\n \tshow_default();\n \tif ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) {\n-\t\tshow(arg);\n+\t\tif (output_prefix) {\n+\t\t\tconst char *prefix = startup_info->prefix;\n+\t\t\tshow(prefix_filename(prefix,\n+\t\t\t\t\t     prefix ? strlen(prefix) : 0,\n+\t\t\t\t\t     arg));\n+\t\t} else\n+\t\t\tshow(arg);\n \t\treturn 1;\n \t}\n \treturn 0;\n@@ -470,6 +476,7 @@ N_(\"git rev-parse --parseopt [options] -- [<args>...]\\n\"\n int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n {\n \tint i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;\n+\tint output_prefix = 0;\n \tunsigned char sha1[20];\n \tconst char *name = NULL;\n \n@@ -503,7 +510,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\tconst char *arg = argv[i];\n \n \t\tif (as_is) {\n-\t\t\tif (show_file(arg) && as_is < 2)\n+\t\t\tif (show_file(arg, output_prefix) && as_is < 2)\n \t\t\t\tverify_filename(prefix, arg, 0);\n \t\t\tcontinue;\n \t\t}\n@@ -527,7 +534,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tas_is = 2;\n \t\t\t\t/* Pass on the \"--\" if we show anything but files.. */\n \t\t\t\tif (filter & (DO_FLAGS | DO_REVS))\n-\t\t\t\t\tshow_file(arg);\n+\t\t\t\t\tshow_file(arg, 0);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--default\")) {\n@@ -535,6 +542,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\ti++;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--prefix\")) {\n+\t\t\t\tprefix = argv[i+1];\n+\t\t\t\tstartup_info->prefix = prefix;\n+\t\t\t\toutput_prefix = 1;\n+\t\t\t\ti++;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tif (!strcmp(arg, \"--revs-only\")) {\n \t\t\t\tfilter &= ~DO_NOREV;\n \t\t\t\tcontinue;\n@@ -754,7 +768,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\tif (verify)\n \t\t\tdie_no_single_rev(quiet);\n \t\tas_is = 1;\n-\t\tif (!show_file(arg))\n+\t\tif (!show_file(arg, output_prefix))\n \t\t\tcontinue;\n \t\tverify_filename(prefix, arg, 1);\n \t}\ndiff --git a/t/t1513-rev-parse-prefix.sh b/t/t1513-rev-parse-prefix.sh\nnew file mode 100755\nindex 0000000..87ec3ae\n--- /dev/null\n+++ b/t/t1513-rev-parse-prefix.sh\n@@ -0,0 +1,96 @@\n+#!/bin/sh\n+\n+test_description='Tests for rev-parse --prefix'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tmkdir -p sub1/sub2 &&\n+\techo top >top &&\n+\techo file1 >sub1/file1 &&\n+\techo file2 >sub1/sub2/file2 &&\n+\tgit add top sub1/file1 sub1/sub2/file2 &&\n+\tgit commit -m commit\n+'\n+\n+test_expect_success 'empty prefix -- file' '\n+\tgit rev-parse --prefix \"\" -- top sub1/file1 >actual &&\n+\tcat <<-\\EOF >expected &&\n+\t--\n+\ttop\n+\tsub1/file1\n+\tEOF\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'valid prefix -- file' '\n+\tgit rev-parse --prefix sub1/ -- file1 sub2/file2 >actual &&\n+\tcat <<-\\EOF >expected &&\n+\t--\n+\tsub1/file1\n+\tsub1/sub2/file2\n+\tEOF\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'valid prefix -- ../file' '\n+\tgit rev-parse --prefix sub1/ -- ../top sub2/file2 >actual &&\n+\tcat <<-\\EOF >expected &&\n+\t--\n+\tsub1/../top\n+\tsub1/sub2/file2\n+\tEOF\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'empty prefix HEAD:./path' '\n+\tgit rev-parse --prefix \"\" HEAD:./top >actual &&\n+\tgit rev-parse HEAD:top >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'valid prefix HEAD:./path' '\n+\tgit rev-parse --prefix sub1/ HEAD:./file1 >actual &&\n+\tgit rev-parse HEAD:sub1/file1 >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'valid prefix HEAD:../path' '\n+\tgit rev-parse --prefix sub1/ HEAD:../top >actual &&\n+\tgit rev-parse HEAD:top >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'prefix ignored with HEAD:top' '\n+\tgit rev-parse --prefix sub1/ HEAD:top >actual &&\n+\tgit rev-parse HEAD:top >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'disambiguate path with valid prefix' '\n+\tgit rev-parse --prefix sub1/ file1 >actual &&\n+\tcat <<-\\EOF >expected &&\n+\tsub1/file1\n+\tEOF\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'file and refs with prefix' '\n+\tgit rev-parse --prefix sub1/ master file1 >actual &&\n+\tcat <<-EOF >expected &&\n+\t$(git rev-parse master)\n+\tsub1/file1\n+\tEOF\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'two-levels deep' '\n+\tgit rev-parse --prefix sub1/sub2/ -- file2 >actual &&\n+\tcat <<-\\EOF >expected &&\n+\t--\n+\tsub1/sub2/file2\n+\tEOF\n+\ttest_cmp expected actual\n+'\n+\n+test_done\n-- \n1.8.3.779.g691e267\n"},{"id":"221005","messageId":"ff294bec3e56e2337353af3c78208f47cb42fb04.1371391740.git.john@keeping.me.uk","threadId":"34164","inReplyTo":"cover.1371391740.git.john@keeping.me.uk","subject":"[PATCH v4 6/6] submodule: drop the top-level requirement","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-06-16T14:18:18Z","receivedAt":"2013-06-16T14:18:18Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Use the new rev-parse --prefix option to process all paths given to the\nsubmodule command, dropping the requirement that it be run from the\ntop-level of the repository.\n\nSince the interpretation of a relative submodule URL depends on whether\nor not \"remote.origin.url\" is configured, explicitly block relative URLs\nin \"git submodule add\" when not at the top level of the working tree.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\n git-submodule.sh             | 135 ++++++++++++++++++++++++++++++++-----------\n t/t7400-submodule-basic.sh   |  80 +++++++++++++++++++++++++\n t/t7401-submodule-summary.sh |  36 ++++++++++++\n t/t7403-submodule-sync.sh    |  72 +++++++++++++++++++++++\n t/t7406-submodule-update.sh  |  15 +++++\n t/t7407-submodule-foreach.sh |  16 +++++\n 6 files changed, 319 insertions(+), 35 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex bdb438b..7756d81 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -14,10 +14,13 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\"\n OPTIONS_SPEC=\n+SUBDIRECTORY_OK=Yes\n . git-sh-setup\n . git-sh-i18n\n . git-parse-remote\n require_work_tree\n+wt_prefix=$(git rev-parse --show-prefix)\n+cd_to_toplevel\n \n command=\n branch=\n@@ -106,12 +109,48 @@ resolve_relative_url ()\n \techo \"${is_relative:+${up_path}}${remoteurl#./}\"\n }\n \n+# Resolve a path to be relative to another path.  This is intended for\n+# converting submodule paths when git-submodule is run in a subdirectory\n+# and only handles paths where the directory separator is '/'.\n+#\n+# The output is the first argument as a path relative to the second argument,\n+# which defaults to $wt_prefix if it is omitted.\n+relative_path ()\n+{\n+\tlocal target curdir result\n+\ttarget=$1\n+\tcurdir=${2-$wt_prefix}\n+\tcurdir=${curdir%/}\n+\tresult=\n+\n+\twhile test -n \"$curdir\"\n+\tdo\n+\t\tcase \"$target\" in\n+\t\t\"$curdir/\"*)\n+\t\t\ttarget=${target#\"$curdir\"/}\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\n+\t\tresult=\"${result}../\"\n+\t\tif test \"$curdir\" = \"${curdir%/*}\"\n+\t\tthen\n+\t\t\tcurdir=\n+\t\telse\n+\t\t\tcurdir=\"${curdir%/*}\"\n+\t\tfi\n+\tdone\n+\n+\techo \"$result$target\"\n+}\n+\n #\n # Get submodule info for registered submodules\n # $@ = path to limit submodule list\n #\n module_list()\n {\n+\teval \"set $(git rev-parse --sq --prefix \"$wt_prefix\" -- \"$@\")\"\n \t(\n \t\tgit ls-files --error-unmatch --stage -- \"$@\" ||\n \t\techo \"unmatched pathspec exists\"\n@@ -282,6 +321,7 @@ isnumber()\n cmd_add()\n {\n \t# parse $args after \"submodule ... add\".\n+\treference_path=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -298,11 +338,11 @@ cmd_add()\n \t\t\t;;\n \t\t--reference)\n \t\t\tcase \"$2\" in '') usage ;; esac\n-\t\t\treference=\"--reference=$2\"\n+\t\t\treference_path=$2\n \t\t\tshift\n \t\t\t;;\n \t\t--reference=*)\n-\t\t\treference=\"$1\"\n+\t\t\treference_path=\"${1#--reference=}\"\n \t\t\t;;\n \t\t--name)\n \t\t\tcase \"$2\" in '') usage ;; esac\n@@ -323,6 +363,14 @@ cmd_add()\n \t\tshift\n \tdone\n \n+\tif test -n \"$reference_path\"\n+\tthen\n+\t\tis_absolute_path \"$reference_path\" ||\n+\t\treference_path=\"$wt_prefix$reference_path\"\n+\n+\t\treference=\"--reference=$reference_path\"\n+\tfi\n+\n \trepo=$1\n \tsm_path=$2\n \n@@ -335,9 +383,14 @@ cmd_add()\n \t\tusage\n \tfi\n \n+\tis_absolute_path \"$sm_path\" || sm_path=\"$wt_prefix$sm_path\"\n+\n \t# assure repo is absolute or relative to parent\n \tcase \"$repo\" in\n \t./*|../*)\n+\t\ttest -z \"$wt_prefix\" ||\n+\t\tdie \"$(gettext \"Relative path can only be used from the toplevel of the working tree\")\"\n+\n \t\t# dereference source url relative to parent's url\n \t\trealrepo=$(resolve_relative_url \"$repo\") || exit\n \t\t;;\n@@ -471,21 +524,23 @@ cmd_foreach()\n \t\tdie_if_unmatched \"$mode\"\n \t\tif test -e \"$sm_path\"/.git\n \t\tthen\n-\t\t\tsay \"$(eval_gettext \"Entering '\\$prefix\\$sm_path'\")\"\n+\t\t\tdisplaypath=$(relative_path \"$sm_path\")\n+\t\t\tsay \"$(eval_gettext \"Entering '\\$prefix\\$displaypath'\")\"\n \t\t\tname=$(module_name \"$sm_path\")\n \t\t\t(\n \t\t\t\tprefix=\"$prefix$sm_path/\"\n \t\t\t\tclear_local_git_env\n-\t\t\t\t# we make $path available to scripts ...\n-\t\t\t\tpath=$sm_path\n \t\t\t\tcd \"$sm_path\" &&\n+\t\t\t\tsm_path=$(relative_path \"$sm_path\") &&\n+\t\t\t\t# we make $path available to scripts ...\n+\t\t\t\tpath=$sm_path &&\n \t\t\t\teval \"$@\" &&\n \t\t\t\tif test -n \"$recursive\"\n \t\t\t\tthen\n \t\t\t\t\tcmd_foreach \"--recursive\" \"$@\"\n \t\t\t\tfi\n \t\t\t) <&3 3<&- ||\n-\t\t\tdie \"$(eval_gettext \"Stopping at '\\$prefix\\$sm_path'; script returned non-zero status.\")\"\n+\t\t\tdie \"$(eval_gettext \"Stopping at '\\$prefix\\$displaypath'; script returned non-zero status.\")\"\n \t\tfi\n \tdone\n }\n@@ -524,12 +579,14 @@ cmd_init()\n \t\tdie_if_unmatched \"$mode\"\n \t\tname=$(module_name \"$sm_path\") || exit\n \n+\t\tdisplaypath=$(relative_path \"$sm_path\")\n+\n \t\t# Copy url setting when it is not set yet\n \t\tif test -z \"$(git config \"submodule.$name.url\")\"\n \t\tthen\n \t\t\turl=$(git config -f .gitmodules submodule.\"$name\".url)\n \t\t\ttest -z \"$url\" &&\n-\t\t\tdie \"$(eval_gettext \"No url found for submodule path '\\$sm_path' in .gitmodules\")\"\n+\t\t\tdie \"$(eval_gettext \"No url found for submodule path '\\$displaypath' in .gitmodules\")\"\n \n \t\t\t# Possibly a url relative to parent\n \t\t\tcase \"$url\" in\n@@ -538,9 +595,9 @@ cmd_init()\n \t\t\t\t;;\n \t\t\tesac\n \t\t\tgit config submodule.\"$name\".url \"$url\" ||\n-\t\t\tdie \"$(eval_gettext \"Failed to register url for submodule path '\\$sm_path'\")\"\n+\t\t\tdie \"$(eval_gettext \"Failed to register url for submodule path '\\$displaypath'\")\"\n \n-\t\t\tsay \"$(eval_gettext \"Submodule '\\$name' (\\$url) registered for path '\\$sm_path'\")\"\n+\t\t\tsay \"$(eval_gettext \"Submodule '\\$name' (\\$url) registered for path '\\$displaypath'\")\"\n \t\tfi\n \n \t\t# Copy \"update\" setting when it is not set yet\n@@ -548,7 +605,7 @@ cmd_init()\n \t\ttest -z \"$upd\" ||\n \t\ttest -n \"$(git config submodule.\"$name\".update)\" ||\n \t\tgit config submodule.\"$name\".update \"$upd\" ||\n-\t\tdie \"$(eval_gettext \"Failed to register update mode for submodule path '\\$sm_path'\")\"\n+\t\tdie \"$(eval_gettext \"Failed to register update mode for submodule path '\\$displaypath'\")\"\n \tdone\n }\n \n@@ -594,27 +651,29 @@ cmd_deinit()\n \t\tdie_if_unmatched \"$mode\"\n \t\tname=$(module_name \"$sm_path\") || exit\n \n+\t\tdisplaypath=$(relative_path \"$sm_path\")\n+\n \t\t# Remove the submodule work tree (unless the user already did it)\n \t\tif test -d \"$sm_path\"\n \t\tthen\n \t\t\t# Protect submodules containing a .git directory\n \t\t\tif test -d \"$sm_path/.git\"\n \t\t\tthen\n-\t\t\t\techo >&2 \"$(eval_gettext \"Submodule work tree '\\$sm_path' contains a .git directory\")\"\n+\t\t\t\techo >&2 \"$(eval_gettext \"Submodule work tree '\\$displaypath' contains a .git directory\")\"\n \t\t\t\tdie \"$(eval_gettext \"(use 'rm -rf' if you really want to remove it including all of its history)\")\"\n \t\t\tfi\n \n \t\t\tif test -z \"$force\"\n \t\t\tthen\n \t\t\t\tgit rm -qn \"$sm_path\" ||\n-\t\t\t\tdie \"$(eval_gettext \"Submodule work tree '\\$sm_path' contains local modifications; use '-f' to discard them\")\"\n+\t\t\t\tdie \"$(eval_gettext \"Submodule work tree '\\$displaypath' contains local modifications; use '-f' to discard them\")\"\n \t\t\tfi\n \t\t\trm -rf \"$sm_path\" &&\n-\t\t\tsay \"$(eval_gettext \"Cleared directory '\\$sm_path'\")\" ||\n-\t\t\tsay \"$(eval_gettext \"Could not remove submodule work tree '\\$sm_path'\")\"\n+\t\t\tsay \"$(eval_gettext \"Cleared directory '\\$displaypath'\")\" ||\n+\t\t\tsay \"$(eval_gettext \"Could not remove submodule work tree '\\$displaypath'\")\"\n \t\tfi\n \n-\t\tmkdir \"$sm_path\" || say \"$(eval_gettext \"Could not create empty submodule directory '\\$sm_path'\")\"\n+\t\tmkdir \"$sm_path\" || say \"$(eval_gettext \"Could not create empty submodule directory '\\$displaypath'\")\"\n \n \t\t# Remove the .git/config entries (unless the user already did it)\n \t\tif test -n \"$(git config --get-regexp submodule.\"$name\\.\")\"\n@@ -623,7 +682,7 @@ cmd_deinit()\n \t\t\t# the user later decides to init this submodule again\n \t\t\turl=$(git config submodule.\"$name\".url)\n \t\t\tgit config --remove-section submodule.\"$name\" 2>/dev/null &&\n-\t\t\tsay \"$(eval_gettext \"Submodule '\\$name' (\\$url) unregistered for path '\\$sm_path'\")\"\n+\t\t\tsay \"$(eval_gettext \"Submodule '\\$name' (\\$url) unregistered for path '\\$displaypath'\")\"\n \t\tfi\n \tdone\n }\n@@ -717,9 +776,11 @@ cmd_update()\n \t\t\tupdate_module=$(git config submodule.\"$name\".update)\n \t\tfi\n \n+\t\tdisplaypath=$(relative_path \"$prefix$sm_path\")\n+\n \t\tif test \"$update_module\" = \"none\"\n \t\tthen\n-\t\t\techo \"Skipping submodule '$prefix$sm_path'\"\n+\t\t\techo \"Skipping submodule '$displaypath'\"\n \t\t\tcontinue\n \t\tfi\n \n@@ -728,7 +789,7 @@ cmd_update()\n \t\t\t# Only mention uninitialized submodules when its\n \t\t\t# path have been specified\n \t\t\ttest \"$#\" != \"0\" &&\n-\t\t\tsay \"$(eval_gettext \"Submodule path '\\$prefix\\$sm_path' not initialized\n+\t\t\tsay \"$(eval_gettext \"Submodule path '\\$displaypath' not initialized\n Maybe you want to use 'update --init'?\")\"\n \t\t\tcontinue\n \t\tfi\n@@ -741,7 +802,7 @@ Maybe you want to use 'update --init'?\")\"\n \t\telse\n \t\t\tsubsha1=$(clear_local_git_env; cd \"$sm_path\" &&\n \t\t\t\tgit rev-parse --verify HEAD) ||\n-\t\t\tdie \"$(eval_gettext \"Unable to find current revision in submodule path '\\$prefix\\$sm_path'\")\"\n+\t\t\tdie \"$(eval_gettext \"Unable to find current revision in submodule path '\\$displaypath'\")\"\n \t\tfi\n \n \t\tif test -n \"$remote\"\n@@ -774,7 +835,7 @@ Maybe you want to use 'update --init'?\")\"\n \t\t\t\t(clear_local_git_env; cd \"$sm_path\" &&\n \t\t\t\t\t( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&\n \t\t\t\t\t test -z \"$rev\") || git-fetch)) ||\n-\t\t\t\tdie \"$(eval_gettext \"Unable to fetch in submodule path '\\$prefix\\$sm_path'\")\"\n+\t\t\t\tdie \"$(eval_gettext \"Unable to fetch in submodule path '\\$displaypath'\")\"\n \t\t\tfi\n \n \t\t\t# Is this something we just cloned?\n@@ -788,20 +849,20 @@ Maybe you want to use 'update --init'?\")\"\n \t\t\tcase \"$update_module\" in\n \t\t\trebase)\n \t\t\t\tcommand=\"git rebase\"\n-\t\t\t\tdie_msg=\"$(eval_gettext \"Unable to rebase '\\$sha1' in submodule path '\\$prefix\\$sm_path'\")\"\n-\t\t\t\tsay_msg=\"$(eval_gettext \"Submodule path '\\$prefix\\$sm_path': rebased into '\\$sha1'\")\"\n+\t\t\t\tdie_msg=\"$(eval_gettext \"Unable to rebase '\\$sha1' in submodule path '\\$displaypath'\")\"\n+\t\t\t\tsay_msg=\"$(eval_gettext \"Submodule path '\\$displaypath': rebased into '\\$sha1'\")\"\n \t\t\t\tmust_die_on_failure=yes\n \t\t\t\t;;\n \t\t\tmerge)\n \t\t\t\tcommand=\"git merge\"\n-\t\t\t\tdie_msg=\"$(eval_gettext \"Unable to merge '\\$sha1' in submodule path '\\$prefix\\$sm_path'\")\"\n-\t\t\t\tsay_msg=\"$(eval_gettext \"Submodule path '\\$prefix\\$sm_path': merged in '\\$sha1'\")\"\n+\t\t\t\tdie_msg=\"$(eval_gettext \"Unable to merge '\\$sha1' in submodule path '\\$displaypath'\")\"\n+\t\t\t\tsay_msg=\"$(eval_gettext \"Submodule path '\\$displaypath': merged in '\\$sha1'\")\"\n \t\t\t\tmust_die_on_failure=yes\n \t\t\t\t;;\n \t\t\t*)\n \t\t\t\tcommand=\"git checkout $subforce -q\"\n-\t\t\t\tdie_msg=\"$(eval_gettext \"Unable to checkout '\\$sha1' in submodule path '\\$prefix\\$sm_path'\")\"\n-\t\t\t\tsay_msg=\"$(eval_gettext \"Submodule path '\\$prefix\\$sm_path': checked out '\\$sha1'\")\"\n+\t\t\t\tdie_msg=\"$(eval_gettext \"Unable to checkout '\\$sha1' in submodule path '\\$displaypath'\")\"\n+\t\t\t\tsay_msg=\"$(eval_gettext \"Submodule path '\\$displaypath': checked out '\\$sha1'\")\"\n \t\t\t\t;;\n \t\t\tesac\n \n@@ -828,7 +889,7 @@ Maybe you want to use 'update --init'?\")\"\n \t\t\tres=$?\n \t\t\tif test $res -gt 0\n \t\t\tthen\n-\t\t\t\tdie_msg=\"$(eval_gettext \"Failed to recurse into submodule path '\\$prefix\\$sm_path'\")\"\n+\t\t\t\tdie_msg=\"$(eval_gettext \"Failed to recurse into submodule path '\\$displaypath'\")\"\n \t\t\t\tif test $res -eq 1\n \t\t\t\tthen\n \t\t\t\t\terr=\"${err};$die_msg\"\n@@ -942,6 +1003,7 @@ cmd_summary() {\n \tfi\n \n \tcd_to_toplevel\n+\teval \"set $(git rev-parse --sq --prefix \"$wt_prefix\" -- \"$@\")\"\n \t# Get modified modules cared by user\n \tmodules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- \"$@\" |\n \t\tsane_egrep '^:([0-7]* )?160000' |\n@@ -991,16 +1053,18 @@ cmd_summary() {\n \t\t! GIT_DIR=\"$name/.git\" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&\n \t\tmissing_dst=t\n \n+\t\tdisplay_name=$(relative_path \"$name\")\n+\n \t\ttotal_commits=\n \t\tcase \"$missing_src,$missing_dst\" in\n \t\tt,)\n-\t\t\terrmsg=\"$(eval_gettext \"  Warn: \\$name doesn't contain commit \\$sha1_src\")\"\n+\t\t\terrmsg=\"$(eval_gettext \"  Warn: \\$display_name doesn't contain commit \\$sha1_src\")\"\n \t\t\t;;\n \t\t,t)\n-\t\t\terrmsg=\"$(eval_gettext \"  Warn: \\$name doesn't contain commit \\$sha1_dst\")\"\n+\t\t\terrmsg=\"$(eval_gettext \"  Warn: \\$display_name doesn't contain commit \\$sha1_dst\")\"\n \t\t\t;;\n \t\tt,t)\n-\t\t\terrmsg=\"$(eval_gettext \"  Warn: \\$name doesn't contain commits \\$sha1_src and \\$sha1_dst\")\"\n+\t\t\terrmsg=\"$(eval_gettext \"  Warn: \\$display_name doesn't contain commits \\$sha1_src and \\$sha1_dst\")\"\n \t\t\t;;\n \t\t*)\n \t\t\terrmsg=\n@@ -1029,12 +1093,12 @@ cmd_summary() {\n \t\t\tsubmodule=\"$(gettext \"submodule\")\"\n \t\t\tif test $mod_dst = 160000\n \t\t\tthen\n-\t\t\t\techo \"* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:\"\n+\t\t\t\techo \"* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:\"\n \t\t\telse\n-\t\t\t\techo \"* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:\"\n+\t\t\t\techo \"* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:\"\n \t\t\tfi\n \t\telse\n-\t\t\techo \"* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:\"\n+\t\t\techo \"* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:\"\n \t\tfi\n \t\tif test -n \"$errmsg\"\n \t\tthen\n@@ -1118,7 +1182,7 @@ cmd_status()\n \t\tdie_if_unmatched \"$mode\"\n \t\tname=$(module_name \"$sm_path\") || exit\n \t\turl=$(git config submodule.\"$name\".url)\n-\t\tdisplaypath=\"$prefix$sm_path\"\n+\t\tdisplaypath=$(relative_path \"$prefix$sm_path\")\n \t\tif test \"$stage\" = U\n \t\tthen\n \t\t\tsay \"U$sha1 $displaypath\"\n@@ -1213,7 +1277,8 @@ cmd_sync()\n \n \t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n \t\tthen\n-\t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$prefix\\$sm_path'\")\"\n+\t\t\tdisplaypath=$(relative_path \"$prefix$sm_path\")\n+\t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n \t\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n \n \t\t\tif test -e \"$sm_path\"/.git\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex ff26535..a38fd92 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -212,6 +212,32 @@ test_expect_success 'submodule add with ./, /.. and // in path' '\n \ttest_cmp empty untracked\n '\n \n+test_expect_success 'submodule add in subdirectory' '\n+\techo \"refs/heads/master\" >expect &&\n+\t>empty &&\n+\n+\tmkdir addtest/sub &&\n+\t(\n+\t\tcd addtest/sub &&\n+\t\tgit submodule add \"$submodurl\" ../realsubmod3 &&\n+\t\tgit submodule init\n+\t) &&\n+\n+\trm -f heads head untracked &&\n+\tinspect addtest/realsubmod3 ../.. &&\n+\ttest_cmp expect heads &&\n+\ttest_cmp expect head &&\n+\ttest_cmp empty untracked\n+'\n+\n+test_expect_success 'submodule add in subdirectory with relative path should fail' '\n+\t(\n+\t\tcd addtest/sub &&\n+\t\ttest_must_fail git submodule add ../../ submod3 2>../../output.err\n+\t) &&\n+\ttest_i18ngrep toplevel output.err\n+'\n+\n test_expect_success 'setup - add an example entry to .gitmodules' '\n \tGIT_CONFIG=.gitmodules \\\n \tgit config submodule.example.url git://example.com/init.git\n@@ -319,6 +345,26 @@ test_expect_success 'status should be \"up-to-date\" after update' '\n \tgrep \"^ $rev1\" list\n '\n \n+test_expect_success 'status \"up-to-date\" from subdirectory' '\n+\tmkdir -p sub &&\n+\t(\n+\t\tcd sub &&\n+\t\tgit submodule status >../list\n+\t) &&\n+\tgrep \"^ $rev1\" list &&\n+\tgrep \"\\\\.\\\\./init\" list\n+'\n+\n+test_expect_success 'status \"up-to-date\" from subdirectory with path' '\n+\tmkdir -p sub &&\n+\t(\n+\t\tcd sub &&\n+\t\tgit submodule status ../init >../list\n+\t) &&\n+\tgrep \"^ $rev1\" list &&\n+\tgrep \"\\\\.\\\\./init\" list\n+'\n+\n test_expect_success 'status should be \"modified\" after submodule commit' '\n \t(\n \t\tcd init &&\n@@ -399,6 +445,25 @@ test_expect_success 'update --init' '\n \tgit rev-parse --resolve-git-dir init/.git\n '\n \n+test_expect_success 'update --init from subdirectory' '\n+\tmv init init2 &&\n+\tgit config -f .gitmodules submodule.example.url \"$(pwd)/init2\" &&\n+\tgit config --remove-section submodule.example &&\n+\ttest_must_fail git config submodule.example.url &&\n+\n+\tmkdir -p sub &&\n+\t(\n+\t\tcd sub &&\n+\t\tgit submodule update ../init >update.out &&\n+\t\tcat update.out &&\n+\t\ttest_i18ngrep \"not initialized\" update.out &&\n+\t\ttest_must_fail git rev-parse --resolve-git-dir ../init/.git &&\n+\n+\t\tgit submodule update --init ../init\n+\t) &&\n+\tgit rev-parse --resolve-git-dir init/.git\n+'\n+\n test_expect_success 'do not add files from a submodule' '\n \n \tgit reset --hard &&\n@@ -772,6 +837,21 @@ test_expect_success 'submodule deinit should remove the whole submodule section\n \trmdir init\n '\n \n+test_expect_success 'submodule deinit from subdirectory' '\n+\tgit submodule update --init &&\n+\tgit config submodule.example.foo bar &&\n+\tmkdir -p sub &&\n+\t(\n+\t\tcd sub &&\n+\t\tgit submodule deinit ../init >../output\n+\t) &&\n+\tgrep \"\\\\.\\\\./init\" output &&\n+\ttest -z \"$(git config --get-regexp \"submodule\\.example\\.\")\" &&\n+\ttest -n \"$(git config --get-regexp \"submodule\\.example2\\.\")\" &&\n+\ttest -f example2/.git &&\n+\trmdir init\n+'\n+\n test_expect_success 'submodule deinit . deinits all initialized submodules' '\n \tgit submodule update --init &&\n \tgit config submodule.example.foo bar &&\ndiff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh\nindex c328726..ac2434c 100755\n--- a/t/t7401-submodule-summary.sh\n+++ b/t/t7401-submodule-summary.sh\n@@ -45,6 +45,42 @@ EOF\n \ttest_cmp expected actual\n \"\n \n+test_expect_success 'added submodule (subdirectory)' \"\n+\tmkdir sub &&\n+\t(\n+\t\tcd sub &&\n+\t\tgit submodule summary >../actual\n+\t) &&\n+\tcat >expected <<-EOF &&\n+* ../sm1 0000000...$head1 (2):\n+  > Add foo2\n+\n+EOF\n+\ttest_cmp expected actual\n+\"\n+\n+test_expect_success 'added submodule (subdirectory only)' \"\n+\t(\n+\t\tcd sub &&\n+\t\tgit submodule summary . >../actual\n+\t) &&\n+\t>expected &&\n+\ttest_cmp expected actual\n+\"\n+\n+test_expect_success 'added submodule (subdirectory with explicit path)' \"\n+\t(\n+\t\tcd sub &&\n+\t\tgit submodule summary ../sm1 >../actual\n+\t) &&\n+\tcat >expected <<-EOF &&\n+* ../sm1 0000000...$head1 (2):\n+  > Add foo2\n+\n+EOF\n+\ttest_cmp expected actual\n+\"\n+\n commit_file sm1 &&\n head2=$(add_file sm1 foo3)\n \ndiff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh\nindex bf90098..79bc135 100755\n--- a/t/t7403-submodule-sync.sh\n+++ b/t/t7403-submodule-sync.sh\n@@ -61,6 +61,19 @@ test_expect_success 'change submodule' '\n \t)\n '\n \n+reset_submodule_urls () {\n+\tlocal root\n+\troot=$(pwd) &&\n+\t(\n+\t\tcd super-clone/submodule &&\n+\t\tgit config remote.origin.url \"$root/submodule\"\n+\t) &&\n+\t(\n+\t\tcd super-clone/submodule/sub-submodule &&\n+\t\tgit config remote.origin.url \"$root/submodule\"\n+\t)\n+}\n+\n test_expect_success 'change submodule url' '\n \t(\n \t\tcd super &&\n@@ -132,6 +145,65 @@ test_expect_success '\"git submodule sync --recursive\" should update all submodul\n \t)\n '\n \n+test_expect_success 'reset submodule URLs' '\n+\treset_submodule_urls super-clone\n+'\n+\n+test_expect_success '\"git submodule sync\" should update submodule URLs - subdirectory' '\n+\t(\n+\t\tcd super-clone &&\n+\t\tgit pull --no-recurse-submodules &&\n+\t\tmkdir -p sub &&\n+\t\tcd sub &&\n+\t\tgit submodule sync >../../output\n+\t) &&\n+\tgrep \"\\\\.\\\\./submodule\" output &&\n+\ttest -d \"$(\n+\t\tcd super-clone/submodule &&\n+\t\tgit config remote.origin.url\n+\t)\" &&\n+\ttest ! -d \"$(\n+\t\tcd super-clone/submodule/sub-submodule &&\n+\t\tgit config remote.origin.url\n+\t)\" &&\n+\t(\n+\t\tcd super-clone/submodule &&\n+\t\tgit checkout master &&\n+\t\tgit pull\n+\t) &&\n+\t(\n+\t\tcd super-clone &&\n+\t\ttest -d \"$(git config submodule.submodule.url)\"\n+\t)\n+'\n+\n+test_expect_success '\"git submodule sync --recursive\" should update all submodule URLs - subdirectory' '\n+\t(\n+\t\tcd super-clone &&\n+\t\t(\n+\t\t\tcd submodule &&\n+\t\t\tgit pull --no-recurse-submodules\n+\t\t) &&\n+\t\tmkdir -p sub &&\n+\t\tcd sub &&\n+\t\tgit submodule sync --recursive >../../output\n+\t) &&\n+\tgrep \"\\\\.\\\\./submodule/sub-submodule\" output &&\n+\ttest -d \"$(\n+\t\tcd super-clone/submodule &&\n+\t\tgit config remote.origin.url\n+\t)\" &&\n+\ttest -d \"$(\n+\t\tcd super-clone/submodule/sub-submodule &&\n+\t\tgit config remote.origin.url\n+\t)\" &&\n+\t(\n+\t\tcd super-clone/submodule/sub-submodule &&\n+\t\tgit checkout master &&\n+\t\tgit pull\n+\t)\n+'\n+\n test_expect_success '\"git submodule sync\" should update known submodule URLs' '\n \t(\n \t\tcd empty-clone &&\ndiff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh\nindex a4ffea0..cdb0538 100755\n--- a/t/t7406-submodule-update.sh\n+++ b/t/t7406-submodule-update.sh\n@@ -80,6 +80,21 @@ test_expect_success 'submodule update detaching the HEAD ' '\n \t)\n '\n \n+test_expect_success 'submodule update from subdirectory' '\n+\t(cd super/submodule &&\n+\t git reset --hard HEAD~1\n+\t) &&\n+\tmkdir super/sub &&\n+\t(cd super/sub &&\n+\t (cd ../submodule &&\n+\t  compare_head\n+\t ) &&\n+\t git submodule update ../submodule &&\n+\t cd ../submodule &&\n+\t ! compare_head\n+\t)\n+'\n+\n apos=\"'\";\n test_expect_success 'submodule update does not fetch already present commits' '\n \t(cd submodule &&\ndiff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh\nindex 107b4b7..91d4fd1 100755\n--- a/t/t7407-submodule-foreach.sh\n+++ b/t/t7407-submodule-foreach.sh\n@@ -80,6 +80,22 @@ test_expect_success 'test basic \"submodule foreach\" usage' '\n \ttest_i18ncmp expect actual\n '\n \n+cat >expect <<EOF\n+Entering '../sub1'\n+$pwd/clone-foo1-../sub1-$sub1sha1\n+Entering '../sub3'\n+$pwd/clone-foo3-../sub3-$sub3sha1\n+EOF\n+\n+test_expect_success 'test \"submodule foreach\" from subdirectory' '\n+\tmkdir clone/sub &&\n+\t(\n+\t\tcd clone/sub &&\n+\t\tgit submodule foreach \"echo \\$toplevel-\\$name-\\$sm_path-\\$sha1\" >../../actual\n+\t) &&\n+\ttest_i18ncmp expect actual\n+'\n+\n test_expect_success 'setup nested submodules' '\n \tgit clone submodule nested1 &&\n \tgit clone submodule nested2 &&\n-- \n1.8.3.779.g691e267\n"},{"id":"221102","messageId":"51BF748F.7070708@web.de","threadId":"34164","inReplyTo":"cover.1371391740.git.john@keeping.me.uk","subject":"Re: [PATCH v4 0/6] submodule: drop the top-level requirement","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2013-06-17T20:41:51Z","receivedAt":"2013-06-17T20:41:51Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 16.06.2013 16:18, schrieb John Keeping:\n> Changes since v3:\n> \n> * There are four new patches, three of which are style fixes for\n>   existing tests and one fixes an existing error message to return a\n>   more accurate path when recursing.\n> \n> * You now cannot run \"git submodule add <relative URL>\" from a\n>   subdirectory.  Because the interpretation of the URL changes depending\n>   on whether or not remote.origin.url is configured, I have decided to\n>   just ban this for now.  If someone comes up with a sensible way to\n>   handle this then we can lift this restriction later.\n> \n> * The \"path\" variable exported in \"submodule foreach\" now uses the\n>   relative path and matches the \"sm_path\" variable.\n> \n> * I audited the code again and fixed a few more cases that weren't\n>   printing relative paths (notably \"submodule init\" and \"submodule\n>   foreach\").\n> \n> * More tests.\n\nThanks for working on this! This series is looking good to me.\n\n> John Keeping (6):\n>   t7401: make indentation consistent\n>   t7403: modernize style\n>   t7403: add missing && chaining\n>   submodule: show full path in error message\n>   rev-parse: add --prefix option\n>   submodule: drop the top-level requirement\n> \n>  Documentation/git-rev-parse.txt |  16 ++\n>  builtin/rev-parse.c             |  24 ++-\n>  git-submodule.sh                | 135 ++++++++++----\n>  t/t1513-rev-parse-prefix.sh     |  96 ++++++++++\n>  t/t7400-submodule-basic.sh      |  80 +++++++++\n>  t/t7401-submodule-summary.sh    | 116 +++++++-----\n>  t/t7403-submodule-sync.sh       | 388 ++++++++++++++++++++++++++--------------\n>  t/t7406-submodule-update.sh     |  15 ++\n>  t/t7407-submodule-foreach.sh    |  16 ++\n>  9 files changed, 673 insertions(+), 213 deletions(-)\n>  create mode 100755 t/t1513-rev-parse-prefix.sh\n> \n"}]}