Move git-dir for submodules

Move git-dir for submodules into $GIT_DIR/modules/[name_of_submodule] of the superproject. This is a step towards being able to delete submodule directories without loosing the information from their .git directory as that is now stored outside the submodules work tree. This is done relying on the already existent .git-file functionality. When adding or updating a submodule whose git directory is found under $GIT_DIR/modules/[name_of_submodule], don't clone it again but simply point the .git-file to it and remove the now stale index file from it. The index will be recreated by the following checkout. This patch will not affect already cloned submodules at all. Tests that rely on .git being a directory have been fixed. Signed-off-by: Fredrik Gustafsson <iveqy@iveqy.com> Mentored-by: Jens Lehmann <Jens.Lehmann@web.de> Mentored-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Fredrik Gustafsson committed Aug 15, 2011 at 23:17 UTC 501770e1bb5d132ae4f79aa96715f07f6b84e1f6
3 files changed +149 -7
git-submodule.sh
+40 -5
@@ -122,14 +122,49 @@ module_clone()
122 path=$1
123 url=$2
124 reference="$3"
125 + gitdir=
126 + gitdir_base=
127 + name=$(module_name "$path")
128 + base_path=$(dirname "$path")
129
126 - if test -n "$reference"
130 + gitdir=$(git rev-parse --git-dir)
131 + gitdir_base="$gitdir/modules/$base_path"
132 + gitdir="$gitdir/modules/$path"
133 +
134 + case $gitdir in
135 + /*)
136 + a="$(cd_to_toplevel && pwd)/"
137 + b=$gitdir
138 + while [ "$b" ] && [ "${a%%/*}" = "${b%%/*}" ]
139 + do
140 + a=${a#*/} b=${b#*/};
141 + done
142 +
143 + rel="$a$name"
144 + rel=`echo $rel | sed -e 's|[^/]*|..|g'`
145 + rel_gitdir="$rel/$b"
146 + ;;
147 + *)
148 + rel=`echo $name | sed -e 's|[^/]*|..|g'`
149 + rel_gitdir="$rel/$gitdir"
150 + ;;
151 + esac
152 +
153 + if test -d "$gitdir"
154 then
128 - git-clone "$reference" -n "$url" "$path"
155 + mkdir -p "$path"
156 + echo "gitdir: $rel_gitdir" >"$path/.git"
157 + rm -f "$gitdir/index"
158 else
130 - git-clone -n "$url" "$path"
131 - fi ||
132 - die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
159 + mkdir -p "$gitdir_base"
160 + if test -n "$reference"
161 + then
162 + git-clone "$reference" -n "$url" "$path" --separate-git-dir "$gitdir"
163 + else
164 + git-clone -n "$url" "$path" --separate-git-dir "$gitdir"
165 + fi ||
166 + die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
167 + fi
168 }
169
170 #
t/t7406-submodule-update.sh
+107
@@ -408,6 +408,7 @@ test_expect_success 'submodule update exit immediately in case of merge conflict
408 test_cmp expect actual
409 )
410 '
411 +
412 test_expect_success 'submodule update exit immediately after recursive rebase error' '
413 (cd super &&
414 git checkout master &&
@@ -442,4 +443,110 @@ test_expect_success 'submodule update exit immediately after recursive rebase er
443 test_cmp expect actual
444 )
445 '
446 +
447 +test_expect_success 'add different submodules to the same path' '
448 + (cd super &&
449 + git submodule add ../submodule s1 &&
450 + test_must_fail git submodule add ../merging s1
451 + )
452 +'
453 +
454 +test_expect_success 'submodule add places git-dir in superprojects git-dir' '
455 + (cd super &&
456 + mkdir deeper &&
457 + git submodule add ../submodule deeper/submodule &&
458 + (cd deeper/submodule &&
459 + git log > ../../expected
460 + ) &&
461 + (cd .git/modules/deeper/submodule &&
462 + git log > ../../../../actual
463 + ) &&
464 + test_cmp actual expected
465 + )
466 +'
467 +
468 +test_expect_success 'submodule update places git-dir in superprojects git-dir' '
469 + (cd super &&
470 + git commit -m "added submodule"
471 + ) &&
472 + git clone super super2 &&
473 + (cd super2 &&
474 + git submodule init deeper/submodule &&
475 + git submodule update &&
476 + (cd deeper/submodule &&
477 + git log > ../../expected
478 + ) &&
479 + (cd .git/modules/deeper/submodule &&
480 + git log > ../../../../actual
481 + ) &&
482 + test_cmp actual expected
483 + )
484 +'
485 +
486 +test_expect_success 'submodule add places git-dir in superprojects git-dir recursive' '
487 + (cd super2 &&
488 + (cd deeper/submodule &&
489 + git submodule add ../submodule subsubmodule &&
490 + (cd subsubmodule &&
491 + git log > ../../../expected
492 + ) &&
493 + git commit -m "added subsubmodule" &&
494 + git push
495 + ) &&
496 + (cd .git/modules/deeper/submodule/modules/subsubmodule &&
497 + git log > ../../../../../actual
498 + ) &&
499 + git add deeper/submodule &&
500 + git commit -m "update submodule" &&
501 + git push &&
502 + test_cmp actual expected
503 + )
504 +'
505 +
506 +test_expect_success 'submodule update places git-dir in superprojects git-dir recursive' '
507 + mkdir super_update_r &&
508 + (cd super_update_r &&
509 + git init --bare
510 + ) &&
511 + mkdir subsuper_update_r &&
512 + (cd subsuper_update_r &&
513 + git init --bare
514 + ) &&
515 + mkdir subsubsuper_update_r &&
516 + (cd subsubsuper_update_r &&
517 + git init --bare
518 + ) &&
519 + git clone subsubsuper_update_r subsubsuper_update_r2 &&
520 + (cd subsubsuper_update_r2 &&
521 + test_commit "update_subsubsuper" file &&
522 + git push origin master
523 + ) &&
524 + git clone subsuper_update_r subsuper_update_r2 &&
525 + (cd subsuper_update_r2 &&
526 + test_commit "update_subsuper" file &&
527 + git submodule add ../subsubsuper_update_r subsubmodule &&
528 + git commit -am "subsubmodule" &&
529 + git push origin master
530 + ) &&
531 + git clone super_update_r super_update_r2 &&
532 + (cd super_update_r2 &&
533 + test_commit "update_super" file &&
534 + git submodule add ../subsuper_update_r submodule &&
535 + git commit -am "submodule" &&
536 + git push origin master
537 + ) &&
538 + rm -rf super_update_r2 &&
539 + git clone super_update_r super_update_r2 &&
540 + (cd super_update_r2 &&
541 + git submodule update --init --recursive &&
542 + (cd submodule/subsubmodule &&
543 + git log > ../../expected
544 + ) &&
545 + (cd .git/modules/submodule/modules/subsubmodule
546 + git log > ../../../../../actual
547 + )
548 + test_cmp actual expected
549 + )
550 +'
551 +
552 test_done
t/t7408-submodule-reference.sh
+2 -2
@@ -43,7 +43,7 @@ git commit -m B-super-added'
43 cd "$base_dir"
44
45 test_expect_success 'after add: existence of info/alternates' \
46 -'test `wc -l <super/sub/.git/objects/info/alternates` = 1'
46 +'test `wc -l <super/.git/modules/sub/objects/info/alternates` = 1'
47
48 cd "$base_dir"
49
@@ -66,7 +66,7 @@ test_expect_success 'update with reference' \
66 cd "$base_dir"
67
68 test_expect_success 'after update: existence of info/alternates' \
69 -'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1'
69 +'test `wc -l <super-clone/.git/modules/sub/objects/info/alternates` = 1'
70
71 cd "$base_dir"
72