{"thread":{"id":"25624","subject":"[PATCH 1/2] submodule: preserve all arguments exactly when recursing","startedAt":"2010-11-03T04:34:41Z","lastAt":"2010-11-05T22:38:40Z","messageCount":17,"participants":["Kevin Ballard","Jonathan Nieder","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"155019","messageId":"1288758882-77286-1-git-send-email-kevin@sb.org","threadId":"25624","inReplyTo":null,"subject":"[PATCH 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T04:34:41Z","receivedAt":"2010-11-03T04:34:41Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"When performing a recursive status or update, any argments with whitespace\nwould be split along that whitespace when passed to the recursive invocation\nof the update or status command.\n\nThis is caused by the special handling that sh provides to the $@ variable.\nStatus and update stored \"$@\" into a separate variable, and passed that\nvariable to the recursive invocation. Unfortunately, the special handling\nafforded to $@ isn't given to this new variable, and word-breaking occurs\nalong whitespace boundaries.\n\nWe can work around this by taking advantage of an easy technique to quote\nany arbitrary string in the shell. Because single-quoted strings don't\nsupport backslash-escapes, any arbitrary string can be quoted by wrapping\nit in single-quotes and replacing any single-quotes inside the string with\nthe sequence '\\''.\n\nThis commit introduces a new shell function quote_words that uses the quote\ntrick to produce a string containing the quoted version of all its\narguments. This string can then be used with `set -` to restore the original\nvalue of $@. This shell function is used in cmd_status and in cmd_update\nto store the original value of $@, which is then restored before the\nrecursive invocation takes place.\n\nSigned-off-by: Kevin Ballard <kevin@sb.org>\n---\nI tried to write tests for this, but there are only two ways to get args\nwith spaces to be accepted and passed to the recursive invocation.\nThe first is via the --reference flag, but I don't think it really makes\nsense to use that flag in connection with --recursive and was not comfortable\nusing it in a test. The second is as a pathname after the flags, but it\nalso doesn't make sense to pass these to recursive invocations, and in fact\nthe subsequent commit fixes it so the pathnames are not passed to recursive\ninvocations.\n\nThat said, despite the lack of tests I still believe this is a worthwhile\nchange, and it will certainly future-proof the command in case new flags\nare added. It's also a reasonable model for how to handle this problem\nin other shell commands.\n git-submodule.sh |   43 +++++++++++++++++++++++++++++++++++++++----\n 1 files changed, 39 insertions(+), 4 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 9ebbab7..ec7a5e4 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -64,6 +64,39 @@ module_list()\n }\n \n #\n+# Emit a quoted version of the all argument suitable for passing to `eval`\n+# $@ = words to quote\n+#\n+# This is intended to be used like the following:\n+#   orig_args=\"$(quote_words \"$@\")\"\n+#   # do some work that includes calling shift\n+#   eval \"set - $orig_args\"\n+#   # now $@ has been restored, suitable for passing to another command\n+#\n+# Note that you cannot simply save off $@ into another variable because\n+# the shell gives $@ and $* special handling in parameter expansion\n+#\n+quote_words ()\n+{\n+\twhile test $# -ne 0; do\n+\t\t# this can be done using sed like so:\n+\t\t#   printf \"'%s'\" \"$(printf \"%s\" \"$1\" | sed -e \"s/'/'\\\\\\\\''/g\")\"\n+\t\t# but in an attempt to avoid spawning a process for every argument, we'll\n+\t\t# just use the prefix/suffix pattern matching stuff\n+\t\tlocal word= suffix=\"$1\" prefix=\n+\t\twhile test -n \"$suffix\"\n+\t\tdo\n+\t\t\tprefix=\"${suffix%%\\'*}\"\n+\t\t\ttest \"$prefix\" != \"$suffix\" || break\n+\t\t\tsuffix=\"${suffix#*\\'}\"\n+\t\t\tword=\"$word$prefix'\\\\''\"\n+\t\tdone\n+\t\tprintf \"'%s' \" \"$word$suffix\"\n+\t\tshift\n+\tdone\n+}\n+\n+#\n # Map submodule path to submodule name\n #\n # $1 = path\n@@ -374,7 +407,7 @@ cmd_init()\n cmd_update()\n {\n \t# parse $args after \"submodule ... update\".\n-\torig_args=\"$@\"\n+\torig_args=\"$(quote_words \"$@\")\"\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -500,7 +533,8 @@ cmd_update()\n \n \t\tif test -n \"$recursive\"\n \t\tthen\n-\t\t\t(clear_local_git_env; cd \"$path\" && cmd_update $orig_args) ||\n+\t\t\teval \"set - $orig_args\"\n+\t\t\t(clear_local_git_env; cd \"$path\" && cmd_update \"$@\") ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n \tdone\n@@ -733,7 +767,7 @@ cmd_summary() {\n cmd_status()\n {\n \t# parse $args after \"submodule ... status\".\n-\torig_args=\"$@\"\n+\torig_args=\"$(quote_words \"$@\")\"\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -788,9 +822,10 @@ cmd_status()\n \t\tthen\n \t\t\t(\n \t\t\t\tprefix=\"$displaypath/\"\n+\t\t\t\teval \"set - $orig_args\"\n \t\t\t\tclear_local_git_env\n \t\t\t\tcd \"$path\" &&\n-\t\t\t\tcmd_status $orig_args\n+\t\t\t\tcmd_status \"$@\"\n \t\t\t) ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n-- \n1.7.3.2.200.ga1bd\n"},{"id":"155020","messageId":"1288758882-77286-2-git-send-email-kevin@sb.org","threadId":"25624","inReplyTo":"1288758882-77286-1-git-send-email-kevin@sb.org","subject":"[PATCH 2/2] submodule: only preserve flags across recursive status/update invocations","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T04:34:42Z","receivedAt":"2010-11-03T04:34:42Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"Recursive invocations of submodule update/status preserve all arguments\nin the recursive invocation. This tends to cause undesired behavior when\nthose arguments include the name of a submodule, as it tries to recurse\ninto a nested submodule with the same name rather than recursing into all\nchild submodules of the named submodule.\n\nThis commit changes the argument preservation to only preserve flags.\nWhen specifying a submodule name on the command-line, all child submodules\nof that named submodule will be recursed into correctly, and it will not\nattempt to recurse into a phantom nested submodule with the same name\nas its parent.\n\nSigned-off-by: Kevin Ballard <kevin@sb.org>\n---\nThis commit was inspired by my coworker, who tried to run `git submodule\nupdate --recursive molecules` (where molecules is the name of a submodule)\nand received the rather unexpected error\n\n  error: pathspec 'molecules' did not match any file(s) known to git.\n  Did you forget to 'git add'?\n\n git-submodule.sh             |   21 +++++++++------------\n t/t7407-submodule-foreach.sh |   19 +++++++++++++++++++\n 2 files changed, 28 insertions(+), 12 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex ec7a5e4..52c693c 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -407,41 +407,35 @@ cmd_init()\n cmd_update()\n {\n \t# parse $args after \"submodule ... update\".\n-\torig_args=\"$(quote_words \"$@\")\"\n+\torig_flags=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n \t\t-q|--quiet)\n-\t\t\tshift\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-i|--init)\n \t\t\tinit=1\n-\t\t\tshift\n \t\t\t;;\n \t\t-N|--no-fetch)\n-\t\t\tshift\n \t\t\tnofetch=1\n \t\t\t;;\n \t\t-r|--rebase)\n-\t\t\tshift\n \t\t\tupdate=\"rebase\"\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\tshift 2\n+\t\t\torig_flags=\"$orig_flags $(quote_words \"$1\")\"\n+\t\t\tshift\n \t\t\t;;\n \t\t--reference=*)\n \t\t\treference=\"$1\"\n-\t\t\tshift\n \t\t\t;;\n \t\t-m|--merge)\n-\t\t\tshift\n \t\t\tupdate=\"merge\"\n \t\t\t;;\n \t\t--recursive)\n-\t\t\tshift\n \t\t\trecursive=1\n \t\t\t;;\n \t\t--)\n@@ -455,6 +449,8 @@ cmd_update()\n \t\t\tbreak\n \t\t\t;;\n \t\tesac\n+\t\torig_flags=\"$orig_flags $(quote_words \"$1\")\"\n+\t\tshift\n \tdone\n \n \tif test -n \"$init\"\n@@ -533,7 +529,7 @@ cmd_update()\n \n \t\tif test -n \"$recursive\"\n \t\tthen\n-\t\t\teval \"set - $orig_args\"\n+\t\t\teval \"set - $orig_flags\"\n \t\t\t(clear_local_git_env; cd \"$path\" && cmd_update \"$@\") ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n@@ -767,7 +763,7 @@ cmd_summary() {\n cmd_status()\n {\n \t# parse $args after \"submodule ... status\".\n-\torig_args=\"$(quote_words \"$@\")\"\n+\torig_flags=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -791,6 +787,7 @@ cmd_status()\n \t\t\tbreak\n \t\t\t;;\n \t\tesac\n+\t\torig_flags=\"$orig_flags $(quote_words \"$1\")\"\n \t\tshift\n \tdone\n \n@@ -822,7 +819,7 @@ cmd_status()\n \t\tthen\n \t\t\t(\n \t\t\t\tprefix=\"$displaypath/\"\n-\t\t\t\teval \"set - $orig_args\"\n+\t\t\t\teval \"set - $orig_flags\"\n \t\t\t\tclear_local_git_env\n \t\t\t\tcd \"$path\" &&\n \t\t\t\tcmd_status \"$@\"\ndiff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh\nindex 905a8ba..2d5a855 100755\n--- a/t/t7407-submodule-foreach.sh\n+++ b/t/t7407-submodule-foreach.sh\n@@ -238,4 +238,23 @@ test_expect_success 'use \"git clone --recursive\" to checkout all submodules' '\n \ttest -d clone4/nested1/nested2/nested3/submodule/.git\n '\n \n+test_expect_success 'use \"update --recursive nested1\" to checkout all submodules rooted in nested1' '\n+\tgit clone super clone5 &&\n+\t(\n+\t\tcd clone5 &&\n+\t\ttest ! -d sub1/.git &&\n+\t\ttest ! -d sub2/.git &&\n+\t\ttest ! -d sub3/.git &&\n+\t\ttest ! -d nested1/.git &&\n+\t\tgit submodule update --init --recursive -- nested1 &&\n+\t\ttest ! -d sub1/.git &&\n+\t\ttest ! -d sub2/.git &&\n+\t\ttest ! -d sub3/.git &&\n+\t\ttest -d nested1/.git &&\n+\t\ttest -d nested1/nested2/.git &&\n+\t\ttest -d nested1/nested2/nested3/.git &&\n+\t\ttest -d nested1/nested2/nested3/submodule/.git\n+\t)\n+'\n+\n test_done\n-- \n1.7.3.2.200.ga1bd\n"},{"id":"155021","messageId":"20101103043725.GA10311@burratino","threadId":"25624","inReplyTo":"1288758882-77286-1-git-send-email-kevin@sb.org","subject":"Re: [PATCH 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-11-03T04:37:25Z","receivedAt":"2010-11-03T04:37:25Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi Kevin,\n\nKevin Ballard wrote:\n\n>            It's also a reasonable model for how to handle this problem\n> in other shell commands.\n\nThis caught my attention. :)\n\n> +# Emit a quoted version of the all argument suitable for passing to `eval`\n> +# $@ = words to quote\n> +#\n> +# This is intended to be used like the following:\n> +#   orig_args=\"$(quote_words \"$@\")\"\n> +#   # do some work that includes calling shift\n> +#   eval \"set - $orig_args\"\n> +#   # now $@ has been restored, suitable for passing to another command\n> +#\n> +# Note that you cannot simply save off $@ into another variable because\n> +# the shell gives $@ and $* special handling in parameter expansion\n> +#\n> +quote_words ()\n\nHave you looked into \"git rev-parse --sq-quote\"?\n\nHope that helps,\nJonathan\n"},{"id":"155022","messageId":"5BE96A08-B8AB-4041-ABF2-7095EB5DD585@sb.org","threadId":"25624","inReplyTo":"20101103043725.GA10311@burratino","subject":"Re: [PATCH 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T04:40:18Z","receivedAt":"2010-11-03T04:40:18Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"On Nov 2, 2010, at 9:37 PM, Jonathan Nieder wrote:\n\n> Hi Kevin,\n> \n> Kevin Ballard wrote:\n> \n>>           It's also a reasonable model for how to handle this problem\n>> in other shell commands.\n> \n> This caught my attention. :)\n> \n>> +# Emit a quoted version of the all argument suitable for passing to `eval`\n>> +# $@ = words to quote\n>> +#\n>> +# This is intended to be used like the following:\n>> +#   orig_args=\"$(quote_words \"$@\")\"\n>> +#   # do some work that includes calling shift\n>> +#   eval \"set - $orig_args\"\n>> +#   # now $@ has been restored, suitable for passing to another command\n>> +#\n>> +# Note that you cannot simply save off $@ into another variable because\n>> +# the shell gives $@ and $* special handling in parameter expansion\n>> +#\n>> +quote_words ()\n> \n> Have you looked into \"git rev-parse --sq-quote\"?\n\nWell crud, I wish I'd seen that before. Looks like it does pretty much the\nexact same thing as my quote_words function. I'll send out another patch\nthat uses this instead of quote_words. Thanks for the info!\n\n-Kevin Ballard"},{"id":"155024","messageId":"1288760740-10075-1-git-send-email-kevin@sb.org","threadId":"25624","inReplyTo":"5BE96A08-B8AB-4041-ABF2-7095EB5DD585@sb.org","subject":"[PATCHv2 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T05:05:39Z","receivedAt":"2010-11-03T05:05:39Z","isPatch":false,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"When performing a recursive status or update, any argments with whitespace\nwould be split along that whitespace when passed to the recursive invocation\nof the update or status command.\n\nThis is caused by the special handling that sh provides to the $@ variable.\nStatus and update stored \"$@\" into a separate variable, and passed that\nvariable to the recursive invocation. Unfortunately, the special handling\nafforded to $@ isn't given to this new variable, and word-breaking occurs\nalong whitespace boundaries.\n\nWe can use $(git rev-parse --sq-quote \"$@\") to produce a string containing\na quoted version of all given args, suitable for passing to eval. We then\nrecurse using something like `eval cmd_status \"$orig_args\"` instead of the\nformer `cmd_status $orig_args`. This preserves all arguments exactly as\ngiven to the initial invocation of the command.\n\nHelped-By: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Kevin Ballard <kevin@sb.org>\n---\nThis patch ditches the quote_words function and uses\n`git rev-parse --sq-quote \"$@\"` instead, as suggested by Jonathan Nieder.\n git-submodule.sh |    8 ++++----\n 1 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 9ebbab7..543554b 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -374,7 +374,7 @@ cmd_init()\n cmd_update()\n {\n \t# parse $args after \"submodule ... update\".\n-\torig_args=\"$@\"\n+\torig_args=\"$(git rev-parse --sq-quote \"$@\")\"\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -500,7 +500,7 @@ cmd_update()\n \n \t\tif test -n \"$recursive\"\n \t\tthen\n-\t\t\t(clear_local_git_env; cd \"$path\" && cmd_update $orig_args) ||\n+\t\t\t(clear_local_git_env; cd \"$path\" && eval cmd_update \"$orig_args\") ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n \tdone\n@@ -733,7 +733,7 @@ cmd_summary() {\n cmd_status()\n {\n \t# parse $args after \"submodule ... status\".\n-\torig_args=\"$@\"\n+\torig_args=\"$(git rev-parse --sq-quote \"$@\")\"\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -790,7 +790,7 @@ cmd_status()\n \t\t\t\tprefix=\"$displaypath/\"\n \t\t\t\tclear_local_git_env\n \t\t\t\tcd \"$path\" &&\n-\t\t\t\tcmd_status $orig_args\n+\t\t\t\teval cmd_status \"$orig_args\"\n \t\t\t) ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n-- \n1.7.3.2.200.g479de\n"},{"id":"155025","messageId":"1288760740-10075-2-git-send-email-kevin@sb.org","threadId":"25624","inReplyTo":"5BE96A08-B8AB-4041-ABF2-7095EB5DD585@sb.org","subject":"[PATCHv2 2/2] submodule: only preserve flags across recursive status/update invocations","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T05:05:40Z","receivedAt":"2010-11-03T05:05:40Z","isPatch":false,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"Recursive invocations of submodule update/status preserve all arguments\nin the recursive invocation. This tends to cause undesired behavior when\nthose arguments include the name of a submodule, as it tries to recurse\ninto a nested submodule with the same name rather than recursing into all\nchild submodules of the named submodule.\n\nThis commit changes the argument preservation to only preserve flags.\nWhen specifying a submodule name on the command-line, all child submodules\nof that named submodule will be recursed into correctly, and it will not\nattempt to recurse into a phantom nested submodule with the same name\nas its parent.\n\nSigned-off-by: Kevin Ballard <kevin@sb.org>\n---\nI'm tempted to make this commit also omit the --reference flag in recursive\ncalls to cmd_update, as I don't believe it makes sense to use --reference\nin conjunction with --recursive, but it may be a better idea to simply\nproduce an error if both flags are used together.\n git-submodule.sh             |   19 ++++++++-----------\n t/t7407-submodule-foreach.sh |   19 +++++++++++++++++++\n 2 files changed, 27 insertions(+), 11 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 543554b..4fd8982 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -374,41 +374,35 @@ cmd_init()\n cmd_update()\n {\n \t# parse $args after \"submodule ... update\".\n-\torig_args=\"$(git rev-parse --sq-quote \"$@\")\"\n+\torig_flags=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n \t\t-q|--quiet)\n-\t\t\tshift\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-i|--init)\n \t\t\tinit=1\n-\t\t\tshift\n \t\t\t;;\n \t\t-N|--no-fetch)\n-\t\t\tshift\n \t\t\tnofetch=1\n \t\t\t;;\n \t\t-r|--rebase)\n-\t\t\tshift\n \t\t\tupdate=\"rebase\"\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\tshift 2\n+\t\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n+\t\t\tshift\n \t\t\t;;\n \t\t--reference=*)\n \t\t\treference=\"$1\"\n-\t\t\tshift\n \t\t\t;;\n \t\t-m|--merge)\n-\t\t\tshift\n \t\t\tupdate=\"merge\"\n \t\t\t;;\n \t\t--recursive)\n-\t\t\tshift\n \t\t\trecursive=1\n \t\t\t;;\n \t\t--)\n@@ -422,6 +416,8 @@ cmd_update()\n \t\t\tbreak\n \t\t\t;;\n \t\tesac\n+\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n+\t\tshift\n \tdone\n \n \tif test -n \"$init\"\n@@ -500,7 +496,7 @@ cmd_update()\n \n \t\tif test -n \"$recursive\"\n \t\tthen\n-\t\t\t(clear_local_git_env; cd \"$path\" && eval cmd_update \"$orig_args\") ||\n+\t\t\t(clear_local_git_env; cd \"$path\" && eval cmd_update \"$orig_flags\") ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n \tdone\n@@ -733,7 +729,7 @@ cmd_summary() {\n cmd_status()\n {\n \t# parse $args after \"submodule ... status\".\n-\torig_args=\"$(git rev-parse --sq-quote \"$@\")\"\n+\torig_flags=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -757,6 +753,7 @@ cmd_status()\n \t\t\tbreak\n \t\t\t;;\n \t\tesac\n+\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n \t\tshift\n \tdone\n \ndiff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh\nindex 905a8ba..2d5a855 100755\n--- a/t/t7407-submodule-foreach.sh\n+++ b/t/t7407-submodule-foreach.sh\n@@ -238,4 +238,23 @@ test_expect_success 'use \"git clone --recursive\" to checkout all submodules' '\n \ttest -d clone4/nested1/nested2/nested3/submodule/.git\n '\n \n+test_expect_success 'use \"update --recursive nested1\" to checkout all submodules rooted in nested1' '\n+\tgit clone super clone5 &&\n+\t(\n+\t\tcd clone5 &&\n+\t\ttest ! -d sub1/.git &&\n+\t\ttest ! -d sub2/.git &&\n+\t\ttest ! -d sub3/.git &&\n+\t\ttest ! -d nested1/.git &&\n+\t\tgit submodule update --init --recursive -- nested1 &&\n+\t\ttest ! -d sub1/.git &&\n+\t\ttest ! -d sub2/.git &&\n+\t\ttest ! -d sub3/.git &&\n+\t\ttest -d nested1/.git &&\n+\t\ttest -d nested1/nested2/.git &&\n+\t\ttest -d nested1/nested2/nested3/.git &&\n+\t\ttest -d nested1/nested2/nested3/submodule/.git\n+\t)\n+'\n+\n test_done\n-- \n1.7.3.2.200.g479de\n"},{"id":"155026","messageId":"20101103052837.GB10631@burratino","threadId":"25624","inReplyTo":"1288760740-10075-1-git-send-email-kevin@sb.org","subject":"Re: [PATCHv2 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-11-03T05:28:37Z","receivedAt":"2010-11-03T05:28:37Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Kevin Ballard wrote:\n\n> When performing a recursive status or update, any argments with whitespace\n> would be split along that whitespace when passed to the recursive invocation\n> of the update or status command.\n> \n> This is caused by the special handling that sh provides to the $@ variable.\n> Status and update stored \"$@\" into a separate variable, and passed that\n> variable to the recursive invocation. Unfortunately, the special handling\n> afforded to $@ isn't given to this new variable, and word-breaking occurs\n> along whitespace boundaries.\n> \n> We can use $(git rev-parse --sq-quote \"$@\") to produce a string containing\n> a quoted version of all given args, suitable for passing to eval. We then\n> recurse using something like `eval cmd_status \"$orig_args\"` instead of the\n> former `cmd_status $orig_args`. This preserves all arguments exactly as\n> given to the initial invocation of the command.\n\nProbably it is because it is late hear, but I find myself intimidated\nby the block of explanatory text.  Maybe an example like\n\n\tEnvironment variables only hold strings, not lists of parameters,\n\tso $orig_args after\n\n\t\torig_args=\"$@\"\n\n\tfails to remember where each parameter starts and ends, if\n\tsome include whitespace.  So\n\n\t\tgit submodule update \\\n\t\t\t--reference='/var/lib/common objects.git' \\\n\t\t\t--recursive\n\n\tbecomes\n\n\t\tgit submodule update --reference=/var/lib/common \\\n\t\t\tobjects.git --recursive\n\n\tin the inner repositories.  Use \"git rev-parse --sq-quote\" to\n\tsave parameters in quoted form ready for evaluation by the\n\tshell, avoiding this problem.\n\nwould be simpler?\n\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -374,7 +374,7 @@ cmd_init()\n>  cmd_update()\n>  {\n>  \t# parse $args after \"submodule ... update\".\n> -\torig_args=\"$@\"\n> +\torig_args=\"$(git rev-parse --sq-quote \"$@\")\"\n\nNo quotes are needed around the RHS to an assignment like this.\n\nAnyway,\nReviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n\nThanks.\n"},{"id":"155027","messageId":"20101103053019.GC10631@burratino","threadId":"25624","inReplyTo":"1288758882-77286-1-git-send-email-kevin@sb.org","subject":"Re: [PATCH 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-11-03T05:30:19Z","receivedAt":"2010-11-03T05:30:19Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Kevin Ballard wrote:\n\n> I tried to write tests for this, but there are only two ways to get args\n> with spaces to be accepted and passed to the recursive invocation.\n> The first is via the --reference flag, but I don't think it really makes\n> sense to use that flag in connection with --recursive and was not comfortable\n> using it in a test.\n\nCould you explain this further?  I think --reference pointing to a\nrepository with objects shared by multiple (sub)projects makes a lot\nof sense.\n"},{"id":"155028","messageId":"E90779F2-C860-494D-9D54-EEF8A513D43D@sb.org","threadId":"25624","inReplyTo":"20101103052837.GB10631@burratino","subject":"Re: [PATCHv2 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T05:35:03Z","receivedAt":"2010-11-03T05:35:03Z","isPatch":false,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"On Nov 2, 2010, at 10:28 PM, Jonathan Nieder wrote:\n\n> Kevin Ballard wrote:\n> \n>> When performing a recursive status or update, any argments with whitespace\n>> would be split along that whitespace when passed to the recursive invocation\n>> of the update or status command.\n>> \n>> This is caused by the special handling that sh provides to the $@ variable.\n>> Status and update stored \"$@\" into a separate variable, and passed that\n>> variable to the recursive invocation. Unfortunately, the special handling\n>> afforded to $@ isn't given to this new variable, and word-breaking occurs\n>> along whitespace boundaries.\n>> \n>> We can use $(git rev-parse --sq-quote \"$@\") to produce a string containing\n>> a quoted version of all given args, suitable for passing to eval. We then\n>> recurse using something like `eval cmd_status \"$orig_args\"` instead of the\n>> former `cmd_status $orig_args`. This preserves all arguments exactly as\n>> given to the initial invocation of the command.\n> \n> Probably it is because it is late hear, but I find myself intimidated\n> by the block of explanatory text.  Maybe an example like\n> \n> \tEnvironment variables only hold strings, not lists of parameters,\n> \tso $orig_args after\n> \n> \t\torig_args=\"$@\"\n> \n> \tfails to remember where each parameter starts and ends, if\n> \tsome include whitespace.  So\n> \n> \t\tgit submodule update \\\n> \t\t\t--reference='/var/lib/common objects.git' \\\n> \t\t\t--recursive\n> \n> \tbecomes\n> \n> \t\tgit submodule update --reference=/var/lib/common \\\n> \t\t\tobjects.git --recursive\n> \n> \tin the inner repositories.  Use \"git rev-parse --sq-quote\" to\n> \tsave parameters in quoted form ready for evaluation by the\n> \tshell, avoiding this problem.\n> \n> would be simpler?\n\nI agree, yours is simpler. I'll send one final patch with the updated description.\n\n>> --- a/git-submodule.sh\n>> +++ b/git-submodule.sh\n>> @@ -374,7 +374,7 @@ cmd_init()\n>> cmd_update()\n>> {\n>> \t# parse $args after \"submodule ... update\".\n>> -\torig_args=\"$@\"\n>> +\torig_args=\"$(git rev-parse --sq-quote \"$@\")\"\n> \n> No quotes are needed around the RHS to an assignment like this.\n\nHrm, looks like you're right. I was under the impression it was necessary in some\ncases when the output of the command included newlines, but a quick test shows\nthat belief to be wrong.\n\n> Anyway,\n> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n\nThanks.\n\n-Kevin Ballard\n"},{"id":"155029","messageId":"B581ED92-DC3D-4F62-99B1-3D02C95471DE@sb.org","threadId":"25624","inReplyTo":"20101103053019.GC10631@burratino","subject":"Re: [PATCH 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T05:36:25Z","receivedAt":"2010-11-03T05:36:25Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"On Nov 2, 2010, at 10:30 PM, Jonathan Nieder wrote:\n\n> Kevin Ballard wrote:\n> \n>> I tried to write tests for this, but there are only two ways to get args\n>> with spaces to be accepted and passed to the recursive invocation.\n>> The first is via the --reference flag, but I don't think it really makes\n>> sense to use that flag in connection with --recursive and was not comfortable\n>> using it in a test.\n> \n> Could you explain this further?  I think --reference pointing to a\n> repository with objects shared by multiple (sub)projects makes a lot\n> of sense.\n\nI hadn't given it a lot of thought, but I suppose you're right. I'm used to\nusing submodules to pull in disparate projects that don't share objects, but\nI can imagine having repos that do share objects. I will try to write a test\nfor this using --reference.\n\n-Kevin Ballard"},{"id":"155030","messageId":"20101103053827.GD10631@burratino","threadId":"25624","inReplyTo":"1288760740-10075-2-git-send-email-kevin@sb.org","subject":"Re: [PATCHv2 2/2] submodule: only preserve flags across recursive status/update invocations","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-11-03T05:38:27Z","receivedAt":"2010-11-03T05:38:27Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Kevin Ballard wrote:\n\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -374,41 +374,35 @@ cmd_init()\n[...]\n>  \t\t--reference)\n>  \t\t\tcase \"$2\" in '') usage ;; esac\n>  \t\t\treference=\"--reference=$2\"\n> -\t\t\tshift 2\n> +\t\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n> +\t\t\tshift\n\nHmm.  Maybe a helper would make it clearer.\n\n\tsave_arg () {\n\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n\t}\n\nmaking this\n\n +\t\t\tsave_arg --reference\n +\t\t\tshift\n\n> --- a/t/t7407-submodule-foreach.sh\n> +++ b/t/t7407-submodule-foreach.sh\n> @@ -238,4 +238,23 @@ test_expect_success 'use \"git clone --recursive\" to checkout all submodules' '\n>  \ttest -d clone4/nested1/nested2/nested3/submodule/.git\n>  '\n>  \n> +test_expect_success 'use \"update --recursive nested1\" to checkout all submodules rooted in nested1' '\n\nMaybe a submodule status --cached --recursive -- <files> test, too?\n\nSleepily,\nJonathan\n"},{"id":"155031","messageId":"E0BA6B5C-AB98-4D72-8E8A-B4EA4B7A17CC@sb.org","threadId":"25624","inReplyTo":"20101103053827.GD10631@burratino","subject":"Re: [PATCHv2 2/2] submodule: only preserve flags across recursive status/update invocations","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T05:45:32Z","receivedAt":"2010-11-03T05:45:32Z","isPatch":false,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"\nOn Nov 2, 2010, at 10:38 PM, Jonathan Nieder wrote:\n\n> Kevin Ballard wrote:\n> \n>> --- a/git-submodule.sh\n>> +++ b/git-submodule.sh\n>> @@ -374,41 +374,35 @@ cmd_init()\n> [...]\n>> \t\t--reference)\n>> \t\t\tcase \"$2\" in '') usage ;; esac\n>> \t\t\treference=\"--reference=$2\"\n>> -\t\t\tshift 2\n>> +\t\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n>> +\t\t\tshift\n> \n> Hmm.  Maybe a helper would make it clearer.\n> \n> \tsave_arg () {\n> \t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n> \t}\n> \n> making this\n> \n> +\t\t\tsave_arg --reference\n> +\t\t\tshift\n\nI considered that, but I already dislike the fact that orig_flags is a global.\nI left it as such for the sake of not fixing what ain't broke, but the use of\na helper function would imply that the global nature of the variable is\nintentional.\n\n>> --- a/t/t7407-submodule-foreach.sh\n>> +++ b/t/t7407-submodule-foreach.sh\n>> @@ -238,4 +238,23 @@ test_expect_success 'use \"git clone --recursive\" to checkout all submodules' '\n>> \ttest -d clone4/nested1/nested2/nested3/submodule/.git\n>> '\n>> \n>> +test_expect_success 'use \"update --recursive nested1\" to checkout all submodules rooted in nested1' '\n> \n> Maybe a submodule status --cached --recursive -- <files> test, too?\n\nGood idea.\n\n-Kevin Ballard"},{"id":"155032","messageId":"20101103054751.GE10631@burratino","threadId":"25624","inReplyTo":"5BE96A08-B8AB-4041-ABF2-7095EB5DD585@sb.org","subject":"Re: [PATCH 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-11-03T05:47:51Z","receivedAt":"2010-11-03T05:47:51Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Kevin Ballard wrote:\n> On Nov 2, 2010, at 9:37 PM, Jonathan Nieder wrote:\n\n>> Have you looked into \"git rev-parse --sq-quote\"?\n>\n> Well crud, I wish I'd seen that before. Looks like it does pretty much the\n> exact same thing as my quote_words function. I'll send out another patch\n> that uses this instead of quote_words. Thanks for the info!\n\nIncidentally, if you still remember where it might have been useful\nto find this advertised (git-sh-setup?), maybe we can find a way to document\nit better.\n\nThanks for the submodule fix.  Well spotted.\n"},{"id":"155033","messageId":"4938B399-3872-4352-9A78-BACAF5ECE38B@sb.org","threadId":"25624","inReplyTo":"20101103054751.GE10631@burratino","subject":"Re: [PATCH 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T05:49:52Z","receivedAt":"2010-11-03T05:49:52Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"On Nov 2, 2010, at 10:47 PM, Jonathan Nieder wrote:\n\n> Kevin Ballard wrote:\n>> On Nov 2, 2010, at 9:37 PM, Jonathan Nieder wrote:\n> \n>>> Have you looked into \"git rev-parse --sq-quote\"?\n>> \n>> Well crud, I wish I'd seen that before. Looks like it does pretty much the\n>> exact same thing as my quote_words function. I'll send out another patch\n>> that uses this instead of quote_words. Thanks for the info!\n> \n> Incidentally, if you still remember where it might have been useful\n> to find this advertised (git-sh-setup?), maybe we can find a way to document\n> it better.\n\nIt might make sense to mention it in CodingGuidelines. That's where I always\nlook when writing shell code in order to make sure I'm not using any bashisms.\n\n-Kevin Ballard"},{"id":"155034","messageId":"1288765585-80823-1-git-send-email-kevin@sb.org","threadId":"25624","inReplyTo":"20101103053827.GD10631@burratino","subject":"[PATCHv3 1/2] submodule: preserve all arguments exactly when recursing","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T06:26:24Z","receivedAt":"2010-11-03T06:26:24Z","isPatch":false,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"Shell variables only hold strings, not lists of parameters,\nso $orig_args after\n\n        orig_args=\"$@\"\n\nfails to remember where each parameter starts and ends, if\nsome include whitespace.  So\n\n        git submodule update \\\n                --reference='/var/lib/common objects.git' \\\n                --recursive --init\n\nbecomes\n\n        git submodule update --reference=/var/lib/common \\\n                objects.git --recursive --init\n\nin the inner repositories.  Use \"git rev-parse --sq-quote\" to\nsave parameters in quoted form ready for evaluation by the\nshell, avoiding this problem.\n\nHelped-By: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Kevin Ballard <kevin@sb.org>\n---\nThis version introduces a test using --reference.\nIt also uses the nice description written by Jonathan\nand it stops unnecessarily quoting the results of\nthe call to $(git rev-parse --sq-quote \"$@\")\n git-submodule.sh             |    8 ++++----\n t/t7407-submodule-foreach.sh |   16 ++++++++++++++++\n 2 files changed, 20 insertions(+), 4 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 9ebbab7..4d2bb37 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -374,7 +374,7 @@ cmd_init()\n cmd_update()\n {\n \t# parse $args after \"submodule ... update\".\n-\torig_args=\"$@\"\n+\torig_args=$(git rev-parse --sq-quote \"$@\")\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -500,7 +500,7 @@ cmd_update()\n \n \t\tif test -n \"$recursive\"\n \t\tthen\n-\t\t\t(clear_local_git_env; cd \"$path\" && cmd_update $orig_args) ||\n+\t\t\t(clear_local_git_env; cd \"$path\" && eval cmd_update \"$orig_args\") ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n \tdone\n@@ -733,7 +733,7 @@ cmd_summary() {\n cmd_status()\n {\n \t# parse $args after \"submodule ... status\".\n-\torig_args=\"$@\"\n+\torig_args=$(git rev-parse --sq-quote \"$@\")\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -790,7 +790,7 @@ cmd_status()\n \t\t\t\tprefix=\"$displaypath/\"\n \t\t\t\tclear_local_git_env\n \t\t\t\tcd \"$path\" &&\n-\t\t\t\tcmd_status $orig_args\n+\t\t\t\teval cmd_status \"$orig_args\"\n \t\t\t) ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\ndiff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh\nindex 905a8ba..15d420f 100755\n--- a/t/t7407-submodule-foreach.sh\n+++ b/t/t7407-submodule-foreach.sh\n@@ -238,4 +238,20 @@ test_expect_success 'use \"git clone --recursive\" to checkout all submodules' '\n \ttest -d clone4/nested1/nested2/nested3/submodule/.git\n '\n \n+test_expect_success 'test \"update --recursive\" with a flag with spaces' '\n+\tgit clone super \"common objects\" &&\n+\tgit clone super clone5 &&\n+\t(\n+\t\tcd clone5 &&\n+\t\ttest ! -d nested1/.git &&\n+\t\tgit submodule update --init --recursive --reference=\"$(dirname \"$PWD\")/common objects\" &&\n+\t\ttest -d nested1/.git &&\n+\t\ttest -d nested1/nested2/.git &&\n+\t\ttest -d nested1/nested2/nested3/.git &&\n+\t\ttest -f nested1/.git/objects/info/alternates &&\n+\t\ttest -f nested1/nested2/.git/objects/info/alternates &&\n+\t\ttest -f nested1/nested2/nested3/.git/objects/info/alternates\n+\t)\n+'\n+\n test_done\n-- \n1.7.3.2.200.g862e8\n"},{"id":"155035","messageId":"1288765585-80823-2-git-send-email-kevin@sb.org","threadId":"25624","inReplyTo":"20101103053827.GD10631@burratino","subject":"[PATCHv3 2/2] submodule: only preserve flags across recursive status/update invocations","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2010-11-03T06:26:25Z","receivedAt":"2010-11-03T06:26:25Z","isPatch":false,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"Recursive invocations of submodule update/status preserve all arguments,\nso executing\n\n        git submodule update --recursive -- foo\n\nattempts to recursively update a submodule named \"foo\".\n\nNaturally, this fails as one cannot have an infinitely-deep stack of\nsubmodules each containing a submodule named \"foo\". The desired behavior\nis instead to update foo and then recursively update all submodules\ninside of foo.\n\nThis commit accomplishes that by only saving the flags for use in the\nrecursive invocation.\n\nSigned-off-by: Kevin Ballard <kevin@sb.org>\n---\nAs suggested by Jonathan Nieder, I've included a test for\n`git submodule status --cached --recursive -- nested` to verify\nthat the flags are preserved but the paths aren't.\n git-submodule.sh             |   19 ++++++++-----------\n t/t7407-submodule-foreach.sh |   34 ++++++++++++++++++++++++++++++++++\n 2 files changed, 42 insertions(+), 11 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 4d2bb37..4fd8982 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -374,41 +374,35 @@ cmd_init()\n cmd_update()\n {\n \t# parse $args after \"submodule ... update\".\n-\torig_args=$(git rev-parse --sq-quote \"$@\")\n+\torig_flags=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n \t\t-q|--quiet)\n-\t\t\tshift\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-i|--init)\n \t\t\tinit=1\n-\t\t\tshift\n \t\t\t;;\n \t\t-N|--no-fetch)\n-\t\t\tshift\n \t\t\tnofetch=1\n \t\t\t;;\n \t\t-r|--rebase)\n-\t\t\tshift\n \t\t\tupdate=\"rebase\"\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\tshift 2\n+\t\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n+\t\t\tshift\n \t\t\t;;\n \t\t--reference=*)\n \t\t\treference=\"$1\"\n-\t\t\tshift\n \t\t\t;;\n \t\t-m|--merge)\n-\t\t\tshift\n \t\t\tupdate=\"merge\"\n \t\t\t;;\n \t\t--recursive)\n-\t\t\tshift\n \t\t\trecursive=1\n \t\t\t;;\n \t\t--)\n@@ -422,6 +416,8 @@ cmd_update()\n \t\t\tbreak\n \t\t\t;;\n \t\tesac\n+\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n+\t\tshift\n \tdone\n \n \tif test -n \"$init\"\n@@ -500,7 +496,7 @@ cmd_update()\n \n \t\tif test -n \"$recursive\"\n \t\tthen\n-\t\t\t(clear_local_git_env; cd \"$path\" && eval cmd_update \"$orig_args\") ||\n+\t\t\t(clear_local_git_env; cd \"$path\" && eval cmd_update \"$orig_flags\") ||\n \t\t\tdie \"Failed to recurse into submodule path '$path'\"\n \t\tfi\n \tdone\n@@ -733,7 +729,7 @@ cmd_summary() {\n cmd_status()\n {\n \t# parse $args after \"submodule ... status\".\n-\torig_args=$(git rev-parse --sq-quote \"$@\")\n+\torig_flags=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -757,6 +753,7 @@ cmd_status()\n \t\t\tbreak\n \t\t\t;;\n \t\tesac\n+\t\torig_flags=\"$orig_flags $(git rev-parse --sq-quote \"$1\")\"\n \t\tshift\n \tdone\n \ndiff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh\nindex 15d420f..d8ad250 100755\n--- a/t/t7407-submodule-foreach.sh\n+++ b/t/t7407-submodule-foreach.sh\n@@ -226,6 +226,21 @@ test_expect_success 'test \"status --recursive\"' '\n \ttest_cmp expect actual\n '\n \n+sed -e \"/nested1 /s/.*/+$nested1sha1 nested1 (file2~1)/;/sub[1-3]/d\" < expect > expect2\n+mv -f expect2 expect\n+\n+test_expect_success 'ensure \"status --cached --recursive\" preserves the --cached flag' '\n+\t(\n+\t\tcd clone3 &&\n+\t\t(\n+\t\t\tcd nested1 &&\n+\t\t\ttest_commit file2\n+\t\t) &&\n+\t\tgit submodule status --cached --recursive -- nested1 > ../actual\n+\t) &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'use \"git clone --recursive\" to checkout all submodules' '\n \tgit clone --recursive super clone4 &&\n \ttest -d clone4/.git &&\n@@ -254,4 +269,23 @@ test_expect_success 'test \"update --recursive\" with a flag with spaces' '\n \t)\n '\n \n+test_expect_success 'use \"update --recursive nested1\" to checkout all submodules rooted in nested1' '\n+\tgit clone super clone6 &&\n+\t(\n+\t\tcd clone6 &&\n+\t\ttest ! -d sub1/.git &&\n+\t\ttest ! -d sub2/.git &&\n+\t\ttest ! -d sub3/.git &&\n+\t\ttest ! -d nested1/.git &&\n+\t\tgit submodule update --init --recursive -- nested1 &&\n+\t\ttest ! -d sub1/.git &&\n+\t\ttest ! -d sub2/.git &&\n+\t\ttest ! -d sub3/.git &&\n+\t\ttest -d nested1/.git &&\n+\t\ttest -d nested1/nested2/.git &&\n+\t\ttest -d nested1/nested2/nested3/.git &&\n+\t\ttest -d nested1/nested2/nested3/submodule/.git\n+\t)\n+'\n+\n test_done\n-- \n1.7.3.2.200.g862e8\n"},{"id":"155272","messageId":"7vvd4bqtu7.fsf@alter.siamese.dyndns.org","threadId":"25624","inReplyTo":"1288765585-80823-2-git-send-email-kevin@sb.org","subject":"Re: [PATCHv3 2/2] submodule: only preserve flags across recursive status/update invocations","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-11-05T22:38:40Z","receivedAt":"2010-11-05T22:38:40Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Well done; thanks both.  Will queue.\n"}]}