git-submodule: clone during update, not during init

This teaches 'git-submodule init' to register submodule paths and urls in
.git/config instead of actually cloning them. The cloning is now handled
as part of 'git-submodule update'.

With this change it is possible to specify preferred/alternate urls for
the submodules in .git/config before the submodules are cloned.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Lars Hjemli 2007-06-06 11:13:02 +02:00 committed by Junio C Hamano
parent 33aa6fff5d
commit 211b7f19c7
3 changed files with 52 additions and 45 deletions

View File

@ -23,15 +23,15 @@ status::
repository. This command is the default command for git-submodule. repository. This command is the default command for git-submodule.
init:: init::
Initialize the submodules, i.e. clone the git repositories specified Initialize the submodules, i.e. register in .git/config each submodule
in the .gitmodules file and checkout the submodule commits specified path and url found in .gitmodules. The key used in git/config is
in the index of the containing repository. This will make the `submodule.$path.url`. This command does not alter existing information
submodules HEAD be detached. in .git/config.
update:: update::
Update the initialized submodules, i.e. checkout the submodule commits Update the registered submodules, i.e. clone missing submodules and
specified in the index of the containing repository. This will make checkout the commit specified in the index of the containing repository.
the submodules HEAD be detached. This will make the submodules HEAD be detached.
OPTIONS OPTIONS
@ -50,7 +50,7 @@ OPTIONS
FILES FILES
----- -----
When cloning submodules, a .gitmodules file in the top-level directory When initializing submodules, a .gitmodules file in the top-level directory
of the containing repository is used to find the url of each submodule. of the containing repository is used to find the url of each submodule.
This file should be formatted in the same way as $GIR_DIR/config. The key This file should be formatted in the same way as $GIR_DIR/config. The key
to each submodule url is "module.$path.url". to each submodule url is "module.$path.url".

View File

@ -53,7 +53,7 @@ module_clone()
} }
# #
# Run clone + checkout on missing submodules # Register submodules in .git/config
# #
# $@ = requested paths (default to all) # $@ = requested paths (default to all)
# #
@ -62,37 +62,23 @@ modules_init()
git ls-files --stage -- "$@" | grep -e '^160000 ' | git ls-files --stage -- "$@" | grep -e '^160000 ' |
while read mode sha1 stage path while read mode sha1 stage path
do do
# Skip submodule paths that already contain a .git directory. # Skip already registered paths
# This will also trigger if $path is a symlink to a git url=$(git-config submodule."$path".url)
# repository test -z "$url" || continue
test -d "$path"/.git && continue
url=$(GIT_CONFIG=.gitmodules git-config module."$path".url) url=$(GIT_CONFIG=.gitmodules git-config module."$path".url)
test -z "$url" && test -z "$url" &&
die "No url found for submodule '$path' in .gitmodules" die "No url found for submodule '$path' in .gitmodules"
# MAYBE FIXME: this would be the place to check GIT_CONFIG git-config submodule."$path".url "$url" ||
# for a preferred url for this submodule, possibly like this: die "Failed to register url for submodule '$path'"
#
# modname=$(GIT_CONFIG=.gitmodules git-config module."$path".name)
# alturl=$(git-config module."$modname".url)
#
# This would let the versioned .gitmodules file use the submodule
# path as key, while the unversioned GIT_CONFIG would use the
# logical modulename (if present) as key. But this would need
# another fallback mechanism if the module wasn't named.
module_clone "$path" "$url" || exit say "Submodule '$path' registered with url '$url'"
(unset GIT_DIR && cd "$path" && git-checkout -q "$sha1") ||
die "Checkout of submodule '$path' failed"
say "Submodule '$path' initialized"
done done
} }
# #
# Checkout correct revision of each initialized submodule # Update each submodule path to correct revision, using clone and checkout as needed
# #
# $@ = requested paths (default to all) # $@ = requested paths (default to all)
# #
@ -101,14 +87,21 @@ modules_update()
git ls-files --stage -- "$@" | grep -e '^160000 ' | git ls-files --stage -- "$@" | grep -e '^160000 ' |
while read mode sha1 stage path while read mode sha1 stage path
do do
if ! test -d "$path"/.git url=$(git-config submodule."$path".url)
if test -z "$url"
then then
# Only mention uninitialized submodules when its # Only mention uninitialized submodules when its
# path have been specified # path have been specified
test "$#" != "0" && test "$#" != "0" &&
say "Submodule '$path' not initialized" say "Submodule '$path' not initialized"
continue; continue
fi fi
if ! test -d "$path"/.git
then
module_clone "$path" "$url" || exit
fi
subsha1=$(unset GIT_DIR && cd "$path" && subsha1=$(unset GIT_DIR && cd "$path" &&
git-rev-parse --verify HEAD) || git-rev-parse --verify HEAD) ||
die "Unable to find current revision of submodule '$path'" die "Unable to find current revision of submodule '$path'"

