git-submodule: clone during update, not during init
authorLars Hjemli <hjemli@gmail.com>
Wed, 6 Jun 2007 09:13:02 +0000 (11:13 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 6 Jun 2007 09:49:08 +0000 (02:49 -0700)
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>
Documentation/git-submodule.txt
git-submodule.sh
t/t7400-submodule-basic.sh

index cb0424f77b41deed3c93f1e34dc48497bf687fce..f8fb80f18b91fc7a7044da261e54ef25988ced99 100644 (file)
@@ -23,15 +23,15 @@ status::
        repository. This command is the default command for git-submodule.
 
 init::
-       Initialize the submodules, i.e. clone the git repositories specified
-       in the .gitmodules file and checkout the submodule commits specified
-       in the index of the containing repository. This will make the
-       submodules HEAD be detached.
+       Initialize the submodules, i.e. register in .git/config each submodule
+       path and url found in .gitmodules. The key used in git/config is
+       `submodule.$path.url`. This command does not alter existing information
+       in .git/config.
 
 update::
-       Update the initialized submodules, i.e. checkout the submodule commits
-       specified in the index of the containing repository. This will make
-       the submodules HEAD be detached.
+       Update the registered submodules, i.e. clone missing submodules and
+       checkout the commit specified in the index of the containing repository.
+       This will make the submodules HEAD be detached.
 
 
 OPTIONS
@@ -50,7 +50,7 @@ OPTIONS
 
 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.
 This file should be formatted in the same way as $GIR_DIR/config. The key
 to each submodule url is "module.$path.url".
index 486d3b212484b2ac8d33f1fb8a1c65c6fded7dc5..8bdd99a2f37a8c76fd4b08e6736d7a67da47be1e 100755 (executable)
@@ -53,7 +53,7 @@ module_clone()
 }
 
 #
-# Run clone + checkout on missing submodules
+# Register submodules in .git/config
 #
 # $@ = requested paths (default to all)
 #
@@ -62,37 +62,23 @@ modules_init()
        git ls-files --stage -- "$@" | grep -e '^160000 ' |
        while read mode sha1 stage path
        do
-               # Skip submodule paths that already contain a .git directory.
-               # This will also trigger if $path is a symlink to a git
-               # repository
-               test -d "$path"/.git && continue
+               # Skip already registered paths
+               url=$(git-config submodule."$path".url)
+               test -z "$url" || continue
 
                url=$(GIT_CONFIG=.gitmodules git-config module."$path".url)
                test -z "$url" &&
                die "No url found for submodule '$path' in .gitmodules"
 
-               # MAYBE FIXME: this would be the place to check GIT_CONFIG
-               # for a preferred url for this submodule, possibly like this:
-               #
-               # 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.
+               git-config submodule."$path".url "$url" ||
+               die "Failed to register url for submodule '$path'"
 
-               module_clone "$path" "$url" || exit
-
-               (unset GIT_DIR && cd "$path" && git-checkout -q "$sha1") ||
-               die "Checkout of submodule '$path' failed"
-
-               say "Submodule '$path' initialized"
+               say "Submodule '$path' registered with url '$url'"
        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)
 #
@@ -101,14 +87,21 @@ modules_update()
        git ls-files --stage -- "$@" | grep -e '^160000 ' |
        while read mode sha1 stage path
        do
-               if ! test -d "$path"/.git
+               url=$(git-config submodule."$path".url)
+               if test -z "$url"
                then
                        # Only mention uninitialized submodules when its
                        # path have been specified
                        test "$#" != "0" &&
                        say "Submodule '$path' not initialized"
-                       continue;
+                       continue
                fi
+
+               if ! test -d "$path"/.git
+               then
+                       module_clone "$path" "$url" || exit
+               fi
+
                subsha1=$(unset GIT_DIR && cd "$path" &&
                        git-rev-parse --verify HEAD) ||
                die "Unable to find current revision of submodule '$path'"
index 627472972918352a026408ddaa4a50d3e21522b5..3940433b8f59196eff06dd24be24c9f54e7254ac 100755 (executable)
@@ -40,7 +40,7 @@ test_expect_success 'Prepare submodule testing' '
        git-add a lib z &&
        git-commit -m "super commit 1" &&
        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' '
@@ -52,41 +52,55 @@ test_expect_success 'status should initially be "missing"' '
        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' '
+       git-submodule init &&
+       url=$(git-config submodule.lib.url) &&
+       if test "$url" != "git://example.com/lib.git"
+       then
+               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 init
+       if git-submodule update
        then
-               echo "[OOPS] init should have failed"
+               echo "[OOPS] update should have failed"
                false
        elif test -f lib && test "$(cat lib)" != "hello"
        then
-               echo "[OOPS] init failed but lib file was molested"
+               echo "[OOPS] update failed but lib file was molested"
                false
        else
                rm lib
        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 &&
        echo "hello" >lib/a &&
-       if git-submodule init
+       if git-submodule update
        then
-               echo "[OOPS] init should have failed"
+               echo "[OOPS] update should have failed"
                false
        elif test "$(cat lib/a)" != "hello"
        then
-               echo "[OOPS] init failed but lib/a was molested"
+               echo "[OOPS] update failed but lib/a was molested"
                false
        else
                rm lib/a
        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 &&
        mkdir lib &&
-       git-submodule init &&
+       git-submodule update &&
        head=$(cd lib && git-rev-parse HEAD) &&
        if test -z "$head"
        then
@@ -99,7 +113,7 @@ test_expect_success 'init should work when path is an empty dir' '
        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"
 '