git-submodule - allow a relative path as the subproject url
authorMark Levedahl <mdl123@verizon.net>
Mon, 24 Sep 2007 02:19:42 +0000 (22:19 -0400)
committerJunio C Hamano <gitster@pobox.com>
Tue, 25 Sep 2007 07:31:12 +0000 (00:31 -0700)
This allows a subproject's location to be specified and stored as relative
to the parent project's location (e.g., ./foo, or ../foo). This url is
stored in .gitmodules as given. It is resolved into an absolute url by
appending it to the parent project's url when the information is written
to .git/config (i.e., during submodule add for the originator, and
submodule init for a downstream recipient). This allows cloning of the
project to work "as expected" if the project is hosted on a different
server than when the subprojects were added.

Signed-off-by: Mark Levedahl <mdl123@verizon.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-submodule.txt
git-submodule.sh

index 2c48936fcd72c5276ae2fed217bd9b9564342f03..335e973a6a1d5350c1558eb68985ffe812c09212 100644 (file)
@@ -21,6 +21,9 @@ add::
        repository is cloned at the specified path, added to the
        changeset and registered in .gitmodules.   If no path is
        specified, the path is deduced from the repository specification.
+       If the repository url begins with ./ or ../, it is stored as
+       given but resolved as a relative path from the main project's
+       url when cloning.
 
 status::
        Show the status of the submodules. This will print the SHA-1 of the
index 673aa27a452b11af62d89986bf21c8a4f10e0c41..727b1d3206da6964affe80d92699cd39c1878e34 100755 (executable)
@@ -39,6 +39,32 @@ get_repo_base() {
        ) 2>/dev/null
 }
 
+# Resolve relative url by appending to parent's url
+resolve_relative_url ()
+{
+       branch="$(git symbolic-ref HEAD 2>/dev/null)"
+       remote="$(git config branch.${branch#refs/heads/}.remote)"
+       remote="${remote:-origin}"
+       remoteurl="$(git config remote.$remote.url)" ||
+               die "remote ($remote) does not have a url in .git/config"
+       url="$1"
+       while test -n "$url"
+       do
+               case "$url" in
+               ../*)
+                       url="${url#../}"
+                       remoteurl="${remoteurl%/*}"
+                       ;;
+               ./*)
+                       url="${url#./}"
+                       ;;
+               *)
+                       break;;
+               esac
+       done
+       echo "$remoteurl/$url"
+}
+
 #
 # Map submodule path to submodule name
 #
@@ -103,11 +129,19 @@ module_add()
                usage
        fi
 
-       # Turn the source into an absolute path if
-       # it is local
-       if base=$(get_repo_base "$repo"); then
-               repo="$base"
-       fi
+       case "$repo" in
+       ./*|../*)
+               # dereference source url relative to parent's url
+               realrepo="$(resolve_relative_url $repo)" ;;
+       *)
+               # Turn the source into an absolute path if
+               # it is local
+               if base=$(get_repo_base "$repo"); then
+                       repo="$base"
+                       realrepo=$repo
+               fi
+               ;;
+       esac
 
        # Guess path from repo if not specified or strip trailing slashes
        if test -z "$path"; then
@@ -122,7 +156,7 @@ module_add()
        git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
        die "'$path' already exists in the index"
 
-       module_clone "$path" "$repo" || exit
+       module_clone "$path" "$realrepo" || exit
        (unset GIT_DIR && cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
        die "Unable to checkout submodule '$path'"
        git add "$path" ||
@@ -153,6 +187,13 @@ modules_init()
                test -z "$url" &&
                die "No url found for submodule path '$path' in .gitmodules"
 
+               # Possibly a url relative to parent
+               case "$url" in
+               ./*|../*)
+                       url="$(resolve_relative_url "$url")"
+                       ;;
+               esac
+
                git config submodule."$name".url "$url" ||
                die "Failed to register url for submodule path '$path'"