summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xgit-submodule.sh48
-rwxr-xr-xt/t7403-submodule-sync.sh8
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 &&