Skip to content

Commit

Permalink
submodule: fix sync handling of some relative superproject origin URLs
Browse files Browse the repository at this point in the history
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 <jon.seymour@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jon Seymour authored and Junio C Hamano committed Jun 6, 2012
1 parent 49301c6 commit 967b2c6
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
48 changes: 43 additions & 5 deletions git-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -64,7 +90,7 @@ resolve_relative_url ()
break;;
esac
done
echo "$remoteurl$sep${url%/}"
echo "${is_relative:+${up_path}}$remoteurl$sep${url%/}"
}

#
Expand Down Expand Up @@ -964,22 +990,34 @@ 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
Expand Down
8 changes: 4 additions & 4 deletions t/t7403-submodule-sync.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down Expand Up @@ -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 &&
Expand All @@ -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 &&
Expand All @@ -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 &&
Expand Down

0 comments on commit 967b2c6

Please sign in to comment.