Merge branch 'js/submodule-relative'
authorJunio C Hamano <gitster@pobox.com>
Thu, 28 Jun 2012 22:20:55 +0000 (15:20 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 28 Jun 2012 22:20:55 +0000 (15:20 -0700)
Teach "git submodule" deal with nested submodule structure where a
module is contained within a module whose origin is specified as a
relative URL to its superproject's origin.

1  2 
git-submodule.sh
diff --combined git-submodule.sh
index fbf2fafaaf49ec65090ec4eadb33d1ccedc60436,b0b6ccbe723e7c86a478b19166871245bf10ed5d..5629d875e6a0c0a390d046f28bf2d768116bf974
@@@ -1,6 -1,6 +1,6 @@@
  #!/bin/sh
  #
 -# git-submodules.sh: add, init, update or list git submodules
 +# git-submodule.sh: add, init, update or list git submodules
  #
  # Copyright (c) 2007 Lars Hjemli
  
@@@ -30,7 -30,22 +30,22 @@@ nofetch
  update=
  prefix=
  
- # Resolve relative url by appending to parent's url
+ # The function takes at most 2 arguments. The first argument is the
+ # URL that navigates to the submodule origin repo. When relative, this URL
+ # is relative to the superproject origin URL repo. The second up_path
+ # argument, if specified, is the relative path that navigates
+ # from the submodule working tree to the superproject working tree.
+ #
+ # The output of the function is the origin URL of the submodule.
+ #
+ # The output will either be an absolute URL or filesystem path (if the
+ # superproject origin URL is an absolute URL or filesystem path,
+ # respectively) or a relative file system path (if the superproject
+ # origin URL is a relative file system path).
+ #
+ # When the output is a relative file system path, the path is either
+ # relative to the submodule working tree, if up_path is specified, or to
+ # the superproject working tree otherwise.
  resolve_relative_url ()
  {
        remote=$(get_default_remote)
        url="$1"
        remoteurl=${remoteurl%/}
        sep=/
+       up_path="$2"
+       case "$remoteurl" in
+       *:*|/*)
+               is_relative=
+               ;;
+       ./*|../*)
+               is_relative=t
+               ;;
+       *)
+               is_relative=t
+               remoteurl="./$remoteurl"
+               ;;
+       esac
        while test -n "$url"
        do
                case "$url" in
                                sep=:
                                ;;
                        *)
-                               die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
+                               if test -z "$is_relative" || test "." = "$remoteurl"
+                               then
+                                       die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
+                               else
+                                       remoteurl=.
+                               fi
                                ;;
                        esac
                        ;;
@@@ -64,7 -99,8 +99,8 @@@
                        break;;
                esac
        done
-       echo "$remoteurl$sep${url%/}"
+       remoteurl="$remoteurl$sep${url%/}"
+       echo "${is_relative:+${up_path}}${remoteurl#./}"
  }
  
  #
@@@ -396,9 -432,8 +432,9 @@@ cmd_init(
        module_list "$@" |
        while read mode sha1 stage sm_path
        do
 -              # Skip already registered paths
                name=$(module_name "$sm_path") || exit
 +
 +              # Copy url setting when it is not set yet
                if test -z "$(git config "submodule.$name.url")"
                then
                        url=$(git config -f .gitmodules submodule."$name".url)
                        esac
                        git config submodule."$name".url "$url" ||
                        die "$(eval_gettext "Failed to register url for submodule path '\$sm_path'")"
 +
 +                      say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
                fi
  
                # Copy "update" setting when it is not set yet
                test -n "$(git config submodule."$name".update)" ||
                git config submodule."$name".update "$upd" ||
                die "$(eval_gettext "Failed to register update mode for submodule path '\$sm_path'")"
 -
 -              say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
        done
  }
  
@@@ -965,14 -1000,26 +1001,26 @@@ cmd_sync(
                # Possibly a url relative to parent
                case "$url" in
                ./*|../*)
-                       url=$(resolve_relative_url "$url") || exit
+                       # rewrite foo/bar as ../.. to find path from
+                       # submodule work tree to superproject work tree
+                       up_path="$(echo "$sm_path" | sed "s/[^/][^/]*/../g")" &&
+                       # guarantee a trailing /
+                       up_path=${up_path%/}/ &&
+                       # path from submodule work tree to submodule origin repo
+                       sub_origin_url=$(resolve_relative_url "$url" "$up_path") &&
+                       # path from superproject work tree to submodule origin repo
+                       super_config_url=$(resolve_relative_url "$url") || exit
+                       ;;
+               *)
+                       sub_origin_url="$url"
+                       super_config_url="$url"
                        ;;
                esac
  
                if git config "submodule.$name.url" >/dev/null 2>/dev/null
                then
                        say "$(eval_gettext "Synchronizing submodule url for '\$name'")"
-                       git config submodule."$name".url "$url"
+                       git config submodule."$name".url "$super_config_url"
  
                        if test -e "$sm_path"/.git
                        then
                                clear_local_git_env
                                cd "$sm_path"
                                remote=$(get_default_remote)
-                               git config remote."$remote".url "$url"
+                               git config remote."$remote".url "$sub_origin_url"
                        )
                        fi
                fi