Skip to content

Commit

Permalink
Move git-dir for submodules
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Fredrik Gustafsson authored and Junio C Hamano committed Aug 23, 2011
1 parent abc0682 commit 501770e
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 7 deletions.
45 changes: 40 additions & 5 deletions git-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,49 @@ module_clone()
path=$1
url=$2
reference="$3"
gitdir=
gitdir_base=
name=$(module_name "$path")
base_path=$(dirname "$path")

if test -n "$reference"
gitdir=$(git rev-parse --git-dir)
gitdir_base="$gitdir/modules/$base_path"
gitdir="$gitdir/modules/$path"

case $gitdir in
/*)
a="$(cd_to_toplevel && pwd)/"
b=$gitdir
while [ "$b" ] && [ "${a%%/*}" = "${b%%/*}" ]
do
a=${a#*/} b=${b#*/};
done

rel="$a$name"
rel=`echo $rel | sed -e 's|[^/]*|..|g'`
rel_gitdir="$rel/$b"
;;
*)
rel=`echo $name | sed -e 's|[^/]*|..|g'`
rel_gitdir="$rel/$gitdir"
;;
esac

if test -d "$gitdir"
then
git-clone "$reference" -n "$url" "$path"
mkdir -p "$path"
echo "gitdir: $rel_gitdir" >"$path/.git"
rm -f "$gitdir/index"
else
git-clone -n "$url" "$path"
fi ||
die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
mkdir -p "$gitdir_base"
if test -n "$reference"
then
git-clone "$reference" -n "$url" "$path" --separate-git-dir "$gitdir"
else
git-clone -n "$url" "$path" --separate-git-dir "$gitdir"
fi ||
die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
fi
}

#
Expand Down
107 changes: 107 additions & 0 deletions t/t7406-submodule-update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ test_expect_success 'submodule update exit immediately in case of merge conflict
test_cmp expect actual
)
'

test_expect_success 'submodule update exit immediately after recursive rebase error' '
(cd super &&
git checkout master &&
Expand Down Expand Up @@ -442,4 +443,110 @@ test_expect_success 'submodule update exit immediately after recursive rebase er
test_cmp expect actual
)
'

test_expect_success 'add different submodules to the same path' '
(cd super &&
git submodule add ../submodule s1 &&
test_must_fail git submodule add ../merging s1
)
'

test_expect_success 'submodule add places git-dir in superprojects git-dir' '
(cd super &&
mkdir deeper &&
git submodule add ../submodule deeper/submodule &&
(cd deeper/submodule &&
git log > ../../expected
) &&
(cd .git/modules/deeper/submodule &&
git log > ../../../../actual
) &&
test_cmp actual expected
)
'

test_expect_success 'submodule update places git-dir in superprojects git-dir' '
(cd super &&
git commit -m "added submodule"
) &&
git clone super super2 &&
(cd super2 &&
git submodule init deeper/submodule &&
git submodule update &&
(cd deeper/submodule &&
git log > ../../expected
) &&
(cd .git/modules/deeper/submodule &&
git log > ../../../../actual
) &&
test_cmp actual expected
)
'

test_expect_success 'submodule add places git-dir in superprojects git-dir recursive' '
(cd super2 &&
(cd deeper/submodule &&
git submodule add ../submodule subsubmodule &&
(cd subsubmodule &&
git log > ../../../expected
) &&
git commit -m "added subsubmodule" &&
git push
) &&
(cd .git/modules/deeper/submodule/modules/subsubmodule &&
git log > ../../../../../actual
) &&
git add deeper/submodule &&
git commit -m "update submodule" &&
git push &&
test_cmp actual expected
)
'

test_expect_success 'submodule update places git-dir in superprojects git-dir recursive' '
mkdir super_update_r &&
(cd super_update_r &&
git init --bare
) &&
mkdir subsuper_update_r &&
(cd subsuper_update_r &&
git init --bare
) &&
mkdir subsubsuper_update_r &&
(cd subsubsuper_update_r &&
git init --bare
) &&
git clone subsubsuper_update_r subsubsuper_update_r2 &&
(cd subsubsuper_update_r2 &&
test_commit "update_subsubsuper" file &&
git push origin master
) &&
git clone subsuper_update_r subsuper_update_r2 &&
(cd subsuper_update_r2 &&
test_commit "update_subsuper" file &&
git submodule add ../subsubsuper_update_r subsubmodule &&
git commit -am "subsubmodule" &&
git push origin master
) &&
git clone super_update_r super_update_r2 &&
(cd super_update_r2 &&
test_commit "update_super" file &&
git submodule add ../subsuper_update_r submodule &&
git commit -am "submodule" &&
git push origin master
) &&
rm -rf super_update_r2 &&
git clone super_update_r super_update_r2 &&
(cd super_update_r2 &&
git submodule update --init --recursive &&
(cd submodule/subsubmodule &&
git log > ../../expected
) &&
(cd .git/modules/submodule/modules/subsubmodule
git log > ../../../../../actual
)
test_cmp actual expected
)
'

test_done
4 changes: 2 additions & 2 deletions t/t7408-submodule-reference.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ git commit -m B-super-added'
cd "$base_dir"

test_expect_success 'after add: existence of info/alternates' \
'test `wc -l <super/sub/.git/objects/info/alternates` = 1'
'test `wc -l <super/.git/modules/sub/objects/info/alternates` = 1'

cd "$base_dir"

Expand All @@ -66,7 +66,7 @@ test_expect_success 'update with reference' \
cd "$base_dir"

test_expect_success 'after update: existence of info/alternates' \
'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1'
'test `wc -l <super-clone/.git/modules/sub/objects/info/alternates` = 1'

cd "$base_dir"

Expand Down

0 comments on commit 501770e

Please sign in to comment.