Re: [PATCH v5 2/2] submodule: fix handling of relative superproject origin URLs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, May 24, 2012 at 1:37 PM, Jon Seymour <jon.seymour@xxxxxxxxx> wrote:
> When the origin URL of the superproject is itself relative, an operation
> such as git submodule add, init or sync may result in either the
> submodule.{name}.url configuration property of the superproject
> referring to the incorrect location or remote.origin.url configuration
> property of the submodule referring to the incorrect location or both
> these conditions. In some cases, git submodule fails to update
> the configuration and fails with an error condition.
>
> The issue arises in these cases because the origin URL of
> the superproject needs to be prepended with a prefix that navigates
> from the submodule to the superproject so that when the submodule
> URL is concatenated the resulting URL is relative to the working tree
> of the submodule.
>
> This change fixes handling for relative superproject origin URLs
> for 6 cases:
>  foo
>  foo/bar
>  ./foo
>  ./foo/bar
>  ../foo
>  ../foo/bar
>
> In each case, the configuration properties in the superproject's
> configuration and the submodule's configuration refer to the
> correct, relative, location of the submodule's origin repo. In all cases,
> the configured paths are relative to the working trees of the
> repositories containing the configuration.
>
> Signed-off-by: Jon Seymour <jon.seymour@xxxxxxxxx>
> ---
>  git-submodule.sh           | 57 +++++++++++++++++++++++++++++++++++++++++-----
>  t/t7400-submodule-basic.sh |  6 ++---
>  t/t7403-submodule-sync.sh  | 18 +++++----------
>  3 files changed, 59 insertions(+), 22 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 64a70d6..738eba3 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -30,13 +30,35 @@ nofetch=
>  update=
>  prefix=
>
> -# Resolve relative url by appending to parent's url
> +# Resolve relative url by appending the submodule url
> +# to the superproject's origin URL
> +#
> +# If the origin URL is itself a relative URL prepend
> +# an additional prefix, if present, that represents
> +# the relative path from the submodule's working tree
> +# to the superprojects' working tree.
> +#
> +# This behaviour is required to ensure that the origin URL
> +# of a submodule, when relative, is relative to the
> +# submodule's work tree and not to the superproject's work tree.
> +#
>  resolve_relative_url ()
>  {
>        remote=$(get_default_remote)
>        remoteurl=$(git config "remote.$remote.url") ||
>                remoteurl=$(pwd) # the repository is its own authoritative upstream
>        url="$1"
> +       up_path="$2"
> +
> +       #
> +       # ensure all relative paths begin with ./ to enable
> +       # selection relative branch of subsequent case "$remoteurl"
> +       # statement.
> +       #
> +       # rewrites foo/bar to ./foo/bar but leaves /foo, :foo ./foo
> +       # and ../foo untouched.
> +       #
> +       remoteurl=$(echo "$remoteurl" | sed "s|^[^/:\\.][^:]*\$|./&|")
>        remoteurl=${remoteurl%/}
>        sep=/
>        while test -n "$url"
> @@ -45,6 +67,16 @@ resolve_relative_url ()
>                ../*)
>                        url="${url#../}"
>                        case "$remoteurl" in
> +                       .*/*)
> +                               # remove last part
> +                               remoteurl="${remoteurl%/*}"
> +                               # remove redundant leading ./
> +                               remoteurl="${remoteurl#./}"
> +                               # prefix path from submodule work tree to superproject work tree
> +                               remoteurl="${up_path}${remoteurl}"
> +                               # remove trailing /.
> +                               remoteurl="${remoteurl%/.}"
> +                               ;;
>                        */*)
>                                remoteurl="${remoteurl%/*}"
>                                ;;
> @@ -959,19 +991,32 @@ cmd_sync()
>        while read mode sha1 stage sm_path
>        do
>                name=$(module_name "$sm_path")
> -               url=$(git config -f .gitmodules --get submodule."$name".url)
> +               # path from superproject origin repo to submodule origin repo
> +               module_url=$(git config -f .gitmodules --get submodule."$name".url)
>
>                # Possibly a url relative to parent
> -               case "$url" in
> +               case "$module_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 "$module_url" "$up_path") &&
> +                       # path from superproject work tree to submodule origin repo
> +                       super_config_url=$(resolve_relative_url "$module_url") || exit
> +                       ;;
> +               *)
> +                       sub_origin_url="$module_url"
> +                       super_config_url="$module_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 +1024,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/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
> index 08b8d2f..f2f907f 100755
> --- a/t/t7400-submodule-basic.sh
> +++ b/t/t7400-submodule-basic.sh
> @@ -507,12 +507,11 @@ test_expect_success 'relative path works with user@host:path' '
>        )
>  '
>
> -test_expect_failure 'relative path works with foo' '
> +test_expect_success 'relative path works with foo' '
>        (
>                cd reltest &&
>                cp pristine-.git-config .git/config &&
>                git config remote.origin.url foo &&
> -               # actual: fails with an error
>                git submodule init &&
>                test "$(git config submodule.sub.url)" = ./subrepo
>        )
> @@ -538,13 +537,12 @@ test_expect_success 'relative path works with ./foo' '
>        )
>  '
>
> -test_expect_failure 'relative path works with ./foo/bar' '
> +test_expect_success 'relative path works with ./foo/bar' '
>        (
>                cd reltest &&
>                cp pristine-.git-config .git/config &&
>                git config remote.origin.url ./foo/bar &&
>                git submodule init &&
> -               #actual: ./foo/subrepo
>                test "$(git config submodule.sub.url)" = foo/subrepo
>        )
>  '
> diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
> index 9fa4e58..9526f8d 100755
> --- a/t/t7403-submodule-sync.sh
> +++ b/t/t7403-submodule-sync.sh
> @@ -88,72 +88,66 @@ 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 &&
>        (cd submodule &&
> -        #actual fails with: "cannot strip off url foo
>         git config remote.origin.url &&

Sorry, it appears I left some debug output in the tests. Will roll
this into a v6 with any updates you suggest.

Regards,

jon.
��.n��������+%������w��{.n��������n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]