{"thread":{"id":"11518","subject":"[PATCH] Added recurse command to git submodule","startedAt":"2008-01-08T03:14:19Z","lastAt":"2008-01-08T06:57:12Z","messageCount":3,"participants":["Imran M Yousuf","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"64694","messageId":"7bfdc29a0801071914s207be500veae8e507d7d9d29@mail.gmail.com","threadId":"11518","inReplyTo":null,"subject":"[PATCH] Added recurse command to git submodule","fromName":"Imran M Yousuf","fromEmail":"imyousuf@gmail.com","sentAt":"2008-01-08T03:14:19Z","receivedAt":"2008-01-08T03:14:19Z","isPatch":true,"sender":{"key":"imyousuf@gmail.com","avatar":"https://gravatar.com/avatar/fda3c870262849d03c7b9c4d288842e128d6d80769fa7bc2d22731b7597928be?d=mp&s=160"},"body":"Added a recurse command to git-submodule. Using this recurse command\nany git command (for example, git-status, git-diff, git-checkout) can\nbe performed from the top level to all its submodules at any depth; if\nthe module has not been initialized and updated (that is git sumodule\ninit and git submodule update) the script will take care of that too.\n\nI needed this feature especially for diff, status and pull; as I am\nworking on a multi module maven project with each module having\nseparate repository due to architecture and future extensibility.\n\nFollowing is the diff with git-submdoule version 1.5.3.7. I also\nattached the diff and the modified file in the attachment.\n\ndiff --git a/git-submodule b/git-submodule\nindex b91d626..e819152 100755\n--- a/git-submodule\n+++ b/git-submodule\n@@ -1,10 +1,11 @@\n #!/bin/sh\n #\n # git-submodules.sh: add, init, update or list git submodules\n+# or recurse any git command over the submodules recursively.\n #\n # Copyright (c) 2007 Lars Hjemli\n\n-USAGE='[--quiet] [--cached] [add <repo> [-b\nbranch]|status|init|update] [--] [<path>...]'\n+USAGE='[[--quiet] [--cached] [add <repo> [-b\nbranch]|status|init|update] [--] [<path>...]|[recurse [-v] command\narguments ...]]'\n . git-sh-setup\n require_work_tree\n\n@@ -251,6 +252,78 @@ modules_list()\n \tdone\n }\n\n+# Simply checks whether the submodule is initialized\n+# or not. If not initialized it does so.\n+initializeSubModule() {\n+\tif [ ! -d \"$1\"/.git ]; then\n+\t\tif [ $recurse_verbose -eq 1 ]; then\n+\t\t\techo Initializing and updating \"$1\"\n+\t\tfi\n+\t\tgit-submodule init \"$1\"; git-submodule update \"$1\"\n+\tfi\n+}\n+\n+# This actually traverses the module; checks\n+# whether the module is initialized or not.\n+# if not initialized, then done so and then the\n+# intended command is evaluated. Then it\n+# recursively goes into it modules.\n+traverseModule() {\n+\tcurrent_dir=`pwd`\n+\tdir_path=\"$current_dir:$dir_path\"\n+\tinitializeSubModule \"$1\"\n+        cd \"$1\"\n+\tif [ $recurse_verbose -eq 1 ]; then\n+\t\techo Working in mod $1 @ `pwd` with $2\n+\tfi\n+        eval \"$2\"\n+\tif [ -f .gitmodules ]; then\n+                for mod_path in `grep \"path =\" .gitmodules | awk\n'{print $3}'`; do\n+                        traverseModule \"$mod_path\" \"$2\"\n+                done\n+        fi\n+\told_dir=$(echo $dir_path | cut -d':' -f1-1)\n+\tlength_old_dir=`expr \"$old_dir\" : '.*'`\n+\tcd $old_dir\n+\tindex=$(echo \"$length_old_dir+2\" | bc)\n+\tdir_path=`echo $dir_path $index | awk '{print substr($1, $2)}'`\n+}\n+\n+# Propagates or recurses over all the submodules at any\n+# depth with any git command, e.g. git-clone, git-status,\n+# git-commit etc., with the arguments supplied exactly as\n+# it would have been supplied to the command otherwise.\n+# This actually starts the recursive propagation\n+propagate() {\n+\tproject_home=`pwd`\n+\techo Project Home: $project_home\n+\tif [ -d $project_home/.git/ ]; then\n+\t\tgit_command=$1\n+\t\tshift\n+\t\tcommand_arguments=\"\"\n+\t\tfor arg in \"$@\"; do\n+\t\t\tif [ `expr index \"$arg\" ' '` -gt 0 ]; then\n+\t\t\t\targ=\"\\\"$arg\\\"\"\n+\t\t\tfi\n+\t\t\tcommand_arguments=\"$command_arguments $arg\"\n+\t\tdone\n+\t\tif [ $recurse_verbose -eq 1 ]; then\n+\t\t\techo GIT Command git-$git_command with arguments\\($#\\) \"$command_arguments\"\n+\t\tfi\n+\t\tmain_command=\"git-$git_command $command_arguments\"\n+\t\teval $main_command\n+\t\tif [ -f .gitmodules ]; then\n+\t\t\tfor mod_path in `grep \"path =\" .gitmodules | awk '{print $3}'`; do\n+\t\t\t\ttraverseModule $mod_path \"$main_command\"\n+\t\t\tdone\n+\t\tfi\n+\telse\n+\t\techo $project_home not a git repo thus exiting\n+\t\texit\n+\tfi\n+}\n+\n+recurse_verbose=0\n while test $# != 0\n do\n \tcase \"$1\" in\n@@ -286,6 +359,17 @@ do\n \t-*)\n \t\tusage\n \t\t;;\n+\trecurse)\n+\t\trecurse=1\n+\t\tcase \"$2\" in\n+\t\t\t-v)\n+\t\t\t\trecurse_verbose=1\n+\t\t\t\tshift\n+\t\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\t\tbreak\n+\t\t;;\n \t*)\n \t\tbreak\n \t\t;;\n@@ -303,17 +387,21 @@ case \"$add,$branch\" in\n \t;;\n esac\n\n-case \"$add,$init,$update,$status,$cached\" in\n-1,,,,)\n+\n+case \"$add,$init,$update,$recurse,$status,$cached\" in\n+1,,,,,)\n \tmodule_add \"$@\"\n \t;;\n-,1,,,)\n+,1,,,,)\n \tmodules_init \"$@\"\n \t;;\n-,,1,,)\n+,,1,,,)\n \tmodules_update \"$@\"\n \t;;\n-,,,*,*)\n+,,,1,,)\n+\tpropagate \"$@\"\n+\t;;\n+,,,,*,*)\n \tmodules_list \"$@\"\n \t;;\n *)\n\n-- \nImran M Yousuf\n\n\ndiff --git a/git-submodule b/git-submodule\nindex b91d626..e819152 100755\n--- a/git-submodule\n+++ b/git-submodule\n@@ -1,10 +1,11 @@\n #!/bin/sh\n #\n # git-submodules.sh: add, init, update or list git submodules\n+# or recurse any git command over the submodules recursively.\n #\n # Copyright (c) 2007 Lars Hjemli\n \n-USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]'\n+USAGE='[[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]|[recurse [-v] command arguments ...]]'\n . git-sh-setup\n require_work_tree\n \n@@ -251,6 +252,78 @@ modules_list()\n \tdone\n }\n \n+# Simply checks whether the submodule is initialized\n+# or not. If not initialized it does so.\n+initializeSubModule() {\n+\tif [ ! -d \"$1\"/.git ]; then\n+\t\tif [ $recurse_verbose -eq 1 ]; then\n+\t\t\techo Initializing and updating \"$1\"\n+\t\tfi\n+\t\tgit-submodule init \"$1\"; git-submodule update \"$1\"\n+\tfi\n+}\n+\n+# This actually traverses the module; checks\n+# whether the module is initialized or not.\n+# if not initialized, then done so and then the\n+# intended command is evaluated. Then it\n+# recursively goes into it modules.\n+traverseModule() {\n+\tcurrent_dir=`pwd`\n+\tdir_path=\"$current_dir:$dir_path\"\n+\tinitializeSubModule \"$1\"\n+        cd \"$1\"\n+\tif [ $recurse_verbose -eq 1 ]; then\n+\t\techo Working in mod $1 @ `pwd` with $2\n+\tfi\n+        eval \"$2\"\n+\tif [ -f .gitmodules ]; then\n+                for mod_path in `grep \"path =\" .gitmodules | awk '{print $3}'`; do\n+                        traverseModule \"$mod_path\" \"$2\"\n+                done\n+        fi\n+\told_dir=$(echo $dir_path | cut -d':' -f1-1)\n+\tlength_old_dir=`expr \"$old_dir\" : '.*'`\n+\tcd $old_dir\n+\tindex=$(echo \"$length_old_dir+2\" | bc)\n+\tdir_path=`echo $dir_path $index | awk '{print substr($1, $2)}'`\n+}\n+\n+# Propagates or recurses over all the submodules at any \n+# depth with any git command, e.g. git-clone, git-status,\n+# git-commit etc., with the arguments supplied exactly as\n+# it would have been supplied to the command otherwise.\n+# This actually starts the recursive propagation\n+propagate() {\n+\tproject_home=`pwd`\n+\techo Project Home: $project_home\n+\tif [ -d $project_home/.git/ ]; then\n+\t\tgit_command=$1\n+\t\tshift\n+\t\tcommand_arguments=\"\"\n+\t\tfor arg in \"$@\"; do\n+\t\t\tif [ `expr index \"$arg\" ' '` -gt 0 ]; then\n+\t\t\t\targ=\"\\\"$arg\\\"\"\n+\t\t\tfi \n+\t\t\tcommand_arguments=\"$command_arguments $arg\"\n+\t\tdone\n+\t\tif [ $recurse_verbose -eq 1 ]; then\n+\t\t\techo GIT Command git-$git_command with arguments\\($#\\) \"$command_arguments\"\n+\t\tfi\n+\t\tmain_command=\"git-$git_command $command_arguments\"\n+\t\teval $main_command\n+\t\tif [ -f .gitmodules ]; then\n+\t\t\tfor mod_path in `grep \"path =\" .gitmodules | awk '{print $3}'`; do\n+\t\t\t\ttraverseModule $mod_path \"$main_command\"\n+\t\t\tdone\n+\t\tfi\n+\telse\n+\t\techo $project_home not a git repo thus exiting\n+\t\texit\n+\tfi\n+}\n+\n+recurse_verbose=0\n while test $# != 0\n do\n \tcase \"$1\" in\n@@ -286,6 +359,17 @@ do\n \t-*)\n \t\tusage\n \t\t;;\n+\trecurse)\n+\t\trecurse=1\n+\t\tcase \"$2\" in\n+\t\t\t-v)\n+\t\t\t\trecurse_verbose=1\n+\t\t\t\tshift\n+\t\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\t\tbreak\n+\t\t;;\n \t*)\n \t\tbreak\n \t\t;;\n@@ -303,17 +387,21 @@ case \"$add,$branch\" in\n \t;;\n esac\n \n-case \"$add,$init,$update,$status,$cached\" in\n-1,,,,)\n+\n+case \"$add,$init,$update,$recurse,$status,$cached\" in\n+1,,,,,)\n \tmodule_add \"$@\"\n \t;;\n-,1,,,)\n+,1,,,,)\n \tmodules_init \"$@\"\n \t;;\n-,,1,,)\n+,,1,,,)\n \tmodules_update \"$@\"\n \t;;\n-,,,*,*)\n+,,,1,,)\n+\tpropagate \"$@\"\n+\t;;\n+,,,,*,*)\n \tmodules_list \"$@\"\n \t;;\n *)\n"},{"id":"64700","messageId":"7v3at8yiq4.fsf@gitster.siamese.dyndns.org","threadId":"11518","inReplyTo":"7bfdc29a0801071914s207be500veae8e507d7d9d29@mail.gmail.com","subject":"Re: [PATCH] Added recurse command to git submodule","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-01-08T05:44:19Z","receivedAt":"2008-01-08T05:44:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Imran M Yousuf\" <imyousuf@gmail.com> writes:\n\n> Following is the diff with git-submdoule version 1.5.3.7. I also\n> attached the diff and the modified file in the attachment.\n\nPlease do not do this when the submission is for real (I think\nyou did not mean this for inclusion but for comment so it is Ok\nthis time around), as such a message cannot be processed with\nour automated tools but need to be applied by hand.\n\nJust send a non whitespace-corrupted, plain text patch.  A\ncorrupt text patch followed by an attachment is the worst of\nboth worlds.\n\n> @@ -251,6 +252,78 @@ modules_list()\n>  \tdone\n>  }\n>\n> +# Simply checks whether the submodule is initialized\n> +# or not. If not initialized it does so.\n> +initializeSubModule() {\n> +\tif [ ! -d \"$1\"/.git ]; then\n> +\t\tif [ $recurse_verbose -eq 1 ]; then\n> +\t\t\techo Initializing and updating \"$1\"\n> +\t\tfi\n> +\t\tgit-submodule init \"$1\"; git-submodule update \"$1\"\n> +\tfi\n> +}\n\nThe comment above sounds quite wrong, isn't it?  It is not just\n\"simply check\" but actively makes sure it is initialized.\n\nDo we use CamelCase in our shell script?\n\nMaking -r to always recurse _fully_ feels quite wrong.  It is\none thing to allow \"git submodule init --recursive\" to recurse\nfully and initialize everything, but it is another thing to\nforce full instantiation of submodules that the user _chose_ not\nto check out, when the user has checkout of some but not all\nsubmodules and asks \"git submodule update --recursive\".\n\n> +# This actually traverses the module; checks\n> +# whether the module is initialized or not.\n> +# if not initialized, then done so and then the\n> +# intended command is evaluated. Then it\n> +# recursively goes into it modules.\n> +traverseModule() {\n> +\tcurrent_dir=`pwd`\n> +\tdir_path=\"$current_dir:$dir_path\"\n> +\tinitializeSubModule \"$1\"\n> +        cd \"$1\"\n> +\tif [ $recurse_verbose -eq 1 ]; then\n> +\t\techo Working in mod $1 @ `pwd` with $2\n> +\tfi\n\nAlways quote variable references unless you mean you want field\nsplitting.  Even when you know $1 and $2 do not have IFS\ncharacters, to make it easier to readers.\n\n> +        eval \"$2\"\n> +\tif [ -f .gitmodules ]; then\n> +                for mod_path in `grep \"path =\" .gitmodules | awk\n> '{print $3}'`; do\n> +                        traverseModule \"$mod_path\" \"$2\"\n> +                done\n> +        fi\n> +\told_dir=$(echo $dir_path | cut -d':' -f1-1)\n> +\tlength_old_dir=`expr \"$old_dir\" : '.*'`\n> +\tcd $old_dir\n> +\tindex=$(echo \"$length_old_dir+2\" | bc)\n> +\tdir_path=`echo $dir_path $index | awk '{print substr($1, $2)}'`\n\nThis dir_path separated with \":\" and shuffling the $cwd with\nchdir'ing around makes me say \"Yuck\".  Is it essential that\nthese operation in the submodule happen in the same process?\nIOW, wouldn't it be enough to do something like:\n\n\n\tinitialize_submodule \"$1\"\n        (\n        \tcd \"$1\"\n                if test -n \"$recursive_verbose\"\n                then\n                \techo \"Working in module $1 with $2\"\n\t\tfi\n                eval \"$2\"\n\t\tif test -f .gitmodules\n                then\n                \tfor p in `sed -n -e 's/^path = //p' .gitmodules`\n\t\t\tdo\n                        \ttraverse_module \"$p\" \"$2\"\n\t\t\tdone\n\t\tfi\n\t)\n\n> +}\n> +\n> +# Propagates or recurses over all the submodules at any\n> +# depth with any git command, e.g. git-clone, git-status,\n> +# git-commit etc., with the arguments supplied exactly as\n> +# it would have been supplied to the command otherwise.\n> +# This actually starts the recursive propagation\n> +propagate() {\n> +\tproject_home=`pwd`\n> +\techo Project Home: $project_home\n> +\tif [ -d $project_home/.git/ ]; then\n> +\t\tgit_command=$1\n> +\t\tshift\n> +\t\tcommand_arguments=\"\"\n> +\t\tfor arg in \"$@\"; do\n\nThat 'in \"$@\"' is distracting.\n\n\tfor arg\n        do\n\t\t...\n\nis enough.\n\n> +\t\t\tif [ `expr index \"$arg\" ' '` -gt 0 ]; then\n\nDo we ever use `expr index` anywhere else?  I thought we fixed\nthat non-portability.\n\n> +\t\t\t\targ=\"\\\"$arg\\\"\"\n> +\t\t\tfi\n> +\t\t\tcommand_arguments=\"$command_arguments $arg\"\n> +\t\tdone\n> +\t\tif [ $recurse_verbose -eq 1 ]; then\n> +\t\t\techo GIT Command git-$git_command with arguments\\($#\\) \"$command_arguments\"\n> +\t\tfi\n> +\t\tmain_command=\"git-$git_command $command_arguments\"\n> +\t\teval $main_command\n\nThis feels like a sloppy quoting, although I haven't looked at\nthe code very deeply.  Does it work when $arg has funny letters\nlike backslash, double-quote and or backquote?\n\n> @@ -286,6 +359,17 @@ do\n>  \t-*)\n>  \t\tusage\n>  \t\t;;\n> +\trecurse)\n> +\t\trecurse=1\n> +\t\tcase \"$2\" in\n> +\t\t\t-v)\n> +\t\t\t\trecurse_verbose=1\n> +\t\t\t\tshift\n> +\t\t\t\t;;\n> +\t\tesac\n> +\t\tshift\n> +\t\tbreak\n> +\t\t;;\n\nI was ahead of myself earlier but I think it makes more sense to\npretend (at the command line syntax level) that --recursive is\nan option to other commands.\n\n> @@ -303,17 +387,21 @@ case \"$add,$branch\" in\n>  \t;;\n>  esac\n>\n> -case \"$add,$init,$update,$status,$cached\" in\n> -1,,,,)\n> +\n> +case \"$add,$init,$update,$recurse,$status,$cached\" in\n> +1,,,,,)\n>  \tmodule_add \"$@\"\n>  \t;;\n> -,1,,,)\n> +,1,,,,)\n>  \tmodules_init \"$@\"\n>  \t;;\n> -,,1,,)\n> +,,1,,,)\n>  \tmodules_update \"$@\"\n>  \t;;\n> -,,,*,*)\n> +,,,1,,)\n> +\tpropagate \"$@\"\n> +\t;;\n> +,,,,*,*)\n>  \tmodules_list \"$@\"\n>  \t;;\n>  *)\n\nI've always hated this part of the script.  How about a bit of\nclean-up patch first before adding $recurse or anything else, to\nintroduce command variable and do:\n\n\tcase \"$command\" in\n        add)\n        \tmodule_add \"$@\"\n                ;;\n\tinit)\n        \tmodule_init \"$@\"\n                ;;\n                ...\n\t*)\n        \tmodules_list \"$@\"\n                ;;\n\tesac\n\nor even just a single:\n\n\t\"module_$command\" \"$@\"\n"},{"id":"64703","messageId":"7bfdc29a0801072257m14fa739el618c932fb38b61fe@mail.gmail.com","threadId":"11518","inReplyTo":"7v3at8yiq4.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Added recurse command to git submodule","fromName":"Imran M Yousuf","fromEmail":"imyousuf@gmail.com","sentAt":"2008-01-08T06:57:12Z","receivedAt":"2008-01-08T06:57:12Z","isPatch":true,"sender":{"key":"imyousuf@gmail.com","avatar":"https://gravatar.com/avatar/fda3c870262849d03c7b9c4d288842e128d6d80769fa7bc2d22731b7597928be?d=mp&s=160"},"body":"Hi Junio,\n\nThanks for the comments.\nFIrstly, yes I did not mean for inclusion right now, but rather for\ncomment. I am already working with the branched out versions of the\nfiles.\nSecondly, I should apologize for messing the patches, as I read the\nSubmittingPatches actually after sending out the patches. From next\ntime, I will try to follow the document strictly.\nSorry for mixing camel case, being a Java developer I always tend to\nuse them, but will fix them right now :). Will be also changing the\ncomments. I will also change the for loop to as you suggested.\nThanks a lot for the chdir solution. I actually did not that it could\nbe done; that saves a lot of effort. Will surely change it\naccordingly.\nI was actually not planning to introduce git submodule init\n--recursive or git submodule update --recursive; but I will also\nintroduce it. Just wanted to clarify that only git submodule init will\nbehave as it used to earlier and there is no recursion involved.\n\n>\n> > +                             arg=\"\\\"$arg\\\"\"\n> > +                     fi\n> > +                     command_arguments=\"$command_arguments $arg\"\n> > +             done\n> > +             if [ $recurse_verbose -eq 1 ]; then\n> > +                     echo GIT Command git-$git_command with arguments\\($#\\) \"$command_arguments\"\n> > +             fi\n> > +             main_command=\"git-$git_command $command_arguments\"\n> > +             eval $main_command\n>\n> This feels like a sloppy quoting, although I haven't looked at\n> the code very deeply.  Does it work when $arg has funny letters\n> like backslash, double-quote and or backquote?\n\nit does work if $arg has double-quote (commit -m \"commit message\"), I\nwill also test with the other 2 characters you mentioned.\n\nI just wanted to confirm that I will submit the patch for commands of\nsubmodule by today. I do agree with having --recursive option with all\nthe commands, but, IMHO, as it is particularly useful for submodules\nonly it also makes sense if it is a separate command for submodule.\n\nAt first I will make the command change and send the patch today and\nthen make the other patches and send them over.\n\nThank you once again for the hints.\n\nImran\n\nOn Jan 8, 2008 11:44 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> \"Imran M Yousuf\" <imyousuf@gmail.com> writes:\n>\n> > Following is the diff with git-submdoule version 1.5.3.7. I also\n> > attached the diff and the modified file in the attachment.\n>\n> Please do not do this when the submission is for real (I think\n> you did not mean this for inclusion but for comment so it is Ok\n> this time around), as such a message cannot be processed with\n> our automated tools but need to be applied by hand.\n>\n> Just send a non whitespace-corrupted, plain text patch.  A\n> corrupt text patch followed by an attachment is the worst of\n> both worlds.\n>\n> > @@ -251,6 +252,78 @@ modules_list()\n> >       done\n> >  }\n> >\n> > +# Simply checks whether the submodule is initialized\n> > +# or not. If not initialized it does so.\n> > +initializeSubModule() {\n> > +     if [ ! -d \"$1\"/.git ]; then\n> > +             if [ $recurse_verbose -eq 1 ]; then\n> > +                     echo Initializing and updating \"$1\"\n> > +             fi\n> > +             git-submodule init \"$1\"; git-submodule update \"$1\"\n> > +     fi\n> > +}\n>\n> The comment above sounds quite wrong, isn't it?  It is not just\n> \"simply check\" but actively makes sure it is initialized.\n>\n> Do we use CamelCase in our shell script?\n>\n> Making -r to always recurse _fully_ feels quite wrong.  It is\n> one thing to allow \"git submodule init --recursive\" to recurse\n> fully and initialize everything, but it is another thing to\n> force full instantiation of submodules that the user _chose_ not\n> to check out, when the user has checkout of some but not all\n> submodules and asks \"git submodule update --recursive\".\n>\n> > +# This actually traverses the module; checks\n> > +# whether the module is initialized or not.\n> > +# if not initialized, then done so and then the\n> > +# intended command is evaluated. Then it\n> > +# recursively goes into it modules.\n> > +traverseModule() {\n> > +     current_dir=`pwd`\n> > +     dir_path=\"$current_dir:$dir_path\"\n> > +     initializeSubModule \"$1\"\n> > +        cd \"$1\"\n> > +     if [ $recurse_verbose -eq 1 ]; then\n> > +             echo Working in mod $1 @ `pwd` with $2\n> > +     fi\n>\n> Always quote variable references unless you mean you want field\n> splitting.  Even when you know $1 and $2 do not have IFS\n> characters, to make it easier to readers.\n>\n> > +        eval \"$2\"\n> > +     if [ -f .gitmodules ]; then\n> > +                for mod_path in `grep \"path =\" .gitmodules | awk\n> > '{print $3}'`; do\n> > +                        traverseModule \"$mod_path\" \"$2\"\n> > +                done\n> > +        fi\n> > +     old_dir=$(echo $dir_path | cut -d':' -f1-1)\n> > +     length_old_dir=`expr \"$old_dir\" : '.*'`\n> > +     cd $old_dir\n> > +     index=$(echo \"$length_old_dir+2\" | bc)\n> > +     dir_path=`echo $dir_path $index | awk '{print substr($1, $2)}'`\n>\n> This dir_path separated with \":\" and shuffling the $cwd with\n> chdir'ing around makes me say \"Yuck\".  Is it essential that\n> these operation in the submodule happen in the same process?\n> IOW, wouldn't it be enough to do something like:\n>\n>\n>         initialize_submodule \"$1\"\n>         (\n>                 cd \"$1\"\n>                 if test -n \"$recursive_verbose\"\n>                 then\n>                         echo \"Working in module $1 with $2\"\n>                 fi\n>                 eval \"$2\"\n>                 if test -f .gitmodules\n>                 then\n>                         for p in `sed -n -e 's/^path = //p' .gitmodules`\n>                         do\n>                                 traverse_module \"$p\" \"$2\"\n>                         done\n>                 fi\n>         )\n>\n> > +}\n> > +\n> > +# Propagates or recurses over all the submodules at any\n> > +# depth with any git command, e.g. git-clone, git-status,\n> > +# git-commit etc., with the arguments supplied exactly as\n> > +# it would have been supplied to the command otherwise.\n> > +# This actually starts the recursive propagation\n> > +propagate() {\n> > +     project_home=`pwd`\n> > +     echo Project Home: $project_home\n> > +     if [ -d $project_home/.git/ ]; then\n> > +             git_command=$1\n> > +             shift\n> > +             command_arguments=\"\"\n> > +             for arg in \"$@\"; do\n>\n> That 'in \"$@\"' is distracting.\n>\n>         for arg\n>         do\n>                 ...\n>\n> is enough.\n>\n> > +                     if [ `expr index \"$arg\" ' '` -gt 0 ]; then\n>\n> Do we ever use `expr index` anywhere else?  I thought we fixed\n> that non-portability.\n>\n> > +                             arg=\"\\\"$arg\\\"\"\n> > +                     fi\n> > +                     command_arguments=\"$command_arguments $arg\"\n> > +             done\n> > +             if [ $recurse_verbose -eq 1 ]; then\n> > +                     echo GIT Command git-$git_command with arguments\\($#\\) \"$command_arguments\"\n> > +             fi\n> > +             main_command=\"git-$git_command $command_arguments\"\n> > +             eval $main_command\n>\n> This feels like a sloppy quoting, although I haven't looked at\n> the code very deeply.  Does it work when $arg has funny letters\n> like backslash, double-quote and or backquote?\n>\n> > @@ -286,6 +359,17 @@ do\n> >       -*)\n> >               usage\n> >               ;;\n> > +     recurse)\n> > +             recurse=1\n> > +             case \"$2\" in\n> > +                     -v)\n> > +                             recurse_verbose=1\n> > +                             shift\n> > +                             ;;\n> > +             esac\n> > +             shift\n> > +             break\n> > +             ;;\n>\n> I was ahead of myself earlier but I think it makes more sense to\n> pretend (at the command line syntax level) that --recursive is\n> an option to other commands.\n>\n> > @@ -303,17 +387,21 @@ case \"$add,$branch\" in\n> >       ;;\n> >  esac\n> >\n> > -case \"$add,$init,$update,$status,$cached\" in\n> > -1,,,,)\n> > +\n> > +case \"$add,$init,$update,$recurse,$status,$cached\" in\n> > +1,,,,,)\n> >       module_add \"$@\"\n> >       ;;\n> > -,1,,,)\n> > +,1,,,,)\n> >       modules_init \"$@\"\n> >       ;;\n> > -,,1,,)\n> > +,,1,,,)\n> >       modules_update \"$@\"\n> >       ;;\n> > -,,,*,*)\n> > +,,,1,,)\n> > +     propagate \"$@\"\n> > +     ;;\n> > +,,,,*,*)\n> >       modules_list \"$@\"\n> >       ;;\n> >  *)\n>\n> I've always hated this part of the script.  How about a bit of\n> clean-up patch first before adding $recurse or anything else, to\n> introduce command variable and do:\n>\n>         case \"$command\" in\n>         add)\n>                 module_add \"$@\"\n>                 ;;\n>         init)\n>                 module_init \"$@\"\n>                 ;;\n>                 ...\n>         *)\n>                 modules_list \"$@\"\n>                 ;;\n>         esac\n>\n> or even just a single:\n>\n>         \"module_$command\" \"$@\"\n>\n>\n>\n\n\n\n-- \nImran M Yousuf\n"}]}