From 967b2c66738fe6b168ead0c3106ac47fb9ae22c7 Mon Sep 17 00:00:00 2001 From: Jon Seymour Date: Wed, 6 Jun 2012 21:57:29 +1000 Subject: submodule: fix sync handling of some relative superproject origin URLs When the origin URL of the superproject is itself relative, git submodule sync configures the remote.origin.url configuration property of the submodule with a path that is relative to the work tree of the superproject rather than the work tree of the submodule. To fix this an 'up_path' that navigates from the work tree of the submodule to the work tree of the superproject needs to be prepended to the URL otherwise calculated. Correct handling of superproject origin URLs like foo, ./foo and ./foo/bar is left to a subsequent patch since an additional change is required to handle these cases. The documentation of resolve_relative_url() is expanded to give a more thorough description of the function's objective. Signed-off-by: Jon Seymour Signed-off-by: Junio C Hamano --- git-submodule.sh | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'git-submodule.sh') 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 -- cgit v1.3 From 758615e2517db8b9fda9218afded06a3e1b42e20 Mon Sep 17 00:00:00 2001 From: Jon Seymour Date: Wed, 6 Jun 2012 21:57:30 +1000 Subject: submodule: fix handling of superproject origin URLs like foo, ./foo and ./foo/bar Currently git submodule init and git submodule sync fail with an error if the superproject origin URL is of the form foo but succeed if the superproject origin URL is of the form ./foo or ./foo/bar or foo/bar. This change makes handling of the foo case behave like the handling of the ./foo case and also ensures that superfluous leading and embedded ./'s are removed from the resulting derived URLs. Signed-off-by: Jon Seymour Signed-off-by: Junio C Hamano --- git-submodule.sh | 14 ++++++++++++-- t/t7400-submodule-basic.sh | 6 +++--- t/t7403-submodule-sync.sh | 6 +++--- 3 files changed, 18 insertions(+), 8 deletions(-) (limited to 'git-submodule.sh') diff --git a/git-submodule.sh b/git-submodule.sh index 0a3e1465e3..b0b6ccbe72 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -60,8 +60,12 @@ resolve_relative_url () *:*|/*) is_relative= ;; + ./*|../*) + is_relative=t + ;; *) is_relative=t + remoteurl="./$remoteurl" ;; esac @@ -79,7 +83,12 @@ resolve_relative_url () 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 ;; @@ -90,7 +99,8 @@ resolve_relative_url () break;; esac done - echo "${is_relative:+${up_path}}$remoteurl$sep${url%/}" + remoteurl="$remoteurl$sep${url%/}" + echo "${is_relative:+${up_path}}${remoteurl#./}" } # diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 09e2b9bf16..a899e6dbf5 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -564,7 +564,7 @@ test_expect_success '../subrepo works with scp-style URL - user@host:path/to/rep ) ' -test_expect_failure '../subrepo works with relative local path - foo' ' +test_expect_success '../subrepo works with relative local path - foo' ' ( cd reltest && cp pristine-.git-config .git/config && @@ -587,7 +587,7 @@ test_expect_success '../subrepo works with relative local path - foo/bar' ' ) ' -test_expect_failure '../subrepo works with relative local path - ./foo' ' +test_expect_success '../subrepo works with relative local path - ./foo' ' ( cd reltest && cp pristine-.git-config .git/config && @@ -598,7 +598,7 @@ test_expect_failure '../subrepo works with relative local path - ./foo' ' ) ' -test_expect_failure '../subrepo works with relative local path - ./foo/bar' ' +test_expect_success '../subrepo works with relative local path - ./foo/bar' ' ( cd reltest && cp pristine-.git-config .git/config && diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 98bc74a4e9..524d5c1b21 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -88,7 +88,7 @@ test_expect_success '"git submodule sync" should not vivify uninteresting submod ) ' -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 && @@ -110,7 +110,7 @@ test_expect_success '"git submodule sync" handles origin URL of the form foo/bar ) ' -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 && @@ -121,7 +121,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 && -- cgit v1.3