View File

@ -40,7 +40,7 @@ test_expect_success 'Prepare submodule testing' '
git-add a lib z && git-add a lib z &&
git-commit -m "super commit 1" && git-commit -m "super commit 1" &&
mv lib .subrepo && mv lib .subrepo &&
GIT_CONFIG=.gitmodules git-config module.lib.url ./.subrepo GIT_CONFIG=.gitmodules git-config module.lib.url git://example.com/lib.git
' '
test_expect_success 'status should only print one line' ' test_expect_success 'status should only print one line' '
@ -52,41 +52,55 @@ test_expect_success 'status should initially be "missing"' '
git-submodule status | grep "^-$rev1" git-submodule status | grep "^-$rev1"
' '
test_expect_success 'init should fail when path is used by a file' ' test_expect_success 'init should register submodule url in .git/config' '
echo "hello" >lib && git-submodule init &&
if git-submodule init url=$(git-config submodule.lib.url) &&
if test "$url" != "git://example.com/lib.git"
then then
echo "[OOPS] init should have failed" echo "[OOPS] init succeeded but submodule url is wrong"
false
elif ! git-config submodule.lib.url ./.subrepo
then
echo "[OOPS] init succeeded but update of url failed"
false
fi
'
test_expect_success 'update should fail when path is used by a file' '
echo "hello" >lib &&
if git-submodule update
then
echo "[OOPS] update should have failed"
false false
elif test -f lib && test "$(cat lib)" != "hello" elif test -f lib && test "$(cat lib)" != "hello"
then then
echo "[OOPS] init failed but lib file was molested" echo "[OOPS] update failed but lib file was molested"
false false
else else
rm lib rm lib
fi fi
' '
test_expect_success 'init should fail when path is used by a nonempty directory' ' test_expect_success 'update should fail when path is used by a nonempty directory' '
mkdir lib && mkdir lib &&
echo "hello" >lib/a && echo "hello" >lib/a &&
if git-submodule init if git-submodule update
then then
echo "[OOPS] init should have failed" echo "[OOPS] update should have failed"
false false
elif test "$(cat lib/a)" != "hello" elif test "$(cat lib/a)" != "hello"
then then
echo "[OOPS] init failed but lib/a was molested" echo "[OOPS] update failed but lib/a was molested"
false false
else else
rm lib/a rm lib/a
fi fi
' '
test_expect_success 'init should work when path is an empty dir' ' test_expect_success 'update should work when path is an empty dir' '
rm -rf lib && rm -rf lib &&
mkdir lib && mkdir lib &&
git-submodule init && git-submodule update &&
head=$(cd lib && git-rev-parse HEAD) && head=$(cd lib && git-rev-parse HEAD) &&
if test -z "$head" if test -z "$head"
then then
@ -99,7 +113,7 @@ test_expect_success 'init should work when path is an empty dir' '
fi fi
' '
test_expect_success 'status should be "up-to-date" after init' ' test_expect_success 'status should be "up-to-date" after update' '
git-submodule status | grep "^ $rev1" git-submodule status | grep "^ $rev1"
' '