{"thread":{"id":"27874","subject":"[RFC PATCH] Move git-dir for submodules","startedAt":"2011-07-21T16:52:19Z","lastAt":"2011-07-22T20:30:10Z","messageCount":8,"participants":["Fredrik Gustafsson","Junio C Hamano","Phil Hord"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"171779","messageId":"1311267139-14658-1-git-send-email-iveqy@iveqy.com","threadId":"27874","inReplyTo":null,"subject":"[RFC PATCH] Move git-dir for submodules","fromName":"Fredrik Gustafsson","fromEmail":"iveqy@iveqy.com","sentAt":"2011-07-21T16:52:19Z","receivedAt":"2011-07-21T16:52:19Z","isPatch":true,"sender":{"key":"iveqy@iveqy.com","avatar":"https://avatars.githubusercontent.com/u/761743?v=4"},"body":"Move git-dir for submodules into $GIT_DIR/modules/[name_of_submodule] of\nthe superproject. This is a step towards being able to delete submodule\ndirectories without loosing the information from their .git directory\nas that is now stored outside the submodules work tree.\n\nThis is done relying on the already existent .git-file functionality.\nTests that rely on .git being a directory have been fixed.\n\nSigned-off-by: Fredrik Gustafsson <iveqy@iveqy.com>\nMentored-by: Jens Lehmann <Jens.Lehmann@web.de>\nMentored-by: Heiko Voigt <hvoigt@hvoigt.net>\n---\n git-submodule.sh               |   52 ++++++++++++++++++--\n t/t7400-submodule-basic.sh     |    4 +-\n t/t7403-submodule-sync.sh      |    2 +-\n t/t7406-submodule-update.sh    |  105 ++++++++++++++++++++++++++++++++++++++++\n t/t7407-submodule-foreach.sh   |   98 +++++++++++++++++++-------------------\n t/t7408-submodule-reference.sh |    4 +-\n 6 files changed, 206 insertions(+), 59 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 87c9452..3ad3012 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -122,14 +122,56 @@ module_clone()\n \tpath=$1\n \turl=$2\n \treference=\"$3\"\n+\tgitdir=\n+\tgitdir_base=\n+\tbase_path=`echo $path | sed -e 's|[^/]*$||'`\n \n-\tif test -n \"$reference\"\n+\tif test -z \"$GIT_DIR\"\n \tthen\n-\t\tgit-clone \"$reference\" -n \"$url\" \"$path\"\n+\t\tgitdir=$(git rev-parse --git-dir)\n+\t\tgitdir_base=\"$gitdir/modules/$base_path\"\n+\t\tgitdir=\"$gitdir/modules/$path\"\n \telse\n-\t\tgit-clone -n \"$url\" \"$path\"\n-\tfi ||\n-\tdie \"$(eval_gettext \"Clone of '\\$url' into submodule path '\\$path' failed\")\"\n+\t\tgitdir=\"$GIT_DIR/modules/$path\"\n+\t\tgitdir_base=\"$GIT_DIR/modules/$base_path\"\n+\tfi\n+\n+\tcase $gitdir in\n+\t\t/*)\n+\t\t\ta=\"$(cd_to_toplevel && pwd)/\"\n+\t\t\tb=$gitdir\n+\t\t\twhile [ \"$b\" ] && [ \"${a%%/*}\" = \"${b%%/*}\" ]\n+\t\t\tdo\n+\t\t\t\ta=${a#*/} b=${b#*/};\n+\t\t\tdone\n+\n+\t\t\trel=\"$a$path\"\n+\t\t\trel=`echo $rel | sed -e 's|[^/]*|..|g'`\n+\t\t\trel_gitdir=\"$rel/$b\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\trel=`echo $path | sed -e 's|[^/]*|..|g'`\n+\t\t\trel_gitdir=\"$rel/$gitdir\"\n+\t\t\t;;\n+\tesac\n+\n+\tif test -d \"$gitdir\"\n+\tthen\n+\t\tmkdir -p \"$path\"\n+\t\techo \"gitdir: $rel_gitdir\" > \"$path/.git\"\n+\telse\n+\t\tif !(test -d \"$gitdir_base\")\n+\t\tthen\n+\t\t\tmkdir -p \"$gitdir_base\"\n+\t\tfi\n+\t\tif test -n \"$reference\"\n+\t\tthen\n+\t\t\tgit-clone \"$reference\" -n \"$url\" \"$path\" --separate-git-dir \"$gitdir\"\n+\t\telse\n+\t\t\tgit-clone -n \"$url\" \"$path\" --separate-git-dir \"$gitdir\"\n+\t\tfi ||\n+\t\tdie \"$(eval_gettext \"Clone of '\\$url' into submodule path '\\$path' failed\")\"\n+\tfi\n }\n \n #\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex b2b26b7..57f5306 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -358,10 +358,10 @@ test_expect_success 'update --init' '\n \tgit submodule update init > update.out &&\n \tcat update.out &&\n \ttest_i18ngrep \"not initialized\" update.out &&\n-\t! test -d init/.git &&\n+\t! test -f init/.git &&\n \n \tgit submodule update --init init &&\n-\ttest -d init/.git\n+\ttest -n $(grep \"/^gitdir: /\" init/.git)\n '\n \n test_expect_success 'do not add files from a submodule' '\ndiff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh\nindex d600583..b0517f0 100755\n--- a/t/t7403-submodule-sync.sh\n+++ b/t/t7403-submodule-sync.sh\n@@ -55,7 +55,7 @@ test_expect_success '\"git submodule sync\" should update submodule URLs' '\n \t git pull --no-recurse-submodules &&\n \t git submodule sync\n \t) &&\n-\ttest -d \"$(git config -f super-clone/submodule/.git/config \\\n+\ttest -d \"$(git config -f super-clone/.git/modules/submodule/config \\\n \t                        remote.origin.url)\" &&\n \t(cd super-clone/submodule &&\n \t git checkout master &&\ndiff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh\nindex c679f36..32d9c59 100755\n--- a/t/t7406-submodule-update.sh\n+++ b/t/t7406-submodule-update.sh\n@@ -442,4 +442,109 @@ test_expect_success 'submodule update exit immediately after recursive rebase er\n \t test_cmp expect actual\n \t)\n '\n+\n+test_expect_success 'submodule add places git-dir in superprojects git-dir' '\n+\t(cd super &&\n+\t mkdir deeper &&\n+\t git submodule add ../submodule deeper/submodule &&\n+\t (cd deeper/submodule &&\n+\t  git log > ../../expected\n+\t ) &&\n+\t (cd .git/modules/deeper/submodule &&\n+\t  git log > ../../../../actual\n+\t ) &&\n+\t test_cmp actual expected\n+\t)\n+'\n+\n+test_expect_success 'submodule update places git-dir in superprojects git-dir' '\n+\t(cd super &&\n+\t git commit -m \"added submodule\"\n+\t) &&\n+\tgit clone super super2 &&\n+\t(cd super2 &&\n+\t git submodule init deeper/submodule &&\n+\t git submodule update &&\n+\t (cd deeper/submodule &&\n+\t  git log > ../../expected\n+\t ) &&\n+\t (cd .git/modules/deeper/submodule &&\n+\t  git log > ../../../../actual\n+\t ) &&\n+\t test_cmp actual expected\n+\t)\n+'\n+\n+test_expect_success 'submodule add places git-dir in superprojects git-dir recursive' '\n+\t(cd super2 &&\n+\t (cd deeper/submodule &&\n+\t  git submodule add ../submodule subsubmodule &&\n+\t  (cd subsubmodule &&\n+\t   git log > ../../../expected\n+\t  ) &&\n+\t  git commit -m \"added subsubmodule\" &&\n+\t  git push\n+\t ) &&\n+\t (cd .git/modules/deeper/submodule/modules/subsubmodule &&\n+\t  git log > ../../../../../actual\n+\t ) &&\n+\t git add deeper/submodule &&\n+\t git commit -m \"update submodule\" &&\n+\t git push &&\n+\t test_cmp actual expected\n+\t)\n+'\n+\n+test_expect_success 'submodule update places git-dir in superprojects git-dir recursive' '\n+\tmkdir super_update_r &&\n+\t(cd super_update_r &&\n+\t git init --bare\n+\t) &&\n+\tmkdir subsuper_update_r &&\n+\t(cd subsuper_update_r &&\n+\t git init --bare\n+\t) &&\n+\tmkdir subsubsuper_update_r &&\n+\t(cd subsubsuper_update_r &&\n+\t git init --bare\n+\t) &&\n+\tgit clone subsubsuper_update_r subsubsuper_update_r2 &&\n+\t(cd subsubsuper_update_r2 &&\n+\t test_commit \"update_subsubsuper\" file &&\n+\t git push origin master\n+\t) &&\n+\tgit clone subsuper_update_r subsuper_update_r2 &&\n+\t(cd subsuper_update_r2 &&\n+\t test_commit \"update_subsuper\" file &&\n+\t git submodule add ../subsubsuper_update_r subsubmodule &&\n+\t git commit -am \"subsubmodule\" &&\n+\t git push origin master\n+\t) &&\n+\tgit clone super_update_r super_update_r2 &&\n+\t(cd super_update_r2 &&\n+\t test_commit \"update_super\" file &&\n+\t git submodule add ../subsuper_update_r submodule &&\n+\t git commit -am \"submodule\" &&\n+\t git push origin master\n+\t) &&\n+\trm -rf super_update_r2 &&\n+\tgit clone super_update_r super_update_r2 &&\n+\t(cd super_update_r2 &&\n+\t git submodule update --init --recursive &&\n+\t (cd submodule/subsubmodule &&\n+\t  git log > ../../expected\n+\t ) &&\n+\t (cd .git/modules/submodule/modules/subsubmodule\n+\t  git log > ../../../../../actual\n+\t )\n+\t test_cmp actual expected\n+\t)\n+'\n+\n+test_expect_success 'add different submodules to the same path' '\n+\t(cd super &&\n+\t git submodule add ../submodule s1 &&\n+\t test_must_fail git submodule add ../merging s1\n+\t)\n+'\n test_done\ndiff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh\nindex be745fb..3f498a3 100755\n--- a/t/t7407-submodule-foreach.sh\n+++ b/t/t7407-submodule-foreach.sh\n@@ -118,19 +118,19 @@ test_expect_success 'use \"submodule foreach\" to checkout 2nd level submodule' '\n \tgit clone super clone2 &&\n \t(\n \t\tcd clone2 &&\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 ! -f sub1/.git &&\n+\t\ttest ! -f sub2/.git &&\n+\t\ttest ! -f sub3/.git &&\n+\t\ttest ! -f nested1/.git &&\n \t\tgit submodule update --init &&\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 -n $(grep \"/^gitdir: /\" sub1/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" sub2/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" sub3/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/.git) &&\n+\t\ttest ! -f nested1/nested2/.git &&\n \t\tgit submodule foreach \"git submodule update --init\" &&\n-\t\ttest -d nested1/nested2/.git &&\n-\t\ttest ! -d nested1/nested2/nested3/.git\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/.git) &&\n+\t\ttest ! -f nested1/nested2/nested3/.git\n \t)\n '\n \n@@ -138,8 +138,8 @@ test_expect_success 'use \"foreach --recursive\" to checkout all submodules' '\n \t(\n \t\tcd clone2 &&\n \t\tgit submodule foreach --recursive \"git submodule update --init\" &&\n-\t\ttest -d nested1/nested2/nested3/.git &&\n-\t\ttest -d nested1/nested2/nested3/submodule/.git\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/nested3/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/nested3/submodule/).git\n \t)\n '\n \n@@ -183,18 +183,18 @@ test_expect_success 'use \"update --recursive\" to checkout all submodules' '\n \tgit clone super clone3 &&\n \t(\n \t\tcd clone3 &&\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 ! -f sub1/.git &&\n+\t\ttest ! -f sub2/.git &&\n+\t\ttest ! -f sub3/.git &&\n+\t\ttest ! -f nested1/.git &&\n \t\tgit submodule update --init --recursive &&\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\ttest -n $(grep \"/^gitdir: /\" sub1/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" sub2/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" sub3/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/nested3/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/nested3/submodule/).git\n \t)\n '\n \n@@ -248,13 +248,13 @@ test_expect_success 'ensure \"status --cached --recursive\" preserves the --cached\n test_expect_success 'use \"git clone --recursive\" to checkout all submodules' '\n \tgit clone --recursive super clone4 &&\n \ttest -d clone4/.git &&\n-\ttest -d clone4/sub1/.git &&\n-\ttest -d clone4/sub2/.git &&\n-\ttest -d clone4/sub3/.git &&\n-\ttest -d clone4/nested1/.git &&\n-\ttest -d clone4/nested1/nested2/.git &&\n-\ttest -d clone4/nested1/nested2/nested3/.git &&\n-\ttest -d clone4/nested1/nested2/nested3/submodule/.git\n+\ttest -n $(grep \"/^gitdir: /\" clone4/sub1/.git) &&\n+\ttest -n $(grep \"/^gitdir: /\" clone4/sub2/.git) &&\n+\ttest -n $(grep \"/^gitdir: /\" clone4/sub3/.git) &&\n+\ttest -n $(grep \"/^gitdir: /\" clone4/nested1/.git) &&\n+\ttest -n $(grep \"/^gitdir: /\" clone4/nested1/nested2/.git) &&\n+\ttest -n $(grep \"/^gitdir: /\" clone4/nested1/nested2/nested3/.git) &&\n+\ttest -n $(grep \"/^gitdir: /\" clone4/nested1/nested2/nested3/submodule/.git)\n '\n \n test_expect_success 'test \"update --recursive\" with a flag with spaces' '\n@@ -262,14 +262,14 @@ test_expect_success 'test \"update --recursive\" with a flag with spaces' '\n \tgit clone super clone5 &&\n \t(\n \t\tcd clone5 &&\n-\t\ttest ! -d nested1/.git &&\n+\t\ttest ! -f 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\ttest -n $(grep \"/^gitdir: /\" nested1/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/nested3/.git) &&\n+\t\ttest -f .git/modules/nested1/objects/info/alternates &&\n+\t\ttest -f .git/modules/nested1/modules/nested2/objects/info/alternates &&\n+\t\ttest -f .git/modules/nested1/modules/nested2/modules/nested3/objects/info/alternates\n \t)\n '\n \n@@ -277,18 +277,18 @@ test_expect_success 'use \"update --recursive nested1\" to checkout all submodules\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\ttest ! -f sub1/.git &&\n+\t\ttest ! -f sub2/.git &&\n+\t\ttest ! -f sub3/.git &&\n+\t\ttest ! -f 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\ttest ! -f sub1/.git &&\n+\t\ttest ! -f sub2/.git &&\n+\t\ttest ! -f sub3/.git &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/nested3/.git) &&\n+\t\ttest -n $(grep \"/^gitdir: /\" nested1/nested2/nested3/submodule/.git)\n \t)\n '\n \ndiff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh\nindex cc16d3f..ab37c36 100755\n--- a/t/t7408-submodule-reference.sh\n+++ b/t/t7408-submodule-reference.sh\n@@ -43,7 +43,7 @@ git commit -m B-super-added'\n cd \"$base_dir\"\n \n test_expect_success 'after add: existence of info/alternates' \\\n-'test `wc -l <super/sub/.git/objects/info/alternates` = 1'\n+'test `wc -l <super/.git/modules/sub/objects/info/alternates` = 1'\n \n cd \"$base_dir\"\n \n@@ -66,7 +66,7 @@ test_expect_success 'update with reference' \\\n cd \"$base_dir\"\n \n test_expect_success 'after update: existence of info/alternates' \\\n-'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1'\n+'test `wc -l <super-clone/.git/modules/sub/objects/info/alternates` = 1'\n \n cd \"$base_dir\"\n \n-- \n1.7.6.132.ga34b5.dirty\n"},{"id":"171818","messageId":"7vhb6f1ipp.fsf@alter.siamese.dyndns.org","threadId":"27874","inReplyTo":"1311267139-14658-1-git-send-email-iveqy@iveqy.com","subject":"Re: [RFC PATCH] Move git-dir for submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-07-21T20:28:50Z","receivedAt":"2011-07-21T20:28:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Fredrik Gustafsson <iveqy@iveqy.com> writes:\n\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index 87c9452..3ad3012 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -122,14 +122,56 @@ module_clone()\n>  \tpath=$1\n>  \turl=$2\n>  \treference=\"$3\"\n> +\tgitdir=\n> +\tgitdir_base=\n> +\tbase_path=`echo $path | sed -e 's|[^/]*$||'`\n\nWe prefer $() over `` these days, no?  Without dq around $path, you would\nnot be able to preserve $IFS inside $PATH. You are stripping a run of non\nslash at the trailing end --- is 'dirname \"$path\"' insufficient?\n\nI think you are using the path the submodule happens to be at in the\ncurrent checkout to decide where in the .git/modules in the superproject\nto keep the submodule metadata directory. Shouldn't you be using\nmodule_name to convert the $path to the name of the submodule (this is\nimportant, as the same submodule that used to be at path P1 can be moved\nto a different path P2 in the history).\n\n> +\tif test -z \"$GIT_DIR\"\n>  \tthen\n> +\t\tgitdir=$(git rev-parse --git-dir)\n> +\t\tgitdir_base=\"$gitdir/modules/$base_path\"\n> +\t\tgitdir=\"$gitdir/modules/$path\"\n>  \telse\n> +\t\tgitdir=\"$GIT_DIR/modules/$path\"\n> +\t\tgitdir_base=\"$GIT_DIR/modules/$base_path\"\n> +\tfi\n\nWhy do you need to switch on \"test -z $GIT_DIR\" yourself to have two\npaths?  Doesn't \"git rev-parse --git-dir\" already know to take $GIT_DIR\ninto account?\n\n> +\tcase $gitdir in\n> +\t\t/*)\n\nIndent case arm labels at the same level as \"case/esac\".\n\n> +\tif test -d \"$gitdir\"\n> +\tthen\n> +\t\tmkdir -p \"$path\"\n> +\t\techo \"gitdir: $rel_gitdir\" > \"$path/.git\"\n\nGood: if it already exists, do not clone, but just reuse what .git/modules\nhierarchy of the superproject has. Is it really necessary to have an ugly\nloop to make things relative, though?\n\nAlso please lose the extra SP after redirection, i.e.\n\n\tcommand >\"$path/.git\"\n\n> +\telse\n> +\t\tif !(test -d \"$gitdir_base\")\n\nDo you need subshell for this?\n\n> +\t\tthen\n> +\t\t\tmkdir -p \"$gitdir_base\"\n> +\t\tfi\n\nDoesn't unconditional \"mkdir -p\" do the right thing?\n\n> +\t\tif test -n \"$reference\"\n> +\t\tthen\n> +\t\t\tgit-clone \"$reference\" -n \"$url\" \"$path\" --separate-git-dir \"$gitdir\"\n> +\t\telse\n> +\t\t\tgit-clone -n \"$url\" \"$path\" --separate-git-dir \"$gitdir\"\n> +\t\tfi ||\n> +\t\tdie \"$(eval_gettext \"Clone of '\\$url' into submodule path '\\$path' failed\")\"\n> +\tfi\n>  }\n\n> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\n> index b2b26b7..57f5306 100755\n> --- a/t/t7400-submodule-basic.sh\n> +++ b/t/t7400-submodule-basic.sh\n> @@ -358,10 +358,10 @@ test_expect_success 'update --init' '\n>  \tgit submodule update init > update.out &&\n>  \tcat update.out &&\n>  \ttest_i18ngrep \"not initialized\" update.out &&\n> -\t! test -d init/.git &&\n> +\t! test -f init/.git &&\n>  \tgit submodule update --init init &&\n> -\ttest -d init/.git\n> +\ttest -n $(grep \"/^gitdir: /\" init/.git)\n\nI wonder if we want a new option to \"git rev-parse\" so that we can say\n\n\tgit rev-parse --is-well-formed-git-dir init/.git\n\nto perform these checks without exposing the implimentation detail.\n\n> diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh\n> index d600583..b0517f0 100755\n> --- a/t/t7403-submodule-sync.sh\n> +++ b/t/t7403-submodule-sync.sh\n> @@ -55,7 +55,7 @@ test_expect_success '\"git submodule sync\" should update submodule URLs' '\n>  \t git pull --no-recurse-submodules &&\n>  \t git submodule sync\n>  \t) &&\n> -\ttest -d \"$(git config -f super-clone/submodule/.git/config \\\n> +\ttest -d \"$(git config -f super-clone/.git/modules/submodule/config \\\n>  \t                        remote.origin.url)\" &&\n\nIs \"submodule\" initialized at this point?  If so, I would think it is\nvastly preferrable to say it like this:\n\n\ttest -d \"$(\n        \tcd super-clone/submodule &&\n                git config --local remote.origin.url\n\t)\"\n\nI won't comment on the rest, but I think you can follow the same line of\nthought to come up with a fix so that they do not have to know the\nimplementation detail of where the subproject metainfo directory is.\n"},{"id":"171822","messageId":"4E289CDA.20209@cisco.com","threadId":"27874","inReplyTo":"7vhb6f1ipp.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC PATCH] Move git-dir for submodules","fromName":"Phil Hord","fromEmail":"hordp@cisco.com","sentAt":"2011-07-21T21:40:42Z","receivedAt":"2011-07-21T21:40:42Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"On 07/21/2011 04:28 PM, Junio C Hamano wrote:\n> Fredrik Gustafsson<iveqy@iveqy.com>  writes:\n>\n>> diff --git a/git-submodule.sh b/git-submodule.sh\n>> index 87c9452..3ad3012 100755\n>> --- a/git-submodule.sh\n>> +++ b/git-submodule.sh\n>> @@ -122,14 +122,56 @@ module_clone()\n>>   \tpath=$1\n>>   \turl=$2\n>>   \treference=\"$3\"\n>> +\tgitdir=\n>> +\tgitdir_base=\n>> +\tbase_path=`echo $path | sed -e 's|[^/]*$||'`\n> We prefer $() over `` these days, no?  Without dq around $path, you would\n> not be able to preserve $IFS inside $PATH. You are stripping a run of non\n> slash at the trailing end --- is 'dirname \"$path\"' insufficient?\n>\n> I think you are using the path the submodule happens to be at in the\n> current checkout to decide where in the .git/modules in the superproject\n> to keep the submodule metadata directory. Shouldn't you be using\n> module_name to convert the $path to the name of the submodule (this is\n> important, as the same submodule that used to be at path P1 can be moved\n> to a different path P2 in the history).\n\nNow that you mention it, what happens if the submodule name changes in \nthe history?\nWhat happens if the submodule URL (and possibly the entire submodule \ncontents) changes in the history?\n\nIs there any unique thing simpler than \"<submodule-name>+<url>\" that can \nbe used to uniquely identify \"that\" submodule repo?\n\nSay I have linux as a submodule in my project.  But over time (or on \ndifferent branches) I have different ideas about what should go there \n(and where it should go):\n\nCommit      .gitmodules\n   E           linux.path=linux ; \nlinux.url=git://sources.blackfin.uclinux.org/git/linux-kernel\n   D           linux.path=linux ; \nlinux.url=https://github.com/mirrors/linux-2.6.git\n   C           linux.path=linux ; \nlinux.url=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\nB           linux.path=linus ; \nlinux.url=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\nA           linus.path=linus ; \nlinus.url=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nHow many repos are in .git/modules/?  I can imagine anything from 1-5 in \nthe implementation.  Logically there should be only 2, ideally (but not \npractically) named something like this:\n\n   .git/modules/linux@blackfin\n   .git/modules/linux@torvalds\n\nand where the last one also includes \"github/mirrors\" as a remote.\n\nBut a more practical implementation would end up with three as it \nwouldn't know it could combine the last two:\n\n   .git/modules/linux@blackfin\n   .git/modules/linux@torvalds\n   .git/modules/linux@github\n\nBut maybe a nearly practical implementation could actually wind up with \none repo and three remotes:\n\n   .git/modules/linux; remotes=blackfin, torvalds, github\n\nBut this is likely to confuse the poor user who did not expect all these \nremotes.  Also, a realistic practical implementation probably would wind \nup like this:\n\n   .git/modules/linux; remotes=blackfin, torvalds, github\n   .git/modules/linus; remotes=torvalds\n\nIn reality I suppose switching repositories like this is simply not \nsupported by the code or the patch.  But it's something to think about \nwhen choosing a name for the .git/modules path.\n\nPhil\n"},{"id":"171823","messageId":"4E289F42.4040708@cisco.com","threadId":"27874","inReplyTo":"4E289CDA.20209@cisco.com","subject":"Re: [RFC PATCH] Move git-dir for submodules","fromName":"Phil Hord","fromEmail":"hordp@cisco.com","sentAt":"2011-07-21T21:50:58Z","receivedAt":"2011-07-21T21:50:58Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"On 07/21/2011 05:40 PM, Phil Hord wrote:\n> On 07/21/2011 04:28 PM, Junio C Hamano wrote:\n>> Fredrik Gustafsson<iveqy@iveqy.com>  writes:\n>>\n>>> diff --git a/git-submodule.sh b/git-submodule.sh\n>>> index 87c9452..3ad3012 100755\n>>> --- a/git-submodule.sh\n>>> +++ b/git-submodule.sh\n>>> @@ -122,14 +122,56 @@ module_clone()\n>>>       path=$1\n>>>       url=$2\n>>>       reference=\"$3\"\n>>> +    gitdir=\n>>> +    gitdir_base=\n>>> +    base_path=`echo $path | sed -e 's|[^/]*$||'`\n>> We prefer $() over `` these days, no?  Without dq around $path, you \n>> would\n>> not be able to preserve $IFS inside $PATH. You are stripping a run of \n>> non\n>> slash at the trailing end --- is 'dirname \"$path\"' insufficient?\n>>\n>> I think you are using the path the submodule happens to be at in the\n>> current checkout to decide where in the .git/modules in the superproject\n>> to keep the submodule metadata directory. Shouldn't you be using\n>> module_name to convert the $path to the name of the submodule (this is\n>> important, as the same submodule that used to be at path P1 can be moved\n>> to a different path P2 in the history).\n>\n\n[ Sending this again to unwrap my table. Sorry for the noise. ]\n\nNow that you mention it, what happens if the submodule name changes in\nthe history?  What happens if the submodule URL (and possibly the entire\nsubmodule contents) changes in the history?\n\nIs there any unique thing simpler than \"<submodule-name>+<url>\" that can\nbe used to uniquely identify \"that\" submodule repo?\n\nSay I have linux as a submodule in my project.  But over time (or on\ndifferent branches) I have different ideas about what should go there.\nwhat it should be called and where it should go:\n\nCommit      .gitmodules\n  E           linux.path=linux ; linux.url=/blackfin/uclinux-kernel\n  D           linux.path=linux ; linux.url=/github/mirrors/linux-2.6.git\n  C           linux.path=linux ; linux.url=/torvalds/linux-2.6.git\n  B           linux.path=linus ; linux.url=/torvalds/linux-2.6.git\n  A           linus.path=linus ; linus.url=/torvalds/linux-2.6.git\n\n\nHow many repos are in .git/modules/?  I can imagine anything from 1-5 in\nthe implementation.  Logically there should be only 2, ideally (but not\npractically) named something like this:\n\n  .git/modules/linux@blackfin\n  .git/modules/linux@torvalds\n\nand where the last one also includes \"github/mirrors\" as a remote.\n\nBut a more practical implementation would end up with three as it\nwouldn't presume to combine the last two:\n\n  .git/modules/linux@blackfin\n  .git/modules/linux@torvalds\n  .git/modules/linux@github\n\nBut maybe a nearly practical implementation could actually wind up with\none repo and three remotes:\n\n  .git/modules/linux; remotes=blackfin, torvalds, github\n\nBut this is likely to confuse the poor user who did not expect all these\nremotes.  A realistic practical implementation probably would wind up\nmore like this:\n\n  .git/modules/linux; remotes=blackfin, torvalds, github\n  .git/modules/linus; remotes=torvalds\n\nIn reality I suppose switching repositories like this is simply not\nsupported by the code or the patch.  But it's something to think about\nwhen choosing a name for the .git/modules path.\n\nPhil\n\n> -- \n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n"},{"id":"171828","messageId":"7vr55jyzlb.fsf@alter.siamese.dyndns.org","threadId":"27874","inReplyTo":"4E289F42.4040708@cisco.com","subject":"Re: [RFC PATCH] Move git-dir for submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-07-21T23:37:52Z","receivedAt":"2011-07-21T23:37:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phil Hord <hordp@cisco.com> writes:\n\n> Now that you mention it, what happens if the submodule name changes in\n> the history?  What happens if the submodule URL (and possibly the entire\n> submodule contents) changes in the history?\n\nThe original idea (dating back before \"git submodule\" was written, but\nonly when \"gitlink\" was added to the index and the tree objects) was to\nidentify the submodule by name and refer to the same logical entity with\nthe same name, so that no matter where in the superproject's working tree\nhierarchy you change your mind to bind a particular submodule (say, \"the\nLinux kernel upstream source\") at (i.e. \"path\"), or from which mirror of\nthe kernel repository you recommend your downstream to clone it from\n(i.e. \"url\" in .gitmodules).\n\nSo \"What happens if the submodule name changes\" is a nonsense question.\n\nBut you remind me an ancient design discussion regarding the submodule URL\n(you should dig the list archive if you are interested in reviving the\ndiscussion of this issue), that hasn't been implemented.\n\nIt was envisioned that we sh/could record (in superproject's .git/config\nsomewhere) all the values of submodule.$name.url the user has ever seen\n(via checkouts and branch switching), the value of submodule.$name.url\nthat was recorded in .gitmodules, along with what URL the user has\nactually chosen to use given the set of these values. \n\nImagine that the original version of the superproject recommended A as the\nURL for the submodule S, and then later versions of the superproject\nrecommend B as its URL because the project it borrows its submodule has\nmigrated to a new home.\n\nA possible user experience under this scenario may go like this:\n\n    $ git clone superproject && cd superproject\n    $ git submodule init S\n\n        The user hasn't seen any submodule.S.url yet, as this is\n        immediately after cloning. .gitmodules records A and this\n        command would ask \"Do you want to clone from A [Y/n]?\" or use A\n        without asking.\n\n        It also records that when given A, the user chose A (or something\n        else, such as its known mirror A').\n\n    Time passes.  The superproject changes the url for submodule S.\n\n    $ git pull\n\n        Now .gitmodules has B in submodule.S.url, which is different from\n        anything the user has seen (recorded in .git/config of\n        superproject). Any \"git submodule\" subcommand that would try to\n        update submodule S from its upstream _should_ offer the user a\n        chance to notice this, and update the actual URL in S/.git/config\n\tto fetch from.  It may ask \"Do you want to update from B [Y/n]? \"\n        and some other choices (e.g. keep using A' may be an option).\n\n\tIt also records that after seeing A and B, and to update the\n\tversion of superproject that records B as the URL for S, the user\n\tchose to use what exact URL to update S (it may be A, B, or A', or\n\tit may be something entirely different).\n\n    $ git checkout -b side master~400 ;# or whatever old version\n\n\tAfter switching to an ancient version, .gitmodules has A. Perhaps\n\tthe module needs to be updated from A, or the module needs to be\n\tupdated from B (because A is defunct and no longer working, but B\n\trecords exactly the same history as A used to). But the record in\n\tthe superproject does not show what URL the user wants to use,\n\twhen A and B are the choices the user has seen, and A is recorded \n\tin .gitmodules, so we ask again, and record the choice.\n\n    After this, we know that given the knowledge of presence of A and B,\n    what URL the user wants to use when .gitmodules records A (or B) as\n    the URL for the submodule, so switching to _any_ version in the\n    history will not have to ask the user what URL should be used to\n    interact with the upstream of submodule S.\n\nNote that the above scenario can be loosened by assuming that B is always\na superset of A and newer recommendation is always preferred. Then the\nmapping from the situation to the actual URL can be simplified to \"Given\nthese URLs the user has seen, the user wants to use this URL\", not \"Given\nthese URLs the user has seen and this URL recorded in .gitmodules for the\nparticular version, the user wants to use this URL\" as the above scenario\noutlined.\n"},{"id":"171829","messageId":"7vmxg7yz4y.fsf@alter.siamese.dyndns.org","threadId":"27874","inReplyTo":"7vr55jyzlb.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC PATCH] Move git-dir for submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-07-21T23:47:41Z","receivedAt":"2011-07-21T23:47:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Phil Hord <hordp@cisco.com> writes:\n>\n>> Now that you mention it, what happens if the submodule name changes in\n>> the history?  What happens if the submodule URL (and possibly the entire\n>> submodule contents) changes in the history?\n>\n> The original idea (dating back before \"git submodule\" was written, but\n> only when \"gitlink\" was added to the index and the tree objects) was to\n> identify the submodule by name and refer to the same logical entity with\n> the same name, so that no matter where in the superproject's working tree\n> hierarchy you change your mind to bind a particular submodule (say, \"the\n> Linux kernel upstream source\") at (i.e. \"path\"), or from which mirror of\n> the kernel repository you recommend your downstream to clone it from\n> (i.e. \"url\" in .gitmodules).\n\nSorry for an incomplete sentence.  \"No matter....\" above should conclude\nwith \"you know you are talking about the same module that retains the\nidentity of its .git metadata directory.\"\n"},{"id":"171852","messageId":"20110722190223.GA27076@kolya","threadId":"27874","inReplyTo":"7vhb6f1ipp.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC PATCH] Move git-dir for submodules","fromName":"Fredrik Gustafsson","fromEmail":"iveqy@iveqy.com","sentAt":"2011-07-22T19:02:23Z","receivedAt":"2011-07-22T19:02:23Z","isPatch":true,"sender":{"key":"iveqy@iveqy.com","avatar":"https://avatars.githubusercontent.com/u/761743?v=4"},"body":"Thanks for the review. I'll send an updated series soon.\n\nOn Thu, Jul 21, 2011 at 01:28:50PM -0700, Junio C Hamano wrote:\n> Is it really necessary to have an ugly\n> loop to make things relative, though?\nThe path must be relative to allow the superproject to be moved\naround.\n\n> I wonder if we want a new option to \"git rev-parse\" so that we can say\n> \n> \tgit rev-parse --is-well-formed-git-dir init/.git\n> \n> to perform these checks without exposing the implimentation detail.\n\nHow about using\n(cd <repo>; git rev-parse --verify HEAD\" >/dev/null)\ninstead?\n\nMed vänliga hälsningar\nFredrik Gustafsson\n"},{"id":"171861","messageId":"7v62muys6l.fsf@alter.siamese.dyndns.org","threadId":"27874","inReplyTo":"20110722190223.GA27076@kolya","subject":"Re: [RFC PATCH] Move git-dir for submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-07-22T20:30:10Z","receivedAt":"2011-07-22T20:30:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Fredrik Gustafsson <iveqy@iveqy.com> writes:\n\n>> I wonder if we want a new option to \"git rev-parse\" so that we can say\n>> \n>> \tgit rev-parse --is-well-formed-git-dir init/.git\n>> \n>> to perform these checks without exposing the implimentation detail.\n>\n> How about using\n> (cd <repo>; git rev-parse --verify HEAD\" >/dev/null)\n> instead?\n\nCan the <repo> be without any commit, i.e. just after created?\n"}]}