diff options
-rwxr-xr-x | git-submodule.sh | 48 | ||||
-rwxr-xr-x | t/t7403-submodule-sync.sh | 8 |
2 files changed, 47 insertions, 9 deletions
diff --git a/git-submodule.sh b/git-submodule.sh index 64a70d621a..0a3e1465e3 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -30,7 +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) @@ -39,6 +54,17 @@ resolve_relative_url () url="$1" remoteurl=${remoteurl%/} sep=/ + up_path="$2" + + case "$remoteurl" in + *:*|/*) + is_relative= + ;; + *) + is_relative=t + ;; + esac + while test -n "$url" do case "$url" in @@ -64,7 +90,7 @@ resolve_relative_url () break;; esac done - echo "$remoteurl$sep${url%/}" + echo "${is_relative:+${up_path}}$remoteurl$sep${url%/}" } # @@ -964,14 +990,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 @@ -979,7 +1017,7 @@ cmd_sync() 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 diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 56b933da45..98bc74a4e9 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -99,7 +99,7 @@ test_expect_failure '"git submodule sync" handles origin URL of the form foo' ' ) ' -test_expect_failure '"git submodule sync" handles origin URL of the form foo/bar' ' +test_expect_success '"git submodule sync" handles origin URL of the form foo/bar' ' (cd relative-clone && git remote set-url origin foo/bar && git submodule sync && @@ -132,7 +132,7 @@ test_expect_failure '"git submodule sync" handles origin URL of the form ./foo/b ) ' -test_expect_failure '"git submodule sync" handles origin URL of the form ../foo' ' +test_expect_success '"git submodule sync" handles origin URL of the form ../foo' ' (cd relative-clone && git remote set-url origin ../foo && git submodule sync && @@ -143,7 +143,7 @@ test_expect_failure '"git submodule sync" handles origin URL of the form ../foo' ) ' -test_expect_failure '"git submodule sync" handles origin URL of the form ../foo/bar' ' +test_expect_success '"git submodule sync" handles origin URL of the form ../foo/bar' ' (cd relative-clone && git remote set-url origin ../foo/bar && git submodule sync && @@ -154,7 +154,7 @@ test_expect_failure '"git submodule sync" handles origin URL of the form ../foo/ ) ' -test_expect_failure '"git submodule sync" handles origin URL of the form ../foo/bar with deeply nested submodule' ' +test_expect_success '"git submodule sync" handles origin URL of the form ../foo/bar with deeply nested submodule' ' (cd relative-clone && git remote set-url origin ../foo/bar && mkdir -p a/b/c && |