Subject: Re: [PATCH 0/2] submodules: Use relative paths to gitdir and work tree

From: Jens Lehmann <[email-masked]>
Date: Sun, 26 Feb 2012 20:58:42 +0100

Am 26.02.2012 18:38, schrieb Johannes Sixt:
> Am 08.02.2012 23:08, schrieb Jens Lehmann:
>> This patch series replaces all absolute paths pointing from submodule work
>> trees to its gitdir and back with relative paths as discussed in $gmane/187785.
>>
>> The motivation is to make superprojects movable again. They lost this ability
>> with the move of the git directory of submodules into the .git/modules directory
>> of the superproject. While fixing that a bug which would hit when moving the
>> submodule inside the superproject was also fixed.
>>
>> Jens Lehmann (2):
>>   submodules: always use a relative path to gitdir
>>   submodules: always use a relative path from gitdir to work tree
> 
> This series, with the tip at e3307adaba in Junio's repo causes major
> headaches on Windows.
>
> First, a check for an absolute path must be extended to take
> Windows-style paths into account.

Okay, but that check is not part of my series (it was introduced by 501770e1
"Move git-dir for submodules", which is in Git since 1.7.8), so that looks
like it would need to be fixed for msysgit even without my patches, right?

But I'm not so happy about the two code paths there anyway, so I prepared a
patch to replace them with a single code path based upon the paths computed
in the last patch of this series. Please see the always-use-relative-gitdir
branch in my github repo https://github.com/jlehmann/git-submod-enhancements

> Second, the a's and b's are filled with different forms of absolute
> paths (/c/there vs. c:/there), and as a consequence the subsequent loops
> do not find a suitable relative path.
> 
> The below is a minimal hack that passes all t/*submod* tests, but it
> works only on Windows, where the pwd utility has an option -W that
> prints a Windows style absolute path.
> 
> How would you have this solved? One option would be to introduce a function
> 
>   pwd() { builtin pwd -W "$@"; }
> 
> in git-sh-setup conditionally on Windows (but that would affect other
> shell scripts, too).

I suspect other shell scripts might be less affected when non-Windows
paths are forced (at least when they aren't developed under Windows
only). What about something like this:

  pwd() { builtin pwd -W "$@" | sed -e 's,^\([a-z]\):/,/\1/,'; }

> Any other ideas?
> 
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 3463d6d..f37745e 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -139,8 +139,8 @@ module_clone()
>  	gitdir="$gitdir/modules/$path"
>
>  	case $gitdir in
> -	/*)
> -		a="$(cd_to_toplevel && pwd)/"
> +	/* | [a-z]:/*)
> +		a="$(cd_to_toplevel && pwd -W)/"
>  		b=$gitdir
>  		while [ "$b" ] && [ "${a%%/*}" = "${b%%/*}" ]
>  		do

Hmm, here the path which starts with "c:/" is returned by the "git
rev-parse --git-dir" which is used to initialize the $gitdir variable
a few lines up.

> @@ -170,8 +170,8 @@ module_clone()
>
>  	echo "gitdir: $rel_gitdir" >"$path/.git"
>
> -	a=$(cd "$gitdir" && pwd)
> -	b=$(cd "$path" && pwd)
> +	a=$(cd "$gitdir" && pwd -W)
> +	b=$(cd "$path" && pwd -W)
>  	while [ "$b" ] && [ "${a%%/*}" = "${b%%/*}" ]
>  	do
>  		a=${a#*/} b=${b#*/};

I don't understand why you need this. Does "pwd" sometimes return a
path starting with "c:/" and sometimes "/c/" depending on what form
you use when you cd into that directory? If not, does the following
help you on windows? (If that is the case, you might need the pwd
redefinition too to make that work)

-----------------8<--------------------
diff --git a/git-submodule.sh b/git-submodule.sh
index 5deabf6..5bb8109 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -134,7 +134,7 @@ module_clone()
        test -n "$name" || name="$path"
        base_path=$(dirname "$path")

-       gitdir=$(git rev-parse --git-dir)
+       gitdir=$(git rev-parse --git-dir | sed -e 's,^\([a-z]\):/,/\1/,')
        gitdir_base="$gitdir/modules/$base_path"
        gitdir="$gitdir/modules/$path"