{"thread":{"id":"12673","subject":"[PATCH 4/7] git-submodule: Fall back on .gitmodules if info not found in $GIT_DIR/config","startedAt":"2008-03-13T17:56:34Z","lastAt":"2008-03-14T14:20:38Z","messageCount":10,"participants":["Ping Yin"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"71969","messageId":"1205431001-18590-1-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":null,"subject":"[PATCH 0/7] git-submodule enhancements","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:34Z","receivedAt":"2008-03-13T17:56:34Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"This patch series do following enhancements for git-submodule\n\n  - Fall back on .gitmodules if info not found in $GIT_DIR/config\n  - multi-level module definition\n  - Don't die when command fails for one submodule \n\nwith diffstat\n\n git-submodule.sh           |  316 +++++++++++++++++++++++++++++++-------------\n t/t7400-submodule-basic.sh |   31 ++++-\n\nand commits\n\n      git-submodule: Avoid 'fatal: cannot describe' message\n      git-submodule: Extract functions module_info and module_url\n      git-submodule: Extract absolute_url & move absolute url logic to module_clone\n      git-submodule: Fall back on .gitmodules if info not found in $GIT_DIR/config\n      git-submodule: Extract module_add from cmd_add\n      git-submodule: multi-level module definition\n      git-submodule: Don't die when command fails for one submodule\n"},{"id":"71973","messageId":"1205431001-18590-2-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-1-git-send-email-pkufranky@gmail.com","subject":"[PATCH 1/7] git-submodule: Avoid 'fatal: cannot describe' message","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:35Z","receivedAt":"2008-03-13T17:56:35Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"When \"git submodule status\" command tries to show the name of the\nsubmodule HEAD revision more descriptively, but the submodule\nrepository lacked a suitable tag to do so, it leaked \"fatal: cannot\ndescribe\" message to the UI.  Squelch it by using '--always'.\n\nSigned-off-by: Ping Yin <pkufranky@gmail.com>\n---\n git-submodule.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 5f1d5ef..2f40620 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -327,7 +327,7 @@ set_name_rev () {\n \t\tcd \"$1\" && {\n \t\t\tgit describe \"$2\" 2>/dev/null ||\n \t\t\tgit describe --tags \"$2\" 2>/dev/null ||\n-\t\t\tgit describe --contains --tags \"$2\"\n+\t\t\tgit describe --contains --tags --always \"$2\"\n \t\t}\n \t) )\n \ttest -z \"$revname\" || revname=\" ($revname)\"\n-- \n1.5.4.4.653.g7cf1e\n"},{"id":"71971","messageId":"1205431001-18590-3-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-2-git-send-email-pkufranky@gmail.com","subject":"[PATCH 2/7] git-submodule: Extract functions module_info and module_url","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:36Z","receivedAt":"2008-03-13T17:56:36Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"module_info is extracted to remove the logic redundance which acquires\nmodule names and urls by path filter in several places.\n\nmodule_url is also extracted to prepare for an alternative logic to get url by\nmodule name.\n\nSigned-off-by: Ping Yin <pkufranky@gmail.com>\n---\n git-submodule.sh |   40 ++++++++++++++++++++++++++++------------\n 1 files changed, 28 insertions(+), 12 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 2f40620..7545d1a 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -82,6 +82,25 @@ module_name()\n        echo \"$name\"\n }\n \n+module_url() {\n+\tgit config submodule.$1.url\n+}\n+\n+module_info() {\n+\tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n+\twhile read mode sha1 stage path\n+\tdo\n+\t\tname=$(module_name \"$path\")\n+\t\tif test -n \"$name\"\n+\t\tthen\n+\t\t\turl=$(module_url \"$name\")\n+\t\t\techo \"$sha1\t$path\t$name\t$url\"\n+\t\telse\n+\t\t\techo \"$sha1\t$path\t\t\"\n+\t\tfi\n+\tdone\n+}\n+\n #\n # Clone a submodule\n #\n@@ -232,12 +251,11 @@ cmd_init()\n \t\tshift\n \tdone\n \n-\tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n-\twhile read mode sha1 stage path\n+\tmodule_info \"$@\" |\n+\twhile read sha1 path name url\n \tdo\n+\t\ttest -n \"$name\" || exit\n \t\t# Skip already registered paths\n-\t\tname=$(module_name \"$path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n \t\ttest -z \"$url\" || continue\n \n \t\turl=$(GIT_CONFIG=.gitmodules git config submodule.\"$name\".url)\n@@ -286,11 +304,10 @@ cmd_update()\n \t\tshift\n \tdone\n \n-\tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n-\twhile read mode sha1 stage path\n+\tmodule_info \"$@\" |\n+\twhile read sha1 path name url\n \tdo\n-\t\tname=$(module_name \"$path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n+\t\ttest -n \"$name\" || exit\n \t\tif test -z \"$url\"\n \t\tthen\n \t\t\t# Only mention uninitialized submodules when its\n@@ -537,11 +554,10 @@ cmd_status()\n \t\tshift\n \tdone\n \n-\tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n-\twhile read mode sha1 stage path\n+\tmodule_info \"$@\" |\n+\twhile read sha1 path name url\n \tdo\n-\t\tname=$(module_name \"$path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n+\t\ttest -n \"$name\" || exit\n \t\tif test -z \"$url\" || ! test -d \"$path\"/.git\n \t\tthen\n \t\t\tsay \"-$sha1 $path\"\n-- \n1.5.4.4.653.g7cf1e\n"},{"id":"71970","messageId":"1205431001-18590-4-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-3-git-send-email-pkufranky@gmail.com","subject":"[PATCH 3/7] git-submodule: Extract absolute_url & move absolute url logic to module_clone","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:37Z","receivedAt":"2008-03-13T17:56:37Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"Extract function absolute_url to remove code redundant and inconsistence in\ncmd_init and cmd_add when resolving relative url/path to absolute one.\n\nAlso move resolving absolute url logic from cmd_add to module_clone which\nresults in a litte behaviour change: cmd_update originally doesn't\nresolve absolute url but now it will.\n\nThis behaviour change breaks t7400 which uses relative url './.subrepo'.\nHowever, this test originally doesn't mean to test relative url, so fix\nthe url as '.subrepo'.\n\nSigned-off-by: Ping Yin <pkufranky@gmail.com>\n---\n git-submodule.sh           |   41 ++++++++++++++++++-----------------------\n t/t7400-submodule-basic.sh |    2 +-\n 2 files changed, 19 insertions(+), 24 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 7545d1a..0e14078 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -65,6 +65,21 @@ resolve_relative_url ()\n \techo \"$remoteurl/$url\"\n }\n \n+# Resolve relative url/path to absolute one\n+absolute_url () {\n+\tcase \"$1\" in\n+\t./*|../*)\n+\t\t# dereference source url relative to parent's url\n+\t\turl=\"$(resolve_relative_url $1)\" ;;\n+\t*)\n+\t\t# Turn the source into an absolute path if it is local\n+\t\turl=$(get_repo_base \"$1\") ||\n+\t\turl=$1\n+\t\t;;\n+\tesac\n+\techo \"$url\"\n+}\n+\n #\n # Map submodule path to submodule name\n #\n@@ -112,7 +127,7 @@ module_info() {\n module_clone()\n {\n \tpath=$1\n-\turl=$2\n+\turl=$(absolute_url \"$2\")\n \n \t# If there already is a directory at the submodule path,\n \t# expect it to be empty (since that is the default checkout\n@@ -195,21 +210,7 @@ cmd_add()\n \t\t\tdie \"'$path' already exists and is not a valid git repo\"\n \t\tfi\n \telse\n-\t\tcase \"$repo\" in\n-\t\t./*|../*)\n-\t\t\t# dereference source url relative to parent's url\n-\t\t\trealrepo=\"$(resolve_relative_url $repo)\" ;;\n-\t\t*)\n-\t\t\t# Turn the source into an absolute path if\n-\t\t\t# it is local\n-\t\t\tif base=$(get_repo_base \"$repo\"); then\n-\t\t\t\trepo=\"$base\"\n-\t\t\tfi\n-\t\t\trealrepo=$repo\n-\t\t\t;;\n-\t\tesac\n-\n-\t\tmodule_clone \"$path\" \"$realrepo\" || exit\n+\t\tmodule_clone \"$path\" \"$repo\" || exit\n \t\t(unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"origin/$branch\"}) ||\n \t\tdie \"Unable to checkout submodule '$path'\"\n \tfi\n@@ -262,13 +263,7 @@ cmd_init()\n \t\ttest -z \"$url\" &&\n \t\tdie \"No url found for submodule path '$path' in .gitmodules\"\n \n-\t\t# Possibly a url relative to parent\n-\t\tcase \"$url\" in\n-\t\t./*|../*)\n-\t\t\turl=\"$(resolve_relative_url \"$url\")\"\n-\t\t\t;;\n-\t\tesac\n-\n+\t\turl=$(absolute_url \"$url\")\n \t\tgit config submodule.\"$name\".url \"$url\" ||\n \t\tdie \"Failed to register url for submodule path '$path'\"\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex 2ef85a8..e5d59b8 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -75,7 +75,7 @@ test_expect_success 'init should register submodule url in .git/config' '\n \tthen\n \t\techo \"[OOPS] init succeeded but submodule url is wrong\"\n \t\tfalse\n-\telif ! git config submodule.example.url ./.subrepo\n+\telif ! git config submodule.example.url .subrepo\n \tthen\n \t\techo \"[OOPS] init succeeded but update of url failed\"\n \t\tfalse\n-- \n1.5.4.4.653.g7cf1e\n"},{"id":"71966","messageId":"1205431001-18590-5-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-4-git-send-email-pkufranky@gmail.com","subject":"[PATCH 4/7] git-submodule: Fall back on .gitmodules if info not found in $GIT_DIR/config","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:38Z","receivedAt":"2008-03-13T17:56:38Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"Originally, the submodule workflow enforces 'git init' in the beginning\nwhich copies submodule config info from .gitmodules to $GIT_DIR/config.\nThen all subcommands except 'init' and 'add' fetch submodule info from\n$GIT_DIR/config and .gitmodules can be discarded.\n\nAnd there may be inconsistence between .git/config and .gitmodules when\nalways using 'git init' at first. If upstream .gitmodules changes, it is\nnot easy to sync the changes to $GIT_DIR/config. Running 'git init' again\nmay not help.\n\nSince .git/config has a whole copy of .gitmodules, the user has no easy\nway to know which entries should follow the upstream changes and which\nentires shouldn't.\n\nActually, .gitmodules which only acts as info hints can and should play\na more important and essential role.\n\nAs an analogy to .gitignore and .git/info/excludes which are for colleagues'\nand individual wishes separately, .gitmodules is for common requirements and\n$GIT_DIR/config is for special requirements.\n\nThis patch implements a fall back strategy to satify both common and\nspecial requirements as follows.\n\n$GIT_DIR/config only keeps submodule info different from $GIT_DIR/config.\nAnd the info from $GIT_DIR/config take higher precedence. The code first\nconsults $GIT_DIR/config and then fall back on in-tree .gitmodules file.\n\nWith this patch, init subcommand becomes not forcefull and less meaningful.\nAnd now it becomes just a tool to help users copy info to $GIT_DIR/config\n(and then modify it) only when they need.\n\nSigned-off-by: Ping Yin <pkufranky@gmail.com>\n---\n git-submodule.sh           |    9 ++++-----\n t/t7400-submodule-basic.sh |   29 +++++++++++++++++++++++++++++\n 2 files changed, 33 insertions(+), 5 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 0e14078..bd2934a 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -98,7 +98,8 @@ module_name()\n }\n \n module_url() {\n-\tgit config submodule.$1.url\n+\tgit config submodule.$1.url ||\n+\tGIT_CONFIG=.gitmodules git config submodule.$1.url\n }\n \n module_info() {\n@@ -256,12 +257,10 @@ cmd_init()\n \twhile read sha1 path name url\n \tdo\n \t\ttest -n \"$name\" || exit\n-\t\t# Skip already registered paths\n-\t\ttest -z \"$url\" || continue\n-\n-\t\turl=$(GIT_CONFIG=.gitmodules git config submodule.\"$name\".url)\n \t\ttest -z \"$url\" &&\n \t\tdie \"No url found for submodule path '$path' in .gitmodules\"\n+\t\t# Skip already registered paths\n+\t\tgit config submodule.$name.url && continue\n \n \t\turl=$(absolute_url \"$url\")\n \t\tgit config submodule.\"$name\".url \"$url\" ||\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex e5d59b8..d9b48f7 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -174,6 +174,35 @@ test_expect_success 'status should be \"up-to-date\" after update' '\n \tgit-submodule status | grep \"^ $rev1\"\n '\n \n+test_expect_success 'status should be \"modified\" after submodule reset --hard HEAD@{1}' '\n+\tcd init &&\n+\tgit reset --hard HEAD@{1}\n+\trev2=$(git rev-parse HEAD) &&\n+\tcd .. &&\n+\tif test -z \"$rev2\"\n+\tthen\n+\t\techo \"[OOPS] submodule git rev-parse returned nothing\"\n+\t\tfalse\n+\tfi &&\n+\tgit-submodule status | grep \"^+$rev2\"\n+'\n+\n+test_expect_success 'update should checkout rev1 when fall back' '\n+\tgit-config --unset submodule.example.url &&\n+\tGIT_CONFIG=.gitmodules git config submodule.example.url .subrepo &&\n+\tgit-submodule update init &&\n+\thead=$(cd init && git rev-parse HEAD) &&\n+\tif test -z \"$head\"\n+\tthen\n+\t\techo \"[OOPS] submodule git rev-parse returned nothing\"\n+\t\tfalse\n+\telif test \"$head\" != \"$rev1\"\n+\tthen\n+\t\techo \"[OOPS] init did not checkout correct head\"\n+\t\tfalse\n+\tfi\n+'\n+\n test_expect_success 'checkout superproject with subproject already present' '\n \tgit-checkout initial &&\n \tgit-checkout master\n-- \n1.5.4.4.653.g7cf1e\n"},{"id":"71972","messageId":"1205431001-18590-6-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-5-git-send-email-pkufranky@gmail.com","subject":"[PATCH 5/7] git-submodule: Extract module_add from cmd_add","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:39Z","receivedAt":"2008-03-13T17:56:39Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"cmd_add will later handle the case adding multiple modules, so extract\nmodule_add to add a single module.\n\nSigned-off-by: Ping Yin <pkufranky@gmail.com>\n---\n git-submodule.sh |   67 +++++++++++++++++++++++++++++++----------------------\n 1 files changed, 39 insertions(+), 28 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex bd2934a..dacd99a 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -155,34 +155,7 @@ module_clone()\n #\n # optional branch is stored in global branch variable\n #\n-cmd_add()\n-{\n-\t# parse $args after \"submodule ... add\".\n-\twhile test $# -ne 0\n-\tdo\n-\t\tcase \"$1\" in\n-\t\t-b | --branch)\n-\t\t\tcase \"$2\" in '') usage ;; esac\n-\t\t\tbranch=$2\n-\t\t\tshift\n-\t\t\t;;\n-\t\t-q|--quiet)\n-\t\t\tquiet=1\n-\t\t\t;;\n-\t\t--)\n-\t\t\tshift\n-\t\t\tbreak\n-\t\t\t;;\n-\t\t-*)\n-\t\t\tusage\n-\t\t\t;;\n-\t\t*)\n-\t\t\tbreak\n-\t\t\t;;\n-\t\tesac\n-\t\tshift\n-\tdone\n-\n+module_add() {\n \trepo=$1\n \tpath=$2\n \n@@ -226,6 +199,44 @@ cmd_add()\n }\n \n #\n+# Add a new submodule to the working tree, .gitmodules and the index\n+#\n+# $@ = repo [path]\n+#\n+# optional branch is stored in global branch variable\n+#\n+cmd_add()\n+{\n+\t# parse $args after \"submodule ... add\".\n+\twhile test $# -ne 0\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-b | --branch)\n+\t\t\tcase \"$2\" in '') usage ;; esac\n+\t\t\tbranch=$2\n+\t\t\tshift\n+\t\t\t;;\n+\t\t-q|--quiet)\n+\t\t\tquiet=1\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tusage\n+\t\t\t;;\n+\t\t*)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\tdone\n+\n+\tmodule_add \"$1\" \"$2\"\n+}\n+\n+#\n # Register submodules in .git/config\n #\n # $@ = requested paths (default to all)\n-- \n1.5.4.4.653.g7cf1e\n"},{"id":"71967","messageId":"1205431001-18590-7-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-6-git-send-email-pkufranky@gmail.com","subject":"[PATCH 6/7] git-submodule: multi-level module definition","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:40Z","receivedAt":"2008-03-13T17:56:40Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"This patch introduces multi-level module definition and '--module-name'\noption to designate submodules by logical names instead of path filters.\nThen the init/update/status/add subcommand is enhanced combined with\nthis option.\n\nThe multi-level module definition in .gitmodules was first suggested by\nLinus and etc. in mails \"Let .git/config specify the url for submodules\"\n(http://article.gmane.org/gmane.comp.version-control.git/48939).\n\nFollowing shows an example of such a .gitmodules which finally comes\nfrom the group notation of 'git remote' which is suggested by Johannes\nSchindelin.\n\n.gitmodules with multiple level of indirection\n------------------------------------------------------\n[submodules]\n\tservice = crawler search\n\tcrawler = util imcrawter\n\tsearch = util imsearch\n[submodule \"util\"]\n\turl = git://xyzzy/util.git\n[submodule \"imsearch\"]\n\tpath = search/imsearch\n\turl = git://xyzzy/imsearch.git\n[submodule \"imcrawler\"]\n\tpath = crawler/imcrawter\n\turl = git://xyzzy/imcrawter.git\n------------------------------------------------------\n\nBy adding the 'submodules' section, we can define multi-level modules\nin an infinite levels of indirection.\n\nThe \"-m|--module-name\" option is introduced with which submodules are\ndesignated by logical names instead of real paths as following shows.\n\nIdentical commands forms with/without \"--module-name\"\n---------------------------------------------------\n$ git submodule XXX util imcrawler              (1)\n$ git submodule XXX -n crawler                  (2)\n$ git submodule XXX util imcrawler imsearch     (3)\n$ git submodule XXX -n service                  (4)\n$ git submodule XXX -n crawler search           (5)\n---------------------------------------------------\n* XXX represents status, update or init, but not add\n* (1) and (2) are identical conditionally (explained below)\n* (3), (4) and (5) are identical conditionally\n\nThere are still minor difference between these two forms.\n\nIn the no \"--module-name\" form, the path parameter may be not the real\nsubmodule path, and it just acts as the filter for real submodule paths.\nWhile in the \"--module-name\" form, the name parameter must be the logical\nname, and the real paths corresponding to the logical name may be neither\na submodule path nor even existent.\n\nThis patch handles such a path for different subcommands as follows.\n\n - status: Output 0{40} as the sha1. Doing this can remind the user to\n   add the path as submodule or delete the path from .gitmodules.\n - update: Skip that path and issue a \"Not a submodule\" warning\n - init: Also init for that path\n\nSo in the example above, commands (1) and (2) are identical only when\nutil and imcrawler are already submodules.\n\nThe add subcommand is also enhanced.\n\nThe former workflow to add submodules is adding one by one with\n\"git submodule add url path\" which then modifies .gitmodules. However,\nsometimes it is more convenient to work in the reverse way: edit\n.gitmodules first and then add submodules in batch.\n\nNow \"git submodule add --module-name modulename\" can help us to do that.\nIt will find all submodules corresponding to the logical name and add them\nin batch by using the paths and urls from .gitmodules. Of course, it will\nskip the paths which have already been submodules.\n\nSigned-off-by: Ping Yin <pkufranky@gmail.com>\n---\n git-submodule.sh |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++---\n 1 files changed, 81 insertions(+), 5 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex dacd99a..79fb30f 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -4,7 +4,7 @@\n #\n # Copyright (c) 2007 Lars Hjemli\n \n-USAGE=\"[--quiet] [--cached] \\\n+USAGE=\"[--quiet] [--cached] [--module-name] \\\n [add <repo> [-b branch]|status|init|update|summary [-n|--summary-limit <n>] [<commit>]] \\\n [--] [<path>...]\"\n OPTIONS_SPEC=\n@@ -15,6 +15,7 @@ command=\n branch=\n quiet=\n cached=\n+use_module_name=\n \n #\n # print stuff on stdout unless -q was specified\n@@ -97,12 +98,23 @@ module_name()\n        echo \"$name\"\n }\n \n+module_path() {\n+\tgit config submodule.$1.path ||\n+\tGIT_CONFIG=.gitmodules git config submodule.$1.path ||\n+\techo \"$1\"\n+}\n+\n module_url() {\n \tgit config submodule.$1.url ||\n \tGIT_CONFIG=.gitmodules git config submodule.$1.url\n }\n \n module_info() {\n+\tif test -n \"$use_module_name\"\n+\tthen\n+\t\tmodule_info_by_name \"$@\"\n+\t\treturn\n+\tfi\n \tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n \twhile read mode sha1 stage path\n \tdo\n@@ -118,6 +130,50 @@ module_info() {\n }\n \n #\n+# List all submodule info line by line by given names as follows\n+# sha1<tab>path<tab>name<tab>url\n+#\n+# Here we assume that module names and paths don't contain space\n+# characters\n+#\n+# $@ = module names\n+# When names is not given, list all module info\n+#\n+module_info_by_name() {\n+\tif test $# = 0\n+\tthen\n+\t\tnames=$(\n+\t\t{\n+\t\t\tgit config --get-regexp 'submodule.*.url'\n+\t\t\tgit config -f .gitmodules --get-regexp 'submodule.*.url'\n+\t\t} | sed 's/submodule.\\(.*\\).url .*$/\\1/' 2>/dev/null\n+\t\t)\n+\telse\n+\t\tnames=$(module_children_names \"$@\")\n+\tfi\n+\tfor name in $names\n+\tdo\n+\t\turl=$(module_url \"$name\") || continue\n+\t\tpath=$(module_path \"$name\")\n+\t\tsha1=$(git ls-files --stage \"$path\" |\n+\t\t\tgrep \"$path$\" | grep '^160000' | awk '{print $2}')\n+\t\ttest -z \"$sha1\" && sha1=0000000000000000000000000000000000000000\n+\t\techo \"$sha1\t$path\t$name\t$url\"\n+\tdone\n+}\n+\n+module_children_names() {\n+\tfor name\n+\tdo\n+\t\techo \"$name\"\n+\t\tmodule_children_names $(\n+\t\t\tgit config \"submodules.$name\"\n+\t\t\tgit config -f .gitmodules \"submodules.$name\"\n+\t\t)\n+\tdone | sort -u\n+}\n+\n+#\n # Clone a submodule\n #\n # Prior to calling, cmd_update checks that a possibly existing\n@@ -233,7 +289,17 @@ cmd_add()\n \t\tshift\n \tdone\n \n-\tmodule_add \"$1\" \"$2\"\n+\tif test -n \"$use_module_name\"\n+\tthen\n+\t\tmodule_info \"$@\" |\n+\t\twhile read sha1 path name url\n+\t\tdo\n+\t\t\tmodule_add \"$url\" \"$path\"\n+\t\tdone\n+\telse\n+\t\tmodule_add \"$1\" \"$2\"\n+\tfi\n+\n }\n \n #\n@@ -313,7 +379,11 @@ cmd_update()\n \twhile read sha1 path name url\n \tdo\n \t\ttest -n \"$name\" || exit\n-\t\tif test -z \"$url\"\n+\t\tif test $sha1 = 0000000000000000000000000000000000000000\n+\t\tthen\n+\t\t\tsay \"Not a submodule: $name @ $path\"\n+\t\t\tcontinue\n+\t\telif test -z \"$url\"\n \t\tthen\n \t\t\t# Only mention uninitialized submodules when its\n \t\t\t# path have been specified\n@@ -558,12 +628,15 @@ cmd_status()\n \t\tesac\n \t\tshift\n \tdone\n-\n \tmodule_info \"$@\" |\n \twhile read sha1 path name url\n \tdo\n \t\ttest -n \"$name\" || exit\n-\t\tif test -z \"$url\" || ! test -d \"$path\"/.git\n+\t\tif test $sha1 = 0000000000000000000000000000000000000000\n+\t\tthen\n+\t\t\tsay \"*$sha1 $path\"\n+\t\t\tcontinue\n+\t\telif test -z \"$url\" || ! test -d \"$path\"/.git\n \t\tthen\n \t\t\tsay \"-$sha1 $path\"\n \t\t\tcontinue;\n@@ -609,6 +682,9 @@ do\n \t--cached)\n \t\tcached=\"$1\"\n \t\t;;\n+\t-m|--module-name)\n+\t\tuse_module_name=1\n+\t\t;;\n \t--)\n \t\tbreak\n \t\t;;\n-- \n1.5.4.4.653.g7cf1e\n"},{"id":"71968","messageId":"1205431001-18590-8-git-send-email-pkufranky@gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-7-git-send-email-pkufranky@gmail.com","subject":"[PATCH 7/7] git-submodule: Don't die when command fails for one submodule","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T17:56:41Z","receivedAt":"2008-03-13T17:56:41Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"When handling multiple modules, init/update/status/add subcommand will\nexit when it fails for one submodule. This patch makes the subcommand\ncontinue bypassing the failure and keep right exit status.\n\nSigned-off-by: Ping Yin <pkufranky@gmail.com>\n---\n git-submodule.sh |   87 +++++++++++++++++++++++++++++++++++++++---------------\n 1 files changed, 63 insertions(+), 24 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 79fb30f..e78d797 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -193,15 +193,19 @@ module_clone()\n \t# succeed but the rmdir will fail. We might want to fix this.\n \tif test -d \"$path\"\n \tthen\n-\t\trmdir \"$path\" 2>/dev/null ||\n-\t\tdie \"Directory '$path' exist, but is neither empty nor a git repository\"\n+\t\t! rmdir \"$path\" 2>/dev/null &&\n+\t\tsay \"Directory '$path' exist, but is neither empty nor a git repository\" &&\n+\t\treturn 1\n \tfi\n \n \ttest -e \"$path\" &&\n-\tdie \"A file already exist at path '$path'\"\n+\tsay \"A file already exist at path '$path'\" &&\n+\treturn 1\n \n-\tgit-clone -n \"$url\" \"$path\" ||\n-\tdie \"Clone of '$url' into submodule path '$path' failed\"\n+\t! git-clone -n \"$url\" \"$path\" &&\n+\tsay \"Clone of '$url' into submodule path '$path' failed\" &&\n+\treturn 1\n+\t:\n }\n \n #\n@@ -227,7 +231,8 @@ module_add() {\n \tfi\n \n \tgit ls-files --error-unmatch \"$path\" > /dev/null 2>&1 &&\n-\tdie \"'$path' already exists in the index\"\n+\tsay \"'$path' already exists in the index\" &&\n+\treturn 1\n \n \t# perhaps the path exists and is already a git repo, else clone it\n \tif test -e \"$path\"\n@@ -237,21 +242,26 @@ module_add() {\n \t\tthen\n \t\t\techo \"Adding existing repo at '$path' to the index\"\n \t\telse\n-\t\t\tdie \"'$path' already exists and is not a valid git repo\"\n+\t\t\tsay \"'$path' already exists and is not a valid git repo\"\n+\t\t\treturn 1\n \t\tfi\n \telse\n-\t\tmodule_clone \"$path\" \"$repo\" || exit\n-\t\t(unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"origin/$branch\"}) ||\n-\t\tdie \"Unable to checkout submodule '$path'\"\n+\t\tmodule_clone \"$path\" \"$repo\" || return 1\n+\t\t! (unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"origin/$branch\"}) &&\n+\t\tsay \"Unable to checkout submodule '$path'\" &&\n+\t\treturn 1\n \tfi\n \n-\tgit add \"$path\" ||\n-\tdie \"Failed to add submodule '$path'\"\n+\t! git add \"$path\" &&\n+\tsay \"Failed to add submodule '$path'\" &&\n+\treturn 1\n \n \tGIT_CONFIG=.gitmodules git config submodule.\"$path\".path \"$path\" &&\n \tGIT_CONFIG=.gitmodules git config submodule.\"$path\".url \"$repo\" &&\n-\tgit add .gitmodules ||\n-\tdie \"Failed to register submodule '$path'\"\n+\t! git add .gitmodules &&\n+\tsay \"Failed to register submodule '$path'\" &&\n+\treturn 1\n+\t:\n }\n \n #\n@@ -292,14 +302,17 @@ cmd_add()\n \tif test -n \"$use_module_name\"\n \tthen\n \t\tmodule_info \"$@\" |\n+\t\t{\n+\t\texit_status=0\n \t\twhile read sha1 path name url\n \t\tdo\n-\t\t\tmodule_add \"$url\" \"$path\"\n+\t\t\tmodule_add \"$url\" \"$path\" || exit_status=1\n \t\tdone\n+\t\ttest $exit_status = 0\n+\t\t}\n \telse\n \t\tmodule_add \"$1\" \"$2\"\n \tfi\n-\n }\n \n #\n@@ -331,20 +344,30 @@ cmd_init()\n \tdone\n \n \tmodule_info \"$@\" |\n+\t{\n+\texit_status=0\n \twhile read sha1 path name url\n \tdo\n-\t\ttest -n \"$name\" || exit\n+\t\ttest -z \"$name\" && exit_status=1 && continue\n \t\ttest -z \"$url\" &&\n-\t\tdie \"No url found for submodule path '$path' in .gitmodules\"\n+\t\tsay \"No url found for submodule path '$path' in .gitmodules\" &&\n+\t\texit_status=1 &&\n+\t\tcontinue\n \t\t# Skip already registered paths\n \t\tgit config submodule.$name.url && continue\n \n \t\turl=$(absolute_url \"$url\")\n \t\tgit config submodule.\"$name\".url \"$url\" ||\n-\t\tdie \"Failed to register url for submodule path '$path'\"\n+\t\t{\n+\t\tsay \"Failed to register url for submodule path '$path'\"\n+\t\texit_status=1\n+\t\tcontinue\n+\t\t}\n \n \t\tsay \"Submodule '$name' ($url) registered for path '$path'\"\n \tdone\n+\texit $exit_status\n+\t}\n }\n \n #\n@@ -376,9 +399,11 @@ cmd_update()\n \tdone\n \n \tmodule_info \"$@\" |\n+\t{\n+\texit_status=0\n \twhile read sha1 path name url\n \tdo\n-\t\ttest -n \"$name\" || exit\n+\t\ttest -z \"$name\" && exit_status=1 && continue\n \t\tif test $sha1 = 0000000000000000000000000000000000000000\n \t\tthen\n \t\t\tsay \"Not a submodule: $name @ $path\"\n@@ -394,23 +419,33 @@ cmd_update()\n \n \t\tif ! test -d \"$path\"/.git\n \t\tthen\n-\t\t\tmodule_clone \"$path\" \"$url\" || exit\n+\t\t\t! module_clone \"$path\" \"$url\" && exit_status=1 && continue\n \t\t\tsubsha1=\n \t\telse\n \t\t\tsubsha1=$(unset GIT_DIR; cd \"$path\" &&\n \t\t\t\tgit rev-parse --verify HEAD) ||\n-\t\t\tdie \"Unable to find current revision in submodule path '$path'\"\n+\t\t\t{\n+\t\t\t\tsay \"Unable to find current revision in submodule path '$path'\"\n+\t\t\t\texit_status=1\n+\t\t\t\tcontinue\n+\t\t\t}\n \t\tfi\n \n \t\tif test \"$subsha1\" != \"$sha1\"\n \t\tthen\n \t\t\t(unset GIT_DIR; cd \"$path\" && git-fetch &&\n \t\t\t\tgit-checkout -q \"$sha1\") ||\n-\t\t\tdie \"Unable to checkout '$sha1' in submodule path '$path'\"\n+\t\t\t{\n+\t\t\t\tsay \"Unable to checkout '$sha1' in submodule path '$path'\"\n+\t\t\t\texit_status=1\n+\t\t\t\tcontinue\n+\t\t\t}\n \n \t\t\tsay \"Submodule path '$path': checked out '$sha1'\"\n \t\tfi\n \tdone\n+\texit $exit_status\n+\t}\n }\n \n set_name_rev () {\n@@ -629,9 +664,11 @@ cmd_status()\n \t\tshift\n \tdone\n \tmodule_info \"$@\" |\n+\t{\n+\texit_status=0\n \twhile read sha1 path name url\n \tdo\n-\t\ttest -n \"$name\" || exit\n+\t\ttest -z \"$name\" && exit_status=1 && continue\n \t\tif test $sha1 = 0000000000000000000000000000000000000000\n \t\tthen\n \t\t\tsay \"*$sha1 $path\"\n@@ -654,6 +691,8 @@ cmd_status()\n \t\t\tsay \"+$sha1 $path$revname\"\n \t\tfi\n \tdone\n+\texit $exit_status\n+\t}\n }\n \n # This loop parses the command line arguments to find the\n-- \n1.5.4.4.653.g7cf1e\n"},{"id":"71979","messageId":"46dff0320803131116k5a4caa84x658369c491f1a175@mail.gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-1-git-send-email-pkufranky@gmail.com","subject":"Re: [PATCH 0/7] git-submodule enhancements","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-13T18:16:17Z","receivedAt":"2008-03-13T18:16:17Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"On Fri, Mar 14, 2008 at 1:56 AM, Ping Yin <pkufranky@gmail.com> wrote:\n> This patch series do following enhancements for git-submodule\n>\n>   - Fall back on .gitmodules if info not found in $GIT_DIR/config\n>   - multi-level module definition\n>   - Don't die when command fails for one submodule\n\nAnd it's built on next\n\n\n-- \nPing Yin\n"},{"id":"72084","messageId":"46dff0320803140720h619107c6v83ef1a3d13866fb9@mail.gmail.com","threadId":"12673","inReplyTo":"1205431001-18590-7-git-send-email-pkufranky@gmail.com","subject":"Re: [PATCH 6/7] git-submodule: multi-level module definition","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-14T14:20:38Z","receivedAt":"2008-03-14T14:20:38Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"On Fri, Mar 14, 2008 at 1:56 AM, Ping Yin <pkufranky@gmail.com> wrote:\n\n>  In the no \"--module-name\" form, the path parameter may be not the real\n>  submodule path, and it just acts as the filter for real submodule paths.\n>  While in the \"--module-name\" form, the name parameter must be the logical\n>  name, and the real paths corresponding to the logical name may be neither\n>  a submodule path nor even existent.\n>\n>  This patch handles such a path for different subcommands as follows.\n>\n>   - status: Output 0{40} as the sha1. Doing this can remind the user to\n>    add the path as submodule or delete the path from .gitmodules.\n>   - update: Skip that path and issue a \"Not a submodule\" warning\n\nSometime it's useful to also update (or clone) the non-submodule\ninstead of \"Not as submodule\" warning. So we can add a --force option\nto allow this kind of behaviour.\n\nThere are cases that we want to clone a group of repositories in batch.\n\nOne way is to put all urls and paths of these repositories in\n.gitmodules which form a submodule group, for example \"all\", and then\nrun \"git submodule --module-name update --force all\" which will clone\nall the repositories in batch even if they are not submodules yet.\n\nAnother way is use the \"git submodule --module-name recurse clone\"\n(recurse patch series sent many days ago but not accept yet). But this\nneeds some discuss since we have no place for the module group name\n\"all\" as the argument.\n\nThere may be other ways. i don't know which way is better and don't\ncare much now. What i care is whether the submodule subcommand should\noperate on the non-submodule path.\n\nMore precisely, with --module-name, we can designate a group of names\nby a logical group name. However, some paths corresponding to these\nnames may not be submodules yet. So should the submodule subcommands\n(especially update for now) operate on these paths?\n\n-- \nPing Yin\n"}]}