git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* Regression in e02ca72: git svn rebase is broken on Windows
@ 2013-09-10 13:14 Tvangeste
  2013-09-10 16:13 ` Johannes Schindelin
                   ` (2 more replies)
  0 siblings, 3 replies; 56+ messages in thread
From: Tvangeste @ 2013-09-10 13:14 UTC (permalink / raw)
  To: git

Hi,

After bisecting this problem I ended up with the mentioned commit that completely breaks git-svn for me on Windows (mingw/msys version).

==========
#> git svn rebase
warning: unable to access '': Invalid argument
warning: unable to access '': Invalid argument
fatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument
fatal: index file open failed: Invalid argument
Cannot rebase: You have unstaged changes.
Please commit or stash them.
rebase refs/remotes/trunk: command returned error: 1
==========

Please note that I use the official git repository as-is, this one (no additional patches):
git://git.kernel.org/pub/scm/git/git.git

e02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit
commit e02ca72f70ed8f0268a81f72cb3230c72e538e77
Author: Jiang Xin
Date:   Tue Jun 25 23:53:43 2013 +0800

    path.c: refactor relative_path(), not only strip prefix

Thanks,
  --Tvangeste

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 13:14 Regression in e02ca72: git svn rebase is broken on Windows Tvangeste
@ 2013-09-10 16:13 ` Johannes Schindelin
  2013-09-10 17:43   ` Tvangeste
  2013-09-10 16:52 ` Johannes Sixt
  2013-09-10 17:06 ` Junio C Hamano
  2 siblings, 1 reply; 56+ messages in thread
From: Johannes Schindelin @ 2013-09-10 16:13 UTC (permalink / raw)
  To: Tvangeste; +Cc: git

Hi Tvangeste,

On Tue, 10 Sep 2013, Tvangeste wrote:

> After bisecting this problem I ended up with the mentioned commit that
> completely breaks git-svn for me on Windows (mingw/msys version).

Have you tried with Git for Windows yet?

Ciao,
Johannes

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 13:14 Regression in e02ca72: git svn rebase is broken on Windows Tvangeste
  2013-09-10 16:13 ` Johannes Schindelin
@ 2013-09-10 16:52 ` Johannes Sixt
  2013-09-10 17:44   ` Tvangeste
  2013-09-10 17:06 ` Junio C Hamano
  2 siblings, 1 reply; 56+ messages in thread
From: Johannes Sixt @ 2013-09-10 16:52 UTC (permalink / raw)
  To: Tvangeste; +Cc: git

Am 10.09.2013 15:14, schrieb Tvangeste:
> After bisecting this problem I ended up with the mentioned commit
> that completely breaks git-svn for me on Windows (mingw/msys version).
> 
> ==========
> #> git svn rebase
> warning: unable to access '': Invalid argument
> warning: unable to access '': Invalid argument
> fatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument
> fatal: index file open failed: Invalid argument
> Cannot rebase: You have unstaged changes.
> Please commit or stash them.
> rebase refs/remotes/trunk: command returned error: 1
> ==========

Can you please run the command with GIT_TRACE=2?

-- Hannes

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 13:14 Regression in e02ca72: git svn rebase is broken on Windows Tvangeste
  2013-09-10 16:13 ` Johannes Schindelin
  2013-09-10 16:52 ` Johannes Sixt
@ 2013-09-10 17:06 ` Junio C Hamano
  2013-09-10 22:17   ` Karsten Blees
                     ` (7 more replies)
  2 siblings, 8 replies; 56+ messages in thread
From: Junio C Hamano @ 2013-09-10 17:06 UTC (permalink / raw)
  To: Jiang Xin; +Cc: git, Tvangeste

Tvangeste <i.4m.l33t@yandex.ru> writes:

> Hi,
>
> After bisecting this problem I ended up with the mentioned commit that completely breaks git-svn for me on Windows (mingw/msys version).
>
> ==========
> #> git svn rebase
> warning: unable to access '': Invalid argument
> warning: unable to access '': Invalid argument
> fatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument
> fatal: index file open failed: Invalid argument
> Cannot rebase: You have unstaged changes.
> Please commit or stash them.
> rebase refs/remotes/trunk: command returned error: 1
> ==========
>
> Please note that I use the official git repository as-is, this one (no additional patches):
> git://git.kernel.org/pub/scm/git/git.git
>
> e02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit
> commit e02ca72f70ed8f0268a81f72cb3230c72e538e77
> Author: Jiang Xin
> Date:   Tue Jun 25 23:53:43 2013 +0800
>
>     path.c: refactor relative_path(), not only strip prefix
>
> Thanks,
>   --Tvangeste

The suspect commit and symptom look consistent.  You started from a
directory whose absolute path is "w:/work/..." and the updated code
mistakenly thoguht that something that begins with "w" (not '/') is
not an absolute, so added a series of ../ to make it relative, or
something silly like that.

Jiang?

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 16:13 ` Johannes Schindelin
@ 2013-09-10 17:43   ` Tvangeste
  2013-09-10 18:02     ` Johannes Schindelin
  0 siblings, 1 reply; 56+ messages in thread
From: Tvangeste @ 2013-09-10 17:43 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git@vger.kernel.org

10.09.2013, 18:13, "Johannes Schindelin" <Johannes.Schindelin@gmx.de>:
> Have you tried with Git for Windows yet?

What's Git for Windows? If you mean msysgit, then I say no, because the latest msysgit version is from June 02, and the change under discussion was made later on, on June 25th. So, this regression is not in msysgit release (yet).

Thanks,
  --Tvangeste

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 16:52 ` Johannes Sixt
@ 2013-09-10 17:44   ` Tvangeste
  0 siblings, 0 replies; 56+ messages in thread
From: Tvangeste @ 2013-09-10 17:44 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git@vger.kernel.org

10.09.2013, 18:53, "Johannes Sixt" <j6t@kdbg.org>:
> Can you please run the command with GIT_TRACE=2?

Sure:
#> git --version
trace: built-in: git 'version'
git version 1.8.4.242.gbb80ee0

#> git svn rebase -l
trace: exec: 'git-svn' 'rebase' '-l'
trace: run_command: 'git-svn' 'rebase' '-l'
trace: built-in: git 'rev-parse' '--git-dir'
trace: built-in: git 'rev-parse' '--show-cdup'
trace: built-in: git 'config' '--bool' '--get' 'svn.fetchall'
trace: built-in: git 'config' '--bool' '--get' 'svn.noauthcache'
trace: built-in: git 'config' '--bool' '--get' 'svn.nocheckout'
trace: built-in: git 'config' '--get' 'svn.authorsprog'
trace: built-in: git 'config' '--bool' '--get' 'svn.dryrun'
trace: built-in: git 'config' '--bool' '--get' 'svn.preservemerges'
trace: built-in: git 'config' '--bool' '--get' 'svn.followparent'
trace: built-in: git 'config' '--bool' '--get' 'svn.useSvmProps'
trace: built-in: git 'config' '--get' 'svn.authorsfile'
trace: built-in: git 'config' '--get' 'svn.username'
trace: built-in: git 'config' '--get' 'svn.repackflags'
trace: built-in: git 'config' '--bool' '--get' 'svn.localtime'
trace: built-in: git 'config' '--int' '--get' 'svn.repack'
trace: built-in: git 'config' '--get' 'svn.ignorepaths'
trace: built-in: git 'config' '--bool' '--get' 'svn.verbose'
trace: built-in: git 'config' '--bool' '--get' 'svn.quiet'
trace: built-in: git 'config' '--int' '--get' 'svn.logwindowsize'
trace: built-in: git 'config' '--get' 'svn.ignorerefs'
trace: built-in: git 'config' '--get' 'svn.configdir'
trace: built-in: git 'config' '--bool' '--get' 'svn.merge'
trace: built-in: git 'config' '--bool' '--get' 'svn.addauthorfrom'
trace: built-in: git 'config' '--bool' '--get' 'svn.useSvnsyncProps'
trace: built-in: git 'config' '--bool' '--get' 'svn.noMetadata'
trace: built-in: git 'config' '--bool' '--get' 'svn.local'
trace: built-in: git 'config' '--get' 'svn.strategy'
trace: built-in: git 'config' '--get' 'svn.includepaths'
trace: built-in: git 'config' '--bool' '--get' 'svn.uselogauthor'
trace: built-in: git 'rev-parse' '--symbolic' '--all'
trace: built-in: git 'config' '-l'
trace: built-in: git 'config' '-l'
trace: built-in: git 'update-index' '--refresh'
trace: built-in: git 'rev-list' '--first-parent' '--pretty=medium' 'HEAD' '--'
trace: built-in: git 'config' '--bool' 'svn.useSvmProps'
trace: built-in: git 'config' '-l'
trace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'
trace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'
trace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'
trace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'
trace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'
trace: built-in: git 'config' '--get' 'svn-remote.svn.rewriteRoot'
trace: built-in: git 'config' '--get' 'svn-remote.svn.url'
trace: built-in: git 'config' '--get' 'svn-remote.svn.pushurl'
trace: built-in: git 'config' '--get' 'svn-remote.svn.uuid'
trace: built-in: git 'rev-list' '--pretty=raw' '--reverse' 'cdc459d7cedcec6bb26812e24661c7318f031be4..refs/remotes/trunk' '--'
trace: built-in: git 'config' '--get' 'svn-remote.svn.rewriteRoot'
trace: built-in: git 'config' '--get' 'svn-remote.svn.rewriteUUID'
trace: built-in: git 'diff-index' 'HEAD' '--'
trace: exec: 'git-rebase' 'refs/remotes/trunk'
trace: run_command: 'git-rebase' 'refs/remotes/trunk'
trace: built-in: git 'rev-parse' '--parseopt' '--' 'refs/remotes/trunk'
trace: built-in: git 'rev-parse' '--git-dir'
trace: built-in: git 'rev-parse' '--is-bare-repository'
trace: built-in: git 'rev-parse' '--show-toplevel'
trace: built-in: git 'config' '--bool' 'rebase.stat'
trace: built-in: git 'config' '--bool' 'rebase.autostash'
trace: built-in: git 'config' '--bool' 'rebase.autosquash'
trace: built-in: git 'rev-parse' '--verify' 'refs/remotes/trunk^0'
trace: built-in: git 'rev-parse' '--verify' 'refs/remotes/trunk^0'
trace: built-in: git 'symbolic-ref' '-q' 'HEAD'
trace: built-in: git 'rev-parse' '--verify' 'HEAD'
trace: built-in: git 'rev-parse' '--verify' 'HEAD'
trace: built-in: git 'update-index' '-q' '--ignore-submodules' '--refresh'
fatal: unable to access '../../../../w:/work/xxx/xxx-xxx-OSS.git.new/.git/config': Invalid argument
trace: built-in: git 'diff-files' '--quiet' '--ignore-submodules'
fatal: index file open failed: Invalid argument
Cannot rebase: You have unstaged changes.
trace: built-in: git 'diff-index' '--cached' '--quiet' '--ignore-submodules' 'HEAD' '--'
Please commit or stash them.
rebase refs/remotes/trunk: command returned error: 1

Thanks,
  --Tvangeste

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 17:43   ` Tvangeste
@ 2013-09-10 18:02     ` Johannes Schindelin
  2013-09-10 20:53       ` Tvangeste
  0 siblings, 1 reply; 56+ messages in thread
From: Johannes Schindelin @ 2013-09-10 18:02 UTC (permalink / raw)
  To: Tvangeste; +Cc: git@vger.kernel.org, msysgit

Hi Tvangeste,

On Tue, 10 Sep 2013, Tvangeste wrote:

> 10.09.2013, 18:13, "Johannes Schindelin" <Johannes.Schindelin@gmx.de>:
> > Have you tried with Git for Windows yet?
> 
> What's Git for Windows? If you mean msysgit,

Actually, they are two different things: Git for Windows is what the name
says, and it comes with an installer. msysGit is the development
environment to *build* Git for Windows.

> then I say no, because the latest msysgit version is from June 02, and
> the change under discussion was made later on, on June 25th. So, this
> regression is not in msysgit release (yet).

Given the explanation what msysGit is, you might suspect that I'd like you
to try to fix this in the msysGit context: After installing

	https://code.google.com/p/msysgit/downloads/list?q=net+installer

you will have a full build environment, including the build of our latest
master. You can then "cd /git/" and "git checkout pt/tentative-1.8.4 &&
make install" to make sure that the version we are very close to releasing
as the new Git for Windows version does not break your workflow.

Ciao,
Johannes

-- 
-- 
*** Please reply-to-all at all times ***
*** (do not pretend to know who is subscribed and who is not) ***
*** Please avoid top-posting. ***
The msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.

You received this message because you are subscribed to the Google
Groups "msysGit" group.
To post to this group, send email to msysgit@googlegroups.com
To unsubscribe from this group, send email to
msysgit+unsubscribe@googlegroups.com
For more options, and view previous threads, visit this group at
http://groups.google.com/group/msysgit?hl=en_US?hl=en

--- 
You received this message because you are subscribed to the Google Groups "msysGit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to msysgit+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 18:02     ` Johannes Schindelin
@ 2013-09-10 20:53       ` Tvangeste
  0 siblings, 0 replies; 56+ messages in thread
From: Tvangeste @ 2013-09-10 20:53 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git@vger.kernel.org, msysgit@googlegroups.com

10.09.2013, 20:02, "Johannes Schindelin" <Johannes.Schindelin@gmx.de>:
>  Given the explanation what msysGit is, you might suspect that I'd like you
>  to try to fix this in the msysGit context: After installing
>
>          https://code.google.com/p/msysgit/downloads/list?q=net+installer

No problem. Here's what I have so far:

1. Installed the latest msysgit from the URL you've provided. Tried the git that comes out of the box that comes with the installer (1.8.3.msysgit):

1a. On CMD: everything is fine.
1b. On msys shell: everything is fine.

2. Checked out the branch you've suggested to try (pt/tentative-1.8.4) and installed it. Tried the new version:

2a. On CMD: got the problem that is being discussed in this thread.
2b. On msys shell: everything is fine.

So, in summary. That commit e02ca72, somewhere between 1.8.3 and 1.8.4 introduced the regression in git/git-svn on Windows, when executed in CMD.

Thanks,
  --Tvangeste

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 17:06 ` Junio C Hamano
@ 2013-09-10 22:17   ` Karsten Blees
  2013-09-11  4:41     ` Jiang Xin
  2013-09-11  3:19   ` Jiang Xin
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 56+ messages in thread
From: Karsten Blees @ 2013-09-10 22:17 UTC (permalink / raw)
  To: git

Junio C Hamano <gitster <at> pobox.com> writes:

> 
> Tvangeste <i.4m.l33t <at> yandex.ru> writes:
> 
> > Hi,
> >
> > After bisecting this problem I ended up with the mentioned commit that
completely breaks git-svn for me on
> Windows (mingw/msys version).
> >
> > ==========
> > #> git svn rebase
> > warning: unable to access '': Invalid argument
> > warning: unable to access '': Invalid argument
> > fatal: unable to access '../../../../w:/work/my/repo.git/.git/config':
Invalid argument
> > fatal: index file open failed: Invalid argument
> > Cannot rebase: You have unstaged changes.
> > Please commit or stash them.
> > rebase refs/remotes/trunk: command returned error: 1
> > ==========
> >
> > Please note that I use the official git repository as-is, this one (no
additional patches):
> > git://git.kernel.org/pub/scm/git/git.git
> >
> > e02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit
> > commit e02ca72f70ed8f0268a81f72cb3230c72e538e77
> > Author: Jiang Xin
> > Date:   Tue Jun 25 23:53:43 2013 +0800
> >
> >     path.c: refactor relative_path(), not only strip prefix
> >
> > Thanks,
> >   --Tvangeste
> 
> The suspect commit and symptom look consistent.  You started from a
> directory whose absolute path is "w:/work/..." and the updated code
> mistakenly thoguht that something that begins with "w" (not '/') is
> not an absolute, so added a series of ../ to make it relative, or
> something silly like that.
> 
> Jiang?
> 

Indeed, this patch seems to change relative_path in a way that breaks git
initialization, not just on Windows.

Previously, relative_path was always called with two absolute paths, and it
only returned a relative path if the first was a subdir of the second (so a
better name would probably have been 'relative_path_if_subdir'). The purpose
was to improve performance by making GIT_DIR shorter if it was a subdir of
GIT_WORK_TREE.

After this patch, relative_path always tries to return a relative path, even
if both absolute paths are completely disjunct. This not only defeats the
purpose (by making GIT_DIR longer, thus hurting performance), it is also not
possible in general. POSIX explicitly allows for '//hostname' notation
referring to network resources that are not explicitly mounted under '/'.
I.e. given two absolute paths '//hostname1/a' and '//hostname2/b', there is
no relative path from a to b or vice versa.

Additionally, GIT_DIR now may or may not have a trailing slash, which gives
me a slightly uneasy feeling...

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 17:06 ` Junio C Hamano
  2013-09-10 22:17   ` Karsten Blees
@ 2013-09-11  3:19   ` Jiang Xin
  2013-09-11  5:43     ` Johannes Sixt
  2013-09-12  9:12   ` [PATCH 1/2] relative_path should honor dos_drive_prefix Jiang Xin
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-11  3:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git List, Tvangeste, msysgit

2013/9/11 Junio C Hamano <gitster@pobox.com>:
> Tvangeste <i.4m.l33t@yandex.ru> writes:
>
>> Hi,
>>
>> After bisecting this problem I ended up with the mentioned commit that completely breaks git-svn for me on Windows (mingw/msys version).
>>
>> ==========
>> #> git svn rebase
>> warning: unable to access '': Invalid argument
>> warning: unable to access '': Invalid argument
>> fatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument
>> fatal: index file open failed: Invalid argument
>> Cannot rebase: You have unstaged changes.
>> Please commit or stash them.
>> rebase refs/remotes/trunk: command returned error: 1
>> ==========
>>
>> Please note that I use the official git repository as-is, this one (no additional patches):
>> git://git.kernel.org/pub/scm/git/git.git
>>
>> e02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit
>> commit e02ca72f70ed8f0268a81f72cb3230c72e538e77
>> Author: Jiang Xin
>> Date:   Tue Jun 25 23:53:43 2013 +0800
>>
>>     path.c: refactor relative_path(), not only strip prefix
>>
>> Thanks,
>>   --Tvangeste
>
> The suspect commit and symptom look consistent.  You started from a
> directory whose absolute path is "w:/work/..." and the updated code
> mistakenly thoguht that something that begins with "w" (not '/') is
> not an absolute, so added a series of ../ to make it relative, or
> something silly like that.
>
> Jiang?

I tested 'relative_path' function using 'test-path-utils', and got the
following result:

    $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'
    ../../../C:/a/b

    $ ./test-path-utils relative_path '/a/b' 'x/y'
    ../..//a/b

    $ ./test-path-utils relative_path 'a/b' '/x/y'
    ../../../a/b

For the first case, in and prefix are on different ROOT, and for the other
two cases, one path is a relative path, and another is an absolute path.

I write a patch to test whether two paths (in and prefix) have the same
root. The result after applied the patch:

    $ ./test-path-utils relative_path 'C:/a/b' 'C:/x/y'
    ../../a/b

    $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'
    C:/a/b

    $ ./test-path-utils relative_path '/a/b' 'x/y'
    /a/b

    $ ./test-path-utils relative_path 'a/b' '/x/y'
    a/b


diff --git a/path.c b/path.c
index 7f3324a..51f5d28 100644
--- a/path.c
+++ b/path.c
@@ -441,6 +441,25 @@ int adjust_shared_perm(const char *path)
        return 0;
 }

+static int have_same_root(const char *path1, const char *path2)
+{
+       /* for POSIX:
+
+          return ((path1 && is_dir_sep(*path1)) ^
+                  (path2 && is_dir_sep(*path2))) == 0;
+       */
+       return path1 && path2 && *path1 && *path2 && (
+               (is_dir_sep(*path1) &&
+                is_dir_sep(*path2)) ||
+               (*(path1+1) == ':' &&
+                *(path2+1) == ':' &&
+                !strncasecmp(path1, path2, 1)) ||
+               (!is_dir_sep(*path1) &&
+                !is_dir_sep(*path2) &&
+                *(path1+1) != ':' &&
+                *(path2+1) != ':'));
+}
+
 /*
  * Give path as relative to prefix.
  *
@@ -461,6 +480,9 @@ const char *relative_path(const char *in, const
char *prefix,
        else if (!prefix_len)
                return in;

+       if (!have_same_root(in, prefix))
+               return in;
+

Should I write the function have_same_root as inline function or macro
like 'is_dir_sep'?

-- 
Jiang Xin

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-10 22:17   ` Karsten Blees
@ 2013-09-11  4:41     ` Jiang Xin
  0 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-11  4:41 UTC (permalink / raw)
  To: Karsten Blees; +Cc: Git List

2013/9/11 Karsten Blees <karsten.blees@gmail.com>:
> Junio C Hamano <gitster <at> pobox.com> writes:
>
>> The suspect commit and symptom look consistent.  You started from a
>> directory whose absolute path is "w:/work/..." and the updated code
>> mistakenly thoguht that something that begins with "w" (not '/') is
>> not an absolute, so added a series of ../ to make it relative, or
>> something silly like that.
>>
>> Jiang?
>>
>
> Indeed, this patch seems to change relative_path in a way that breaks git
> initialization, not just on Windows.
>
> Previously, relative_path was always called with two absolute paths, and it
> only returned a relative path if the first was a subdir of the second (so a
> better name would probably have been 'relative_path_if_subdir'). The purpose
> was to improve performance by making GIT_DIR shorter if it was a subdir of
> GIT_WORK_TREE.

Yes, it's what commit v1.5.6-1-g044bbbc says.

> After this patch, relative_path always tries to return a relative path, even
> if both absolute paths are completely disjunct. This not only defeats the
> purpose (by making GIT_DIR longer, thus hurting performance), it is also not

Sometimes longer, sometimes shorter maybe.

> possible in general. POSIX explicitly allows for '//hostname' notation
> referring to network resources that are not explicitly mounted under '/'.
> I.e. given two absolute paths '//hostname1/a' and '//hostname2/b', there is
> no relative path from a to b or vice versa.

Yes, path like "//hostname/path" can be used on Windows.
My hack "have_same_root" does not cover this case, so using
a "simple_relative_path" function instead of "relative_path" in setup.c
may be the better.


-- 
Jiang Xin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: Regression in e02ca72: git svn rebase is broken on Windows
  2013-09-11  3:19   ` Jiang Xin
@ 2013-09-11  5:43     ` Johannes Sixt
  0 siblings, 0 replies; 56+ messages in thread
From: Johannes Sixt @ 2013-09-11  5:43 UTC (permalink / raw)
  To: Jiang Xin; +Cc: Junio C Hamano, Git List, Tvangeste, msysgit

Am 11.09.2013 05:19, schrieb Jiang Xin:
> I tested 'relative_path' function using 'test-path-utils', and got the
> following result:
> 
>     $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'
>     ../../../C:/a/b
> 
>     $ ./test-path-utils relative_path '/a/b' 'x/y'
>     ../..//a/b
> 
>     $ ./test-path-utils relative_path 'a/b' '/x/y'
>     ../../../a/b
> 
> For the first case, in and prefix are on different ROOT, and for the other
> two cases, one path is a relative path, and another is an absolute path.
> 
> I write a patch to test whether two paths (in and prefix) have the same
> root. The result after applied the patch:
> 
>     $ ./test-path-utils relative_path 'C:/a/b' 'C:/x/y'
>     ../../a/b
> 
>     $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'
>     C:/a/b
> 
>     $ ./test-path-utils relative_path '/a/b' 'x/y'
>     /a/b
> 
>     $ ./test-path-utils relative_path 'a/b' '/x/y'
>     a/b
> 
> 
> diff --git a/path.c b/path.c
> index 7f3324a..51f5d28 100644
> --- a/path.c
> +++ b/path.c
> @@ -441,6 +441,25 @@ int adjust_shared_perm(const char *path)
>         return 0;
>  }
> 
> +static int have_same_root(const char *path1, const char *path2)
> +{
> +       /* for POSIX:
> +
> +          return ((path1 && is_dir_sep(*path1)) ^
> +                  (path2 && is_dir_sep(*path2))) == 0;
> +       */
> +       return path1 && path2 && *path1 && *path2 && (
> +               (is_dir_sep(*path1) &&
> +                is_dir_sep(*path2)) ||
> +               (*(path1+1) == ':' &&
> +                *(path2+1) == ':' &&
> +                !strncasecmp(path1, path2, 1)) ||
> +               (!is_dir_sep(*path1) &&
> +                !is_dir_sep(*path2) &&
> +                *(path1+1) != ':' &&
> +                *(path2+1) != ':'));

I think this can be simplified to

	return path1 && path2 &&
		is_absolute_path(path1) &&
		is_absolute_path(path2) &&
		!strncasecmp(path1, path2, 1);

which would not mistake a path D:/foo on Unix as an absolute path.

> +}

-- Hannes

-- 
-- 
*** Please reply-to-all at all times ***
*** (do not pretend to know who is subscribed and who is not) ***
*** Please avoid top-posting. ***
The msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.

You received this message because you are subscribed to the Google
Groups "msysGit" group.
To post to this group, send email to msysgit@googlegroups.com
To unsubscribe from this group, send email to
msysgit+unsubscribe@googlegroups.com
For more options, and view previous threads, visit this group at
http://groups.google.com/group/msysgit?hl=en_US?hl=en

--- 
You received this message because you are subscribed to the Google Groups "msysGit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to msysgit+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-10 17:06 ` Junio C Hamano
  2013-09-10 22:17   ` Karsten Blees
  2013-09-11  3:19   ` Jiang Xin
@ 2013-09-12  9:12   ` Jiang Xin
  2013-09-12  9:32     ` Tvangeste
                       ` (2 more replies)
  2013-09-12  9:12   ` [PATCH 2/2] Use simpler relative_path when set_git_dir Jiang Xin
                     ` (4 subsequent siblings)
  7 siblings, 3 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-12  9:12 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees, Jiang Xin

Tvangeste found that the "relative_path" function could not work
properly on Windows if "in" and "prefix" have dos driver prefix.
($gmane/234434)

e.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
should return "C:/a/b", but returns "../../C:/a/b", which is wrong.

So make relative_path honor dos_drive_prefix, and add test cases
for it in t0060.

Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 path.c                | 20 ++++++++++++++++++++
 t/t0060-path-utils.sh |  4 ++++
 2 files changed, 24 insertions(+)

diff --git a/path.c b/path.c
index 7f3324a..ffcdea1 100644
--- a/path.c
+++ b/path.c
@@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)
 	return 0;
 }
 
+static int have_same_root(const char *path1, const char *path2)
+{
+	int is_abs1, is_abs2;
+
+	is_abs1 = is_absolute_path(path1);
+	is_abs2 = is_absolute_path(path2);
+	return (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||
+	       (!is_abs1 && !is_abs2);
+}
+
 /*
  * Give path as relative to prefix.
  *
@@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,
 	else if (!prefix_len)
 		return in;
 
+	if (have_same_root(in, prefix)) {
+		/* bypass dos_drive, for "c:" is identical to "C:" */
+		if (has_dos_drive_prefix(in)) {
+			i = 2;
+			j = 2;
+		}
+	} else {
+		return in;
+	}
+
 	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
 		if (is_dir_sep(prefix[i])) {
 			while (is_dir_sep(prefix[i]))
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 76c7792..c3c3b33 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -208,6 +208,10 @@ relative_path a/b/	a/b		./
 relative_path a		a/b		../
 relative_path x/y	a/b		../../x/y
 relative_path a/c	a/b		../c
+relative_path a/b	/x/y		a/b
+relative_path /a/b	x/y		/a/b	POSIX
+relative_path d:/a/b	D:/a/c		../b	MINGW
+relative_path C:/a/b	D:/a/c		C:/a/b	MINGW
 relative_path a/b	"<empty>"	a/b
 relative_path a/b 	"<null>"	a/b
 relative_path "<empty>"	/a/b		./
-- 
1.8.3.rc2.14.g5ac1b82

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 2/2] Use simpler relative_path when set_git_dir
  2013-09-10 17:06 ` Junio C Hamano
                     ` (2 preceding siblings ...)
  2013-09-12  9:12   ` [PATCH 1/2] relative_path should honor dos_drive_prefix Jiang Xin
@ 2013-09-12  9:12   ` Jiang Xin
  2013-09-12 17:36     ` Johannes Sixt
  2013-09-13  5:08   ` [PATCH v2 0/3] fixes for relative_path Jiang Xin
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-12  9:12 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees, Jiang Xin

Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.
It will make git_dir shorter only if git_dir is inside work_tree,
and this will increase performance. But my last refactor effort on
relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.
Always use relative_path as git_dir may bring troubles like
$gmane/234434.

Because new relative_path is a combination of original relative_path
from path.c and original path_relative from quote.c, so in order to
restore the origin implementation, save the original relative_path
to simple_relative_path, and call it in setup.c.

Suggested-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 cache.h |  1 +
 path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 setup.c |  5 +----
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index 8e42256..ab17f1d 100644
--- a/cache.h
+++ b/cache.h
@@ -738,6 +738,7 @@ const char *real_path(const char *path);
 const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
 const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
+const char *simple_relative_path(const char *in, const char *prefix);
 int normalize_path_copy(char *dst, const char *src);
 int longest_ancestor_length(const char *path, struct string_list *prefixes);
 char *strip_path_suffix(const char *path, const char *suffix);
diff --git a/path.c b/path.c
index ffcdea1..0f0c92f 100644
--- a/path.c
+++ b/path.c
@@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,
 }
 
 /*
+ * A simpler implementation of relative_path
+ *
+ * Get relative path by removing "prefix" from "in". This function
+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
+ * to increase performance when traversing the path to work_tree.
+ */
+const char *simple_relative_path(const char *in, const char *prefix)
+{
+	static char buf[PATH_MAX + 1];
+	int i = 0, j = 0;
+
+	if (!prefix || !prefix[0])
+		return in;
+	while (prefix[i]) {
+		if (is_dir_sep(prefix[i])) {
+			if (!is_dir_sep(in[j]))
+				return in;
+			while (is_dir_sep(prefix[i]))
+				i++;
+			while (is_dir_sep(in[j]))
+				j++;
+			continue;
+		} else if (in[j] != prefix[i]) {
+			return in;
+		}
+		i++;
+		j++;
+	}
+	if (
+	    /* "/foo" is a prefix of "/foo" */
+	    in[j] &&
+	    /* "/foo" is not a prefix of "/foobar" */
+	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
+	   )
+		return in;
+	while (is_dir_sep(in[j]))
+		j++;
+	if (!in[j])
+		strcpy(buf, ".");
+	else
+		strcpy(buf, in + j);
+	return buf;
+}
+
+/*
  * It is okay if dst == src, but they should not overlap otherwise.
  *
  * Performs the following normalizations on src, storing the result in dst:
diff --git a/setup.c b/setup.c
index 0d9ea62..f4be6ff 100644
--- a/setup.c
+++ b/setup.c
@@ -360,7 +360,6 @@ int is_inside_work_tree(void)
 
 void setup_work_tree(void)
 {
-	struct strbuf sb = STRBUF_INIT;
 	const char *work_tree, *git_dir;
 	static int initialized = 0;
 
@@ -380,10 +379,8 @@ void setup_work_tree(void)
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
 		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
-	set_git_dir(relative_path(git_dir, work_tree, &sb));
+	set_git_dir(simple_relative_path(git_dir, work_tree));
 	initialized = 1;
-
-	strbuf_release(&sb);
 }
 
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
-- 
1.8.3.rc2.14.g5ac1b82

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-12  9:12   ` [PATCH 1/2] relative_path should honor dos_drive_prefix Jiang Xin
@ 2013-09-12  9:32     ` Tvangeste
  2013-09-12 14:13     ` Torsten Bögershausen
  2013-09-12 15:45     ` Karsten Blees
  2 siblings, 0 replies; 56+ messages in thread
From: Tvangeste @ 2013-09-12  9:32 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Junio C Hamano, Git List, Tvangeste, Johannes Sixt, Karsten Blees

Thank you, this fixes the problem with `git svn rebase` on Windows for me.

--Tvangeste

On Thu, Sep 12, 2013 at 11:12 AM, Jiang Xin <worldhello.net@gmail.com> wrote:
> Tvangeste found that the "relative_path" function could not work
> properly on Windows if "in" and "prefix" have dos driver prefix.
> ($gmane/234434)
>
> e.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
> should return "C:/a/b", but returns "../../C:/a/b", which is wrong.
>
> So make relative_path honor dos_drive_prefix, and add test cases
> for it in t0060.
>
> Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
> Helped-by: Johannes Sixt <j6t@kdbg.org>
> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
> ---
>  path.c                | 20 ++++++++++++++++++++
>  t/t0060-path-utils.sh |  4 ++++
>  2 files changed, 24 insertions(+)
>
> diff --git a/path.c b/path.c
> index 7f3324a..ffcdea1 100644
> --- a/path.c
> +++ b/path.c
> @@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)
>         return 0;
>  }
>
> +static int have_same_root(const char *path1, const char *path2)
> +{
> +       int is_abs1, is_abs2;
> +
> +       is_abs1 = is_absolute_path(path1);
> +       is_abs2 = is_absolute_path(path2);
> +       return (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||
> +              (!is_abs1 && !is_abs2);
> +}
> +
>  /*
>   * Give path as relative to prefix.
>   *
> @@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,
>         else if (!prefix_len)
>                 return in;
>
> +       if (have_same_root(in, prefix)) {
> +               /* bypass dos_drive, for "c:" is identical to "C:" */
> +               if (has_dos_drive_prefix(in)) {
> +                       i = 2;
> +                       j = 2;
> +               }
> +       } else {
> +               return in;
> +       }
> +
>         while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
>                 if (is_dir_sep(prefix[i])) {
>                         while (is_dir_sep(prefix[i]))
> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
> index 76c7792..c3c3b33 100755
> --- a/t/t0060-path-utils.sh
> +++ b/t/t0060-path-utils.sh
> @@ -208,6 +208,10 @@ relative_path a/b/ a/b             ./
>  relative_path a                a/b             ../
>  relative_path x/y      a/b             ../../x/y
>  relative_path a/c      a/b             ../c
> +relative_path a/b      /x/y            a/b
> +relative_path /a/b     x/y             /a/b    POSIX
> +relative_path d:/a/b   D:/a/c          ../b    MINGW
> +relative_path C:/a/b   D:/a/c          C:/a/b  MINGW
>  relative_path a/b      "<empty>"       a/b
>  relative_path a/b      "<null>"        a/b
>  relative_path "<empty>"        /a/b            ./
> --
> 1.8.3.rc2.14.g5ac1b82
>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-12  9:12   ` [PATCH 1/2] relative_path should honor dos_drive_prefix Jiang Xin
  2013-09-12  9:32     ` Tvangeste
@ 2013-09-12 14:13     ` Torsten Bögershausen
  2013-09-12 15:48       ` Junio C Hamano
  2013-09-12 17:22       ` Johannes Sixt
  2013-09-12 15:45     ` Karsten Blees
  2 siblings, 2 replies; 56+ messages in thread
From: Torsten Bögershausen @ 2013-09-12 14:13 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Junio C Hamano, Git List, Tvangeste, Johannes Sixt, Karsten Blees

On 2013-09-12 11.12, Jiang Xin wrote:
> Tvangeste found that the "relative_path" function could not work
> properly on Windows if "in" and "prefix" have dos driver prefix.
> ($gmane/234434)
> 
> e.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
> should return "C:/a/b", but returns "../../C:/a/b", which is wrong.
> 
> So make relative_path honor dos_drive_prefix, and add test cases
> for it in t0060.
> 
> Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
> Helped-by: Johannes Sixt <j6t@kdbg.org>
> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
> ---
>  path.c                | 20 ++++++++++++++++++++
>  t/t0060-path-utils.sh |  4 ++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/path.c b/path.c
> index 7f3324a..ffcdea1 100644
> --- a/path.c
> +++ b/path.c
> @@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)
>  	return 0;
>  }
>  
> +static int have_same_root(const char *path1, const char *path2)
> +{
> +	int is_abs1, is_abs2;
> +
> +	is_abs1 = is_absolute_path(path1);
> +	is_abs2 = is_absolute_path(path2);
> +	return (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||
                                       ^^^^^^^^^^^
I wonder: should strncasecmp() be replaced with strncmp_icase() ?

See dir.c: 
int strncmp_icase(const char *a, const char *b, size_t count)
{
	return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
}
/Torsten











> +	       (!is_abs1 && !is_abs2);
> +}
> +
>  /*
>   * Give path as relative to prefix.
>   *
> @@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,
>  	else if (!prefix_len)
>  		return in;
>  
> +	if (have_same_root(in, prefix)) {
> +		/* bypass dos_drive, for "c:" is identical to "C:" */
> +		if (has_dos_drive_prefix(in)) {
> +			i = 2;
> +			j = 2;
> +		}
> +	} else {
> +		return in;
> +	}
> +
>  	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
>  		if (is_dir_sep(prefix[i])) {
>  			while (is_dir_sep(prefix[i]))
> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
> index 76c7792..c3c3b33 100755
> --- a/t/t0060-path-utils.sh
> +++ b/t/t0060-path-utils.sh
> @@ -208,6 +208,10 @@ relative_path a/b/	a/b		./
>  relative_path a		a/b		../
>  relative_path x/y	a/b		../../x/y
>  relative_path a/c	a/b		../c
> +relative_path a/b	/x/y		a/b
> +relative_path /a/b	x/y		/a/b	POSIX
> +relative_path d:/a/b	D:/a/c		../b	MINGW
> +relative_path C:/a/b	D:/a/c		C:/a/b	MINGW
>  relative_path a/b	"<empty>"	a/b
>  relative_path a/b 	"<null>"	a/b
>  relative_path "<empty>"	/a/b		./
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-12  9:12   ` [PATCH 1/2] relative_path should honor dos_drive_prefix Jiang Xin
  2013-09-12  9:32     ` Tvangeste
  2013-09-12 14:13     ` Torsten Bögershausen
@ 2013-09-12 15:45     ` Karsten Blees
  2 siblings, 0 replies; 56+ messages in thread
From: Karsten Blees @ 2013-09-12 15:45 UTC (permalink / raw)
  To: Jiang Xin; +Cc: Junio C Hamano, Git List, Tvangeste, Johannes Sixt

Am 12.09.2013 11:12, schrieb Jiang Xin:
> Tvangeste found that the "relative_path" function could not work
> properly on Windows if "in" and "prefix" have dos driver prefix.
> ($gmane/234434)
> 
> e.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
> should return "C:/a/b", but returns "../../C:/a/b", which is wrong.
> 
> So make relative_path honor dos_drive_prefix, and add test cases
> for it in t0060.
> 

I still don't think that cd'ing through the root is a Good Thing for absolute paths, as it is not possible to do so in general.

POSIX says the meaning of '//' is implementation-defined [1].

Cygwin supports //hostname/share/directory/file. You cannot cd to the hostname (i.e. root would be //hostname/share).

On Windows, we have drive letters, UNC paths and namespaces:
C:\directory\file
\\hostname\share\directory\file (same as cygwin)
\\?\C:\directory\file
\\?\UNC\hostname\share\directory\file

I'm not sure about '//' support on other git platforms (the most likely candidate would probably be HP-UX, as HP bought Apollo/DomainOS, which supported '//hostname/directory/file back in 1981).


You could of course handle all these special cases. However, with the POSIX definition above, the only reliable and future-proof way to check if we can cd out of a path component of an _absolute_ path is to actually try it until we get an error. And we probably don't want to do actual IO in relative_path (which is pure string manipulation so far).

[1] http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_12

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-12 14:13     ` Torsten Bögershausen
@ 2013-09-12 15:48       ` Junio C Hamano
  2013-09-12 17:22       ` Johannes Sixt
  1 sibling, 0 replies; 56+ messages in thread
From: Junio C Hamano @ 2013-09-12 15:48 UTC (permalink / raw)
  To: Torsten Bögershausen
  Cc: Jiang Xin, Git List, Tvangeste, Johannes Sixt, Karsten Blees

Torsten Bögershausen <tboegi@web.de> writes:

>> +static int have_same_root(const char *path1, const char *path2)
>> +{
>> +	int is_abs1, is_abs2;
>> +
>> +	is_abs1 = is_absolute_path(path1);
>> +	is_abs2 = is_absolute_path(path2);
>> +	return (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||
>                                        ^^^^^^^^^^^
> I wonder: should strncasecmp() be replaced with strncmp_icase() ?

True.

> See dir.c: 
> int strncmp_icase(const char *a, const char *b, size_t count)
> {
> 	return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
> }

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-12 14:13     ` Torsten Bögershausen
  2013-09-12 15:48       ` Junio C Hamano
@ 2013-09-12 17:22       ` Johannes Sixt
  2013-09-12 19:11         ` Junio C Hamano
  1 sibling, 1 reply; 56+ messages in thread
From: Johannes Sixt @ 2013-09-12 17:22 UTC (permalink / raw)
  To: Torsten Bögershausen
  Cc: Jiang Xin, Junio C Hamano, Git List, Tvangeste, Karsten Blees

Am 12.09.2013 16:13, schrieb Torsten Bögershausen:
> On 2013-09-12 11.12, Jiang Xin wrote:
>> +static int have_same_root(const char *path1, const char *path2)
>> +{
>> +	int is_abs1, is_abs2;
>> +
>> +	is_abs1 = is_absolute_path(path1);
>> +	is_abs2 = is_absolute_path(path2);
>> +	return (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||
>                                        ^^^^^^^^^^^
> I wonder: should strncasecmp() be replaced with strncmp_icase() ?

I don't think so: On POSIX, it is irrelevant, because the call will only
compare a slash to a slash. On Windows, it compares the drive letters
(or a slash); it is *always* case-insensitive, even if the volume
mounted is NTFS with case-sensitivity enabled and core.ignorecase is false.

> See dir.c: 
> int strncmp_icase(const char *a, const char *b, size_t count)
> {
> 	return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
> }

-- Hannes

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 2/2] Use simpler relative_path when set_git_dir
  2013-09-12  9:12   ` [PATCH 2/2] Use simpler relative_path when set_git_dir Jiang Xin
@ 2013-09-12 17:36     ` Johannes Sixt
  0 siblings, 0 replies; 56+ messages in thread
From: Johannes Sixt @ 2013-09-12 17:36 UTC (permalink / raw)
  To: Jiang Xin; +Cc: Junio C Hamano, Git List, Tvangeste, Karsten Blees

Am 12.09.2013 11:12, schrieb Jiang Xin:
> Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.
> It will make git_dir shorter only if git_dir is inside work_tree,
> and this will increase performance. But my last refactor effort on
> relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.
> Always use relative_path as git_dir may bring troubles like
> $gmane/234434.
> 
> Because new relative_path is a combination of original relative_path
> from path.c and original path_relative from quote.c, so in order to
> restore the origin implementation, save the original relative_path
> to simple_relative_path, and call it in setup.c.
> 
> Suggested-by: Karsten Blees <karsten.blees@gmail.com>
> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
> ---
>  cache.h |  1 +
>  path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  setup.c |  5 +----
>  3 files changed, 47 insertions(+), 4 deletions(-)
> 
> diff --git a/cache.h b/cache.h
> index 8e42256..ab17f1d 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -738,6 +738,7 @@ const char *real_path(const char *path);
>  const char *real_path_if_valid(const char *path);
>  const char *absolute_path(const char *path);
>  const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
> +const char *simple_relative_path(const char *in, const char *prefix);
>  int normalize_path_copy(char *dst, const char *src);
>  int longest_ancestor_length(const char *path, struct string_list *prefixes);
>  char *strip_path_suffix(const char *path, const char *suffix);
> diff --git a/path.c b/path.c
> index ffcdea1..0f0c92f 100644
> --- a/path.c
> +++ b/path.c
> @@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,
>  }
>  
>  /*
> + * A simpler implementation of relative_path

So we have a heavy-duty function relative_path(), but it is not capable
of doing the "simple" operations that this function does?

There must be something wrong.

This function were easier to sell if it were named
remove_optional_prefix() or something.

> + *
> + * Get relative path by removing "prefix" from "in". This function
> + * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
> + * to increase performance when traversing the path to work_tree.
> + */
> +const char *simple_relative_path(const char *in, const char *prefix)
> +{
> +	static char buf[PATH_MAX + 1];
> +	int i = 0, j = 0;
> +
> +	if (!prefix || !prefix[0])
> +		return in;
> +	while (prefix[i]) {
> +		if (is_dir_sep(prefix[i])) {
> +			if (!is_dir_sep(in[j]))
> +				return in;
> +			while (is_dir_sep(prefix[i]))
> +				i++;
> +			while (is_dir_sep(in[j]))
> +				j++;
> +			continue;
> +		} else if (in[j] != prefix[i]) {
> +			return in;
> +		}
> +		i++;
> +		j++;
> +	}
> +	if (
> +	    /* "/foo" is a prefix of "/foo" */
> +	    in[j] &&
> +	    /* "/foo" is not a prefix of "/foobar" */
> +	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
> +	   )
> +		return in;
> +	while (is_dir_sep(in[j]))
> +		j++;
> +	if (!in[j])
> +		strcpy(buf, ".");
> +	else
> +		strcpy(buf, in + j);
> +	return buf;
> +}
> ...

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-12 17:22       ` Johannes Sixt
@ 2013-09-12 19:11         ` Junio C Hamano
  2013-09-13  4:55           ` Jiang Xin
  0 siblings, 1 reply; 56+ messages in thread
From: Junio C Hamano @ 2013-09-12 19:11 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Torsten Bögershausen, Jiang Xin, Git List, Tvangeste,
	Karsten Blees

Johannes Sixt <j6t@kdbg.org> writes:

> Am 12.09.2013 16:13, schrieb Torsten Bögershausen:
>> On 2013-09-12 11.12, Jiang Xin wrote:
>>> +static int have_same_root(const char *path1, const char *path2)
>>> +{
>>> +	int is_abs1, is_abs2;
>>> +
>>> +	is_abs1 = is_absolute_path(path1);
>>> +	is_abs2 = is_absolute_path(path2);
>>> +	return (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||
>>                                        ^^^^^^^^^^^
>> I wonder: should strncasecmp() be replaced with strncmp_icase() ?
>
> I don't think so: On POSIX, it is irrelevant, because the call will only
> compare a slash to a slash. On Windows, it compares the drive letters
> (or a slash); it is *always* case-insensitive, even if the volume
> mounted is NTFS with case-sensitivity enabled and core.ignorecase is false.

Ah, you are right, of course.  We could even do

	tolower(path1[0]) == tolower(path2[0])

which might be more explicit.

For systems that need POSIX escape hatch for Apollo Domain ;-), we
would need a bit more work.  When both path1 and path2 begin with a
double-dash, we would need to check if they match up to the next
slash, so that

 - //host1/usr/src and //host1/usr/lib share the same root and the
   former can be made to ../src relative to the latter;

 - //host1/usr/src and //host2/usr/lib are of separate roots.

or something.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-12 19:11         ` Junio C Hamano
@ 2013-09-13  4:55           ` Jiang Xin
  2013-09-13  5:53             ` Junio C Hamano
  2013-09-13 13:59             ` [PATCH 1/2] relative_path should honor dos_drive_prefix Torsten Bögershausen
  0 siblings, 2 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-13  4:55 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Sixt, Torsten Bögershausen, Git List, Tvangeste,
	Karsten Blees

2013/9/13 Junio C Hamano <gitster@pobox.com>:
>
> For systems that need POSIX escape hatch for Apollo Domain ;-), we
> would need a bit more work.  When both path1 and path2 begin with a
> double-dash, we would need to check if they match up to the next
> slash, so that
>
>  - //host1/usr/src and //host1/usr/lib share the same root and the
>    former can be made to ../src relative to the latter;
>
>  - //host1/usr/src and //host2/usr/lib are of separate roots.
>
> or something.
>
>

But how could we know which platform supports network pathnames and
needs such implementation.

-- 
Jiang Xin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v2 0/3] fixes for relative_path
  2013-09-10 17:06 ` Junio C Hamano
                     ` (3 preceding siblings ...)
  2013-09-12  9:12   ` [PATCH 2/2] Use simpler relative_path when set_git_dir Jiang Xin
@ 2013-09-13  5:08   ` Jiang Xin
  2013-09-13  5:08   ` [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-13  5:08 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Updates since v1:

* New patch 1/3 on t0060, which use umambigous leading path (/foo).
* Call tolower instead of strncasecmp in patch 2/3.
* Rename simple_relative_path to remove_leading_path in patch 3/3.

Jiang Xin (3):
  test: use unambigous leading path (/foo) for mingw
  relative_path should honor dos_drive_prefix
  Use simpler relative_path when set_git_dir

 cache.h               |  1 +
 path.c                | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++
 setup.c               |  5 +---
 t/t0060-path-utils.sh | 60 +++++++++++++++++++++++++----------------------
 4 files changed, 99 insertions(+), 32 deletions(-)

-- 
1.8.4.459.gd80d422

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw
  2013-09-10 17:06 ` Junio C Hamano
                     ` (4 preceding siblings ...)
  2013-09-13  5:08   ` [PATCH v2 0/3] fixes for relative_path Jiang Xin
@ 2013-09-13  5:08   ` Jiang Xin
  2013-09-13 19:51     ` Junio C Hamano
  2013-09-13  5:08   ` [PATCH v2 2/3] relative_path should honor dos_drive_prefix Jiang Xin
  2013-09-13  5:08   ` [PATCH v2 3/3] Use simpler relative_path when set_git_dir Jiang Xin
  7 siblings, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-13  5:08 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

In test cases for relative_path, path with one leading character
(such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
such doc drive on MINGW platform. Use an umambigous leading path
"/foo" instead.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 3a48de2..82a6f21 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
 	test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
 '
 
-relative_path /a/b/c/	/a/b/		c/
-relative_path /a/b/c/	/a/b		c/
-relative_path /a//b//c/	//a/b//		c/	POSIX
-relative_path /a/b	/a/b		./
-relative_path /a/b/	/a/b		./
-relative_path /a	/a/b		../
-relative_path /		/a/b/		../../
-relative_path /a/c	/a/b/		../c
-relative_path /a/c	/a/b		../c
-relative_path /x/y	/a/b/		../../x/y
-relative_path /a/b	"<empty>"	/a/b
-relative_path /a/b 	"<null>"	/a/b
-relative_path a/b/c/	a/b/		c/
-relative_path a/b/c/	a/b		c/
-relative_path a/b//c	a//b		c
-relative_path a/b/	a/b/		./
-relative_path a/b/	a/b		./
-relative_path a		a/b		../
-relative_path x/y	a/b		../../x/y
-relative_path a/c	a/b		../c
-relative_path a/b	"<empty>"	a/b
-relative_path a/b 	"<null>"	a/b
-relative_path "<empty>"	/a/b		./
-relative_path "<empty>"	"<empty>"	./
-relative_path "<empty>"	"<null>"	./
-relative_path "<null>"	"<empty>"	./
-relative_path "<null>"	"<null>"	./
-relative_path "<null>"	/a/b		./
+relative_path /foo/a/b/c/	/foo/a/b/	c/
+relative_path /foo/a/b/c/	/foo/a/b	c/
+relative_path /foo/a//b//c/	//foo/a/b//	c/		POSIX
+relative_path /foo/a/b		/foo/a/b	./
+relative_path /foo/a/b/		/foo/a/b	./
+relative_path /foo/a		/foo/a/b	../
+relative_path /			/foo/a/b/	../../../
+relative_path /foo/a/c		/foo/a/b/	../c
+relative_path /foo/a/c		/foo/a/b	../c
+relative_path /foo/x/y		/foo/a/b/	../../x/y
+relative_path /foo/a/b		"<empty>"	/foo/a/b
+relative_path /foo/a/b 		"<null>"	/foo/a/b
+relative_path foo/a/b/c/	foo/a/b/	c/
+relative_path foo/a/b/c/	foo/a/b		c/
+relative_path foo/a/b//c	foo/a//b	c
+relative_path foo/a/b/		foo/a/b/	./
+relative_path foo/a/b/		foo/a/b		./
+relative_path foo/a		foo/a/b		../
+relative_path foo/x/y		foo/a/b		../../x/y
+relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		"<empty>"	foo/a/b
+relative_path foo/a/b 		"<null>"	foo/a/b
+relative_path "<empty>"		/foo/a/b	./
+relative_path "<empty>"		"<empty>"	./
+relative_path "<empty>"		"<null>"	./
+relative_path "<null>"		"<empty>"	./
+relative_path "<null>"		"<null>"	./
+relative_path "<null>"		/foo/a/b	./
 
 test_done
-- 
1.8.4.459.gd80d422

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 2/3] relative_path should honor dos_drive_prefix
  2013-09-10 17:06 ` Junio C Hamano
                     ` (5 preceding siblings ...)
  2013-09-13  5:08   ` [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
@ 2013-09-13  5:08   ` Jiang Xin
  2013-09-14  6:11     ` Torsten Bögershausen
  2013-09-13  5:08   ` [PATCH v2 3/3] Use simpler relative_path when set_git_dir Jiang Xin
  7 siblings, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-13  5:08 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Tvangeste found that the "relative_path" function could not work
properly on Windows if "in" and "prefix" have dos driver prefix.
($gmane/234434)

e.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
should return "C:/a/b", but returns "../../C:/a/b", which is wrong.

So make relative_path honor dos_drive_prefix, and add test cases
for it in t0060.

Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 path.c                | 20 ++++++++++++++++++++
 t/t0060-path-utils.sh |  4 ++++
 2 files changed, 24 insertions(+)

diff --git a/path.c b/path.c
index 9fd28bcd..65d376d 100644
--- a/path.c
+++ b/path.c
@@ -434,6 +434,16 @@ int adjust_shared_perm(const char *path)
 	return 0;
 }
 
+static int have_same_root(const char *path1, const char *path2)
+{
+	int is_abs1, is_abs2;
+
+	is_abs1 = is_absolute_path(path1);
+	is_abs2 = is_absolute_path(path2);
+	return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
+	       (!is_abs1 && !is_abs2);
+}
+
 /*
  * Give path as relative to prefix.
  *
@@ -454,6 +464,16 @@ const char *relative_path(const char *in, const char *prefix,
 	else if (!prefix_len)
 		return in;
 
+	if (have_same_root(in, prefix)) {
+		/* bypass dos_drive, for "c:" is identical to "C:" */
+		if (has_dos_drive_prefix(in)) {
+			i = 2;
+			j = 2;
+		}
+	} else {
+		return in;
+	}
+
 	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
 		if (is_dir_sep(prefix[i])) {
 			while (is_dir_sep(prefix[i]))
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 82a6f21..0187d11 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -210,6 +210,10 @@ relative_path foo/a/b/		foo/a/b		./
 relative_path foo/a		foo/a/b		../
 relative_path foo/x/y		foo/a/b		../../x/y
 relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		/foo/x/y	foo/a/b
+relative_path /foo/a/b		foo/x/y		/foo/a/b
+relative_path d:/a/b		D:/a/c		../b		MINGW
+relative_path C:/a/b		D:/a/c		C:/a/b		MINGW
 relative_path foo/a/b		"<empty>"	foo/a/b
 relative_path foo/a/b 		"<null>"	foo/a/b
 relative_path "<empty>"		/foo/a/b	./
-- 
1.8.4.459.gd80d422

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 3/3] Use simpler relative_path when set_git_dir
  2013-09-10 17:06 ` Junio C Hamano
                     ` (6 preceding siblings ...)
  2013-09-13  5:08   ` [PATCH v2 2/3] relative_path should honor dos_drive_prefix Jiang Xin
@ 2013-09-13  5:08   ` Jiang Xin
  7 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-13  5:08 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.
It will make git_dir shorter only if git_dir is inside work_tree,
and this will increase performance. But my last refactor effort on
relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.
Always use relative_path as git_dir may bring troubles like
$gmane/234434.

Because new relative_path is a combination of original relative_path
from path.c and original path_relative from quote.c, so in order to
restore the origin implementation, save the original relative_path
as remove_leading_path, and call it in setup.c.

Suggested-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 cache.h |  1 +
 path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 setup.c |  5 +----
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index a47b9c0..73fa334 100644
--- a/cache.h
+++ b/cache.h
@@ -747,6 +747,7 @@ int is_directory(const char *);
 const char *real_path(const char *path);
 const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
+const char *remove_leading_path(const char *in, const char *prefix);
 const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
 int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
 int normalize_path_copy(char *dst, const char *src);
diff --git a/path.c b/path.c
index 65d376d..24594c4 100644
--- a/path.c
+++ b/path.c
@@ -551,6 +551,51 @@ const char *relative_path(const char *in, const char *prefix,
 }
 
 /*
+ * A simpler implementation of relative_path
+ *
+ * Get relative path by removing "prefix" from "in". This function
+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
+ * to increase performance when traversing the path to work_tree.
+ */
+const char *remove_leading_path(const char *in, const char *prefix)
+{
+	static char buf[PATH_MAX + 1];
+	int i = 0, j = 0;
+
+	if (!prefix || !prefix[0])
+		return in;
+	while (prefix[i]) {
+		if (is_dir_sep(prefix[i])) {
+			if (!is_dir_sep(in[j]))
+				return in;
+			while (is_dir_sep(prefix[i]))
+				i++;
+			while (is_dir_sep(in[j]))
+				j++;
+			continue;
+		} else if (in[j] != prefix[i]) {
+			return in;
+		}
+		i++;
+		j++;
+	}
+	if (
+	    /* "/foo" is a prefix of "/foo" */
+	    in[j] &&
+	    /* "/foo" is not a prefix of "/foobar" */
+	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
+	   )
+		return in;
+	while (is_dir_sep(in[j]))
+		j++;
+	if (!in[j])
+		strcpy(buf, ".");
+	else
+		strcpy(buf, in + j);
+	return buf;
+}
+
+/*
  * It is okay if dst == src, but they should not overlap otherwise.
  *
  * Performs the following normalizations on src, storing the result in dst:
diff --git a/setup.c b/setup.c
index f08dd64..dbf4138 100644
--- a/setup.c
+++ b/setup.c
@@ -227,7 +227,6 @@ int is_inside_work_tree(void)
 
 void setup_work_tree(void)
 {
-	struct strbuf sb = STRBUF_INIT;
 	const char *work_tree, *git_dir;
 	static int initialized = 0;
 
@@ -247,10 +246,8 @@ void setup_work_tree(void)
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
 		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
-	set_git_dir(relative_path(git_dir, work_tree, &sb));
+	set_git_dir(remove_leading_path(git_dir, work_tree));
 	initialized = 1;
-
-	strbuf_release(&sb);
 }
 
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
-- 
1.8.4.459.gd80d422

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-13  4:55           ` Jiang Xin
@ 2013-09-13  5:53             ` Junio C Hamano
  2013-09-17  8:24               ` Jiang Xin
  2013-09-13 13:59             ` [PATCH 1/2] relative_path should honor dos_drive_prefix Torsten Bögershausen
  1 sibling, 1 reply; 56+ messages in thread
From: Junio C Hamano @ 2013-09-13  5:53 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Johannes Sixt, Torsten Bögershausen, Git List, Tvangeste,
	Karsten Blees

Jiang Xin <worldhello.net@gmail.com> writes:

> 2013/9/13 Junio C Hamano <gitster@pobox.com>:
>>
>> For systems that need POSIX escape hatch for Apollo Domain ;-), we
>> would need a bit more work.  When both path1 and path2 begin with a
>> double-dash, we would need to check if they match up to the next
>> slash, so that
>>
>>  - //host1/usr/src and //host1/usr/lib share the same root and the
>>    former can be made to ../src relative to the latter;
>>
>>  - //host1/usr/src and //host2/usr/lib are of separate roots.
>>
>> or something.
>
> But how could we know which platform supports network pathnames and
> needs such implementation.

Near the end of

http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12

is this:

    If a pathname begins with two successive <slash> characters, the
    first component following the leading <slash> characters may be
    interpreted in an implementation-defined manner, although more than
    two leading <slash> characters shall be treated as a single <slash>
    character.

Two points to note are

 (1) Only paths that begin with exactly two slashes are special.

 (2) As it is "implementation-defined", we are not even allowed to
     treat that //host1/usr/src and //host1/usr/lib as sharing "the
     same root", and make the former to ../src relative to the
     latter.

So in the strictest sense, we do not have to bother. As long as we
make sure we do not molest anything that begins with exactly two
slashes.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-13  4:55           ` Jiang Xin
  2013-09-13  5:53             ` Junio C Hamano
@ 2013-09-13 13:59             ` Torsten Bögershausen
  1 sibling, 0 replies; 56+ messages in thread
From: Torsten Bögershausen @ 2013-09-13 13:59 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Junio C Hamano, Johannes Sixt, Git List, Tvangeste, Karsten Blees

On 13.09.13 06:55, Jiang Xin wrote:
> 2013/9/13 Junio C Hamano <gitster@pobox.com>:
>> For systems that need POSIX escape hatch for Apollo Domain ;-), we
>> would need a bit more work.  When both path1 and path2 begin with a
>> double-dash, we would need to check if they match up to the next
>> slash, so that
>>
>>  - //host1/usr/src and //host1/usr/lib share the same root and the
>>    former can be made to ../src relative to the latter;
>>
>>  - //host1/usr/src and //host2/usr/lib are of separate roots.
>>
>> or something.
>>
>>
> But how could we know which platform supports network pathnames and
> needs such implementation.
Similar to the has_dos_drive_prefix:

For Windows/Mingw we do like this

mingw.h
#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')

And all other platforms defines has_dos_drive_prefix() to be 0 here
git-compat-util.h
#ifndef has_dos_drive_prefix
#define has_dos_drive_prefix(path) 0
#endif

mingw.h:
#define has_unc_path_prefix(path) ((path)[0] == '/' && (path)[1] == '/')
(Or may be)
#define has_unc_path_prefix(path) (is_dir_sep((path)[0])   && is_dir_sep((path)[1]))
 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw
  2013-09-13  5:08   ` [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
@ 2013-09-13 19:51     ` Junio C Hamano
  2013-09-14  6:52       ` Torsten Bögershausen
  0 siblings, 1 reply; 56+ messages in thread
From: Junio C Hamano @ 2013-09-13 19:51 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

Jiang Xin <worldhello.net@gmail.com> writes:

> In test cases for relative_path, path with one leading character
> (such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
> such doc drive on MINGW platform. Use an umambigous leading path
> "/foo" instead.

"DOS drive", you mean?

Are they really spelled as /a or /x (not e.g. //a or something)?

Just double-checking.

> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
> ---
>  t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------
>  1 file changed, 28 insertions(+), 28 deletions(-)
>
> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
> index 3a48de2..82a6f21 100755
> --- a/t/t0060-path-utils.sh
> +++ b/t/t0060-path-utils.sh
> @@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
>  	test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
>  '
>  
> -relative_path /a/b/c/	/a/b/		c/
> -relative_path /a/b/c/	/a/b		c/
> -relative_path /a//b//c/	//a/b//		c/	POSIX
> -relative_path /a/b	/a/b		./
> -relative_path /a/b/	/a/b		./
> -relative_path /a	/a/b		../
> -relative_path /		/a/b/		../../
> -relative_path /a/c	/a/b/		../c
> -relative_path /a/c	/a/b		../c
> -relative_path /x/y	/a/b/		../../x/y
> -relative_path /a/b	"<empty>"	/a/b
> -relative_path /a/b 	"<null>"	/a/b
> -relative_path a/b/c/	a/b/		c/
> -relative_path a/b/c/	a/b		c/
> -relative_path a/b//c	a//b		c
> -relative_path a/b/	a/b/		./
> -relative_path a/b/	a/b		./
> -relative_path a		a/b		../
> -relative_path x/y	a/b		../../x/y
> -relative_path a/c	a/b		../c
> -relative_path a/b	"<empty>"	a/b
> -relative_path a/b 	"<null>"	a/b
> -relative_path "<empty>"	/a/b		./
> -relative_path "<empty>"	"<empty>"	./
> -relative_path "<empty>"	"<null>"	./
> -relative_path "<null>"	"<empty>"	./
> -relative_path "<null>"	"<null>"	./
> -relative_path "<null>"	/a/b		./
> +relative_path /foo/a/b/c/	/foo/a/b/	c/
> +relative_path /foo/a/b/c/	/foo/a/b	c/
> +relative_path /foo/a//b//c/	//foo/a/b//	c/		POSIX
> +relative_path /foo/a/b		/foo/a/b	./
> +relative_path /foo/a/b/		/foo/a/b	./
> +relative_path /foo/a		/foo/a/b	../
> +relative_path /			/foo/a/b/	../../../
> +relative_path /foo/a/c		/foo/a/b/	../c
> +relative_path /foo/a/c		/foo/a/b	../c
> +relative_path /foo/x/y		/foo/a/b/	../../x/y
> +relative_path /foo/a/b		"<empty>"	/foo/a/b
> +relative_path /foo/a/b 		"<null>"	/foo/a/b
> +relative_path foo/a/b/c/	foo/a/b/	c/
> +relative_path foo/a/b/c/	foo/a/b		c/
> +relative_path foo/a/b//c	foo/a//b	c
> +relative_path foo/a/b/		foo/a/b/	./
> +relative_path foo/a/b/		foo/a/b		./
> +relative_path foo/a		foo/a/b		../
> +relative_path foo/x/y		foo/a/b		../../x/y
> +relative_path foo/a/c		foo/a/b		../c
> +relative_path foo/a/b		"<empty>"	foo/a/b
> +relative_path foo/a/b 		"<null>"	foo/a/b
> +relative_path "<empty>"		/foo/a/b	./
> +relative_path "<empty>"		"<empty>"	./
> +relative_path "<empty>"		"<null>"	./
> +relative_path "<null>"		"<empty>"	./
> +relative_path "<null>"		"<null>"	./
> +relative_path "<null>"		/foo/a/b	./
>  
>  test_done

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 2/3] relative_path should honor dos_drive_prefix
  2013-09-13  5:08   ` [PATCH v2 2/3] relative_path should honor dos_drive_prefix Jiang Xin
@ 2013-09-14  6:11     ` Torsten Bögershausen
  0 siblings, 0 replies; 56+ messages in thread
From: Torsten Bögershausen @ 2013-09-14  6:11 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Junio C Hamano, Git List, Tvangeste, Johannes Sixt, Karsten Blees

On 13.09.13 07:08, Jiang Xin wrote:
> Tvangeste found that the "relative_path" function could not work
> properly on Windows if "in" and "prefix" have dos driver prefix.
> ($gmane/234434)
>
> e.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
> should return "C:/a/b", but returns "../../C:/a/b", which is wrong.
>
> So make relative_path honor dos_drive_prefix, and add test cases
> for it in t0060.
>
> Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
> Helped-by: Johannes Sixt <j6t@kdbg.org>
> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
> ---
>  path.c                | 20 ++++++++++++++++++++
>  t/t0060-path-utils.sh |  4 ++++
>  2 files changed, 24 insertions(+)
>
> diff --git a/path.c b/path.c
> index 9fd28bcd..65d376d 100644
> --- a/path.c
> +++ b/path.c
> @@ -434,6 +434,16 @@ int adjust_shared_perm(const char *path)
>  	return 0;
>  }
>  
> +static int have_same_root(const char *path1, const char *path2)
> +{
> +	int is_abs1, is_abs2;
> +
> +	is_abs1 = is_absolute_path(path1);
> +	is_abs2 = is_absolute_path(path2);
> +	return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
> +	       (!is_abs1 && !is_abs2);
> +}
> +
I think the name of the fuction is somewhat misleading, as we are not sure if
they really have the same root.
And that is investigated further down.

may_have_same_root() could be a better name.

[snip]

>  	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
>  		if (is_dir_sep(prefix[i])) {
>  			while (is_dir_sep(prefix[i]))
> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
> index 82a6f21..0187d11 100755
> --- a/t/t0060-path-utils.sh
> +++ b/t/t0060-path-utils.sh
> @@ -210,6 +210,10 @@ relative_path foo/a/b/		foo/a/b		./
>  relative_path foo/a		foo/a/b		../
>  relative_path foo/x/y		foo/a/b		../../x/y
>  relative_path foo/a/c		foo/a/b		../c
> +relative_path foo/a/b		/foo/x/y	foo/a/b
> +relative_path /foo/a/b		foo/x/y		/foo/a/b
> +relative_path d:/a/b		D:/a/c		../b		MINGW
> +relative_path C:/a/b		D:/a/c		C:/a/b		MINGW
Side question:
What happens if we feed in a relative path with a dos drive?
like "c:foo" which is different from c:/foo.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw
  2013-09-13 19:51     ` Junio C Hamano
@ 2013-09-14  6:52       ` Torsten Bögershausen
  2013-09-17 16:19         ` Junio C Hamano
  0 siblings, 1 reply; 56+ messages in thread
From: Torsten Bögershausen @ 2013-09-14  6:52 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Jiang Xin, Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

On 2013-09-13 21.51, Junio C Hamano wrote:
> Jiang Xin <worldhello.net@gmail.com> writes:
> 
>> In test cases for relative_path, path with one leading character
>> (such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
>> such doc drive on MINGW platform. Use an umambigous leading path
>> "/foo" instead.
> 
> "DOS drive", you mean?
> 
> Are they really spelled as /a or /x (not e.g. //a or something)?
> 
> Just double-checking.
Yes,
there is a directoctory structure in / like this:

/usr
/bin
/lib
Then we have the drive letters mapped to single letters:
/c/Documents and Settings
/c/temp

As an alternative
c:/temp can be used
or the DOS style
"c:\temp"

And the // or "\\" is used for the UNC names (Universal Name Convention)
//Servername/ShareName/Directory

/Torsten

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-13  5:53             ` Junio C Hamano
@ 2013-09-17  8:24               ` Jiang Xin
  2013-09-17  8:30                 ` [PATCH v3 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
                                   ` (3 more replies)
  0 siblings, 4 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-17  8:24 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Sixt, Torsten Bögershausen, Git List, Tvangeste,
	Karsten Blees

2013/9/13 Junio C Hamano <gitster@pobox.com>:
> Jiang Xin <worldhello.net@gmail.com> writes:
>
>> 2013/9/13 Junio C Hamano <gitster@pobox.com>:
>>>
>>> For systems that need POSIX escape hatch for Apollo Domain ;-), we
>>> would need a bit more work.  When both path1 and path2 begin with a
>>> double-dash, we would need to check if they match up to the next
>>> slash, so that
>>>
>>>  - //host1/usr/src and //host1/usr/lib share the same root and the
>>>    former can be made to ../src relative to the latter;
>>>
>>>  - //host1/usr/src and //host2/usr/lib are of separate roots.
>>>
>>> or something.
>>
>> But how could we know which platform supports network pathnames and
>> needs such implementation.
>
> Near the end of
>
> http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12
>
> is this:
>
>     If a pathname begins with two successive <slash> characters, the
>     first component following the leading <slash> characters may be
>     interpreted in an implementation-defined manner, although more than
>     two leading <slash> characters shall be treated as a single <slash>
>     character.
>
> Two points to note are
>
>  (1) Only paths that begin with exactly two slashes are special.
>
>  (2) As it is "implementation-defined", we are not even allowed to
>      treat that //host1/usr/src and //host1/usr/lib as sharing "the
>      same root", and make the former to ../src relative to the
>      latter.
>
> So in the strictest sense, we do not have to bother. As long as we
> make sure we do not molest anything that begins with exactly two
> slashes.
>

I have checked the behavior of UNC path on Windows (msysGit):

* I can cd to a UNC path:

    cd //server1/share1/path

* can cd to other share:

    cd ../../share2/path

* and can cd to other server's share:

    cd ../../../server2/share/path

That means relative_path(path1, path2) support UNC paths out of the box.
We only need to check both path1 and path2 are UNC paths, or both not.

So, funciton “have_same_root" will write like this:


+static int have_same_root(const char *path1, const char *path2)
+{
+       int is_abs1, is_abs2;
+
+       is_abs1 = is_absolute_path(path1);
+       is_abs2 = is_absolute_path(path2);
+       if (is_abs1 && is_abs2) {
+               if (is_unc_path(path1) ^ is_unc_path(path2))
+                       return 0;
+               return tolower(path1[0]) == tolower(path2[0]);
+       } else {
+               return !is_abs1 && !is_abs2;
+       }
+}


-- 
Jiang Xin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v3 1/3] test: use unambigous leading path (/foo) for mingw
  2013-09-17  8:24               ` Jiang Xin
@ 2013-09-17  8:30                 ` Jiang Xin
  2013-09-17  8:30                 ` [PATCH v3 2/3] relative_path should honor DOS and UNC paths Jiang Xin
                                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-17  8:30 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

In test cases for relative_path, path with one leading character
(such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
such DOS drive on MINGW platform. Use an umambigous leading path
"/foo" instead.

Also change two leading slashes (//) to three leading slashes (///),
otherwize it will be recognized as UNC path on MINGW platform.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 3a48de2..92976e0 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
 	test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
 '
 
-relative_path /a/b/c/	/a/b/		c/
-relative_path /a/b/c/	/a/b		c/
-relative_path /a//b//c/	//a/b//		c/	POSIX
-relative_path /a/b	/a/b		./
-relative_path /a/b/	/a/b		./
-relative_path /a	/a/b		../
-relative_path /		/a/b/		../../
-relative_path /a/c	/a/b/		../c
-relative_path /a/c	/a/b		../c
-relative_path /x/y	/a/b/		../../x/y
-relative_path /a/b	"<empty>"	/a/b
-relative_path /a/b 	"<null>"	/a/b
-relative_path a/b/c/	a/b/		c/
-relative_path a/b/c/	a/b		c/
-relative_path a/b//c	a//b		c
-relative_path a/b/	a/b/		./
-relative_path a/b/	a/b		./
-relative_path a		a/b		../
-relative_path x/y	a/b		../../x/y
-relative_path a/c	a/b		../c
-relative_path a/b	"<empty>"	a/b
-relative_path a/b 	"<null>"	a/b
-relative_path "<empty>"	/a/b		./
-relative_path "<empty>"	"<empty>"	./
-relative_path "<empty>"	"<null>"	./
-relative_path "<null>"	"<empty>"	./
-relative_path "<null>"	"<null>"	./
-relative_path "<null>"	/a/b		./
+relative_path /foo/a/b/c/	/foo/a/b/	c/
+relative_path /foo/a/b/c/	/foo/a/b	c/
+relative_path /foo/a//b//c/	///foo/a/b//	c/		POSIX
+relative_path /foo/a/b		/foo/a/b	./
+relative_path /foo/a/b/		/foo/a/b	./
+relative_path /foo/a		/foo/a/b	../
+relative_path /			/foo/a/b/	../../../
+relative_path /foo/a/c		/foo/a/b/	../c
+relative_path /foo/a/c		/foo/a/b	../c
+relative_path /foo/x/y		/foo/a/b/	../../x/y
+relative_path /foo/a/b		"<empty>"	/foo/a/b
+relative_path /foo/a/b 		"<null>"	/foo/a/b
+relative_path foo/a/b/c/	foo/a/b/	c/
+relative_path foo/a/b/c/	foo/a/b		c/
+relative_path foo/a/b//c	foo/a//b	c
+relative_path foo/a/b/		foo/a/b/	./
+relative_path foo/a/b/		foo/a/b		./
+relative_path foo/a		foo/a/b		../
+relative_path foo/x/y		foo/a/b		../../x/y
+relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		"<empty>"	foo/a/b
+relative_path foo/a/b 		"<null>"	foo/a/b
+relative_path "<empty>"		/foo/a/b	./
+relative_path "<empty>"		"<empty>"	./
+relative_path "<empty>"		"<null>"	./
+relative_path "<null>"		"<empty>"	./
+relative_path "<null>"		"<null>"	./
+relative_path "<null>"		/foo/a/b	./
 
 test_done
-- 
1.8.4.460.g2f083d1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v3 2/3] relative_path should honor DOS and UNC paths
  2013-09-17  8:24               ` Jiang Xin
  2013-09-17  8:30                 ` [PATCH v3 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
@ 2013-09-17  8:30                 ` Jiang Xin
  2013-09-17 16:12                   ` Junio C Hamano
  2013-09-17  8:30                 ` [PATCH v3 3/3] Use simpler relative_path when set_git_dir Jiang Xin
  2013-09-17 19:32                 ` [PATCH 1/2] relative_path should honor dos_drive_prefix Johannes Sixt
  3 siblings, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-17  8:30 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Tvangeste found that the "relative_path" function could not work
properly on Windows if "in" and "prefix" have DOS driver prefix
(such as "C:/windows"). And the "relative_path" function won't
work properly if either "in" or "prefix" is a UNC path (like
"//host/share"). ($gmane/234434)

E.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
should return "C:/a/b", but returns "../../C:/a/b", which is wrong.

So make relative_path honor DOS and UNC paths, and add test cases
for it in t0060.

Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 compat/mingw.h        |  9 +++++++++
 git-compat-util.h     |  4 ++++
 path.c                | 25 +++++++++++++++++++++++++
 t/t0060-path-utils.sh |  8 ++++++++
 4 files changed, 46 insertions(+)

diff --git a/compat/mingw.h b/compat/mingw.h
index bd0a88b..06e9f49 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format
 
 #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
 #define is_dir_sep(c) ((c) == '/' || (c) == '\\')
+static inline int is_unc_path(const char *path)
+{
+	if (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))
+		return 0;
+	for (path += 2; *path; path++)
+		if (is_dir_sep(*path))
+			return 1;
+	return 0;
+}
 static inline char *mingw_find_last_dir_sep(const char *path)
 {
 	char *ret = NULL;
diff --git a/git-compat-util.h b/git-compat-util.h
index 9549de6..93c2206 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -274,6 +274,10 @@ extern char *gitbasename(char *);
 #define is_dir_sep(c) ((c) == '/')
 #endif
 
+#ifndef is_unc_path
+#define is_unc_path(path) 0
+#endif
+
 #ifndef find_last_dir_sep
 #define find_last_dir_sep(path) strrchr(path, '/')
 #endif
diff --git a/path.c b/path.c
index 9fd28bcd..544d10d 100644
--- a/path.c
+++ b/path.c
@@ -434,6 +434,21 @@ int adjust_shared_perm(const char *path)
 	return 0;
 }
 
+static int have_same_root(const char *path1, const char *path2)
+{
+	int is_abs1, is_abs2;
+
+	is_abs1 = is_absolute_path(path1);
+	is_abs2 = is_absolute_path(path2);
+	if (is_abs1 && is_abs2) {
+		if (is_unc_path(path1) ^ is_unc_path(path2))
+			return 0;
+		return tolower(path1[0]) == tolower(path2[0]);
+	} else {
+		return !is_abs1 && !is_abs2;
+	}
+}
+
 /*
  * Give path as relative to prefix.
  *
@@ -454,6 +469,16 @@ const char *relative_path(const char *in, const char *prefix,
 	else if (!prefix_len)
 		return in;
 
+	if (have_same_root(in, prefix)) {
+		/* bypass dos_drive, for "c:" is identical to "C:" */
+		if (has_dos_drive_prefix(in)) {
+			i = 2;
+			j = 2;
+		}
+	} else {
+		return in;
+	}
+
 	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
 		if (is_dir_sep(prefix[i])) {
 			while (is_dir_sep(prefix[i]))
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 92976e0..830b6d5 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -210,6 +210,14 @@ relative_path foo/a/b/		foo/a/b		./
 relative_path foo/a		foo/a/b		../
 relative_path foo/x/y		foo/a/b		../../x/y
 relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		/foo/x/y	foo/a/b
+relative_path /foo/a/b		foo/x/y		/foo/a/b
+relative_path d:/a/b		D:/a/c		../b		MINGW
+relative_path C:/a/b		D:/a/c		C:/a/b		MINGW
+relative_path //host1/a/b	//host1/a/c	../b
+relative_path //host1/a/b	//host2/a/c	../../../host1/a/b
+relative_path //host1/a/b	/foo/a/c	//host1/a/b	MINGW
+relative_path /foo/a/b		//host2/a/c	/foo/a/b	MINGW
 relative_path foo/a/b		"<empty>"	foo/a/b
 relative_path foo/a/b 		"<null>"	foo/a/b
 relative_path "<empty>"		/foo/a/b	./
-- 
1.8.4.460.g2f083d1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v3 3/3] Use simpler relative_path when set_git_dir
  2013-09-17  8:24               ` Jiang Xin
  2013-09-17  8:30                 ` [PATCH v3 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
  2013-09-17  8:30                 ` [PATCH v3 2/3] relative_path should honor DOS and UNC paths Jiang Xin
@ 2013-09-17  8:30                 ` Jiang Xin
  2013-09-17 19:32                 ` [PATCH 1/2] relative_path should honor dos_drive_prefix Johannes Sixt
  3 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-17  8:30 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.
It will make git_dir shorter only if git_dir is inside work_tree,
and this will increase performance. But my last refactor effort on
relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.
Always use relative_path as git_dir may bring troubles like
$gmane/234434.

Because new relative_path is a combination of original relative_path
from path.c and original path_relative from quote.c, so in order to
restore the origin implementation, save the original relative_path
as remove_leading_path, and call it in setup.c.

Suggested-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 cache.h |  1 +
 path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 setup.c |  5 +----
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index a47b9c0..73fa334 100644
--- a/cache.h
+++ b/cache.h
@@ -747,6 +747,7 @@ int is_directory(const char *);
 const char *real_path(const char *path);
 const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
+const char *remove_leading_path(const char *in, const char *prefix);
 const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
 int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
 int normalize_path_copy(char *dst, const char *src);
diff --git a/path.c b/path.c
index 544d10d..5ad3554 100644
--- a/path.c
+++ b/path.c
@@ -556,6 +556,51 @@ const char *relative_path(const char *in, const char *prefix,
 }
 
 /*
+ * A simpler implementation of relative_path
+ *
+ * Get relative path by removing "prefix" from "in". This function
+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
+ * to increase performance when traversing the path to work_tree.
+ */
+const char *remove_leading_path(const char *in, const char *prefix)
+{
+	static char buf[PATH_MAX + 1];
+	int i = 0, j = 0;
+
+	if (!prefix || !prefix[0])
+		return in;
+	while (prefix[i]) {
+		if (is_dir_sep(prefix[i])) {
+			if (!is_dir_sep(in[j]))
+				return in;
+			while (is_dir_sep(prefix[i]))
+				i++;
+			while (is_dir_sep(in[j]))
+				j++;
+			continue;
+		} else if (in[j] != prefix[i]) {
+			return in;
+		}
+		i++;
+		j++;
+	}
+	if (
+	    /* "/foo" is a prefix of "/foo" */
+	    in[j] &&
+	    /* "/foo" is not a prefix of "/foobar" */
+	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
+	   )
+		return in;
+	while (is_dir_sep(in[j]))
+		j++;
+	if (!in[j])
+		strcpy(buf, ".");
+	else
+		strcpy(buf, in + j);
+	return buf;
+}
+
+/*
  * It is okay if dst == src, but they should not overlap otherwise.
  *
  * Performs the following normalizations on src, storing the result in dst:
diff --git a/setup.c b/setup.c
index f08dd64..dbf4138 100644
--- a/setup.c
+++ b/setup.c
@@ -227,7 +227,6 @@ int is_inside_work_tree(void)
 
 void setup_work_tree(void)
 {
-	struct strbuf sb = STRBUF_INIT;
 	const char *work_tree, *git_dir;
 	static int initialized = 0;
 
@@ -247,10 +246,8 @@ void setup_work_tree(void)
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
 		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
-	set_git_dir(relative_path(git_dir, work_tree, &sb));
+	set_git_dir(remove_leading_path(git_dir, work_tree));
 	initialized = 1;
-
-	strbuf_release(&sb);
 }
 
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
-- 
1.8.4.460.g2f083d1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
  2013-09-17  8:30                 ` [PATCH v3 2/3] relative_path should honor DOS and UNC paths Jiang Xin
@ 2013-09-17 16:12                   ` Junio C Hamano
  2013-09-18  9:02                     ` Jiang Xin
       [not found]                     ` <5239BA98.9000205@gmail.com>
  0 siblings, 2 replies; 56+ messages in thread
From: Junio C Hamano @ 2013-09-17 16:12 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

Jiang Xin <worldhello.net@gmail.com> writes:

> diff --git a/compat/mingw.h b/compat/mingw.h
> index bd0a88b..06e9f49 100644
> --- a/compat/mingw.h
> +++ b/compat/mingw.h
> @@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format
>  
>  #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
>  #define is_dir_sep(c) ((c) == '/' || (c) == '\\')
> +static inline int is_unc_path(const char *path)
> +{
> +	if (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))
> +		return 0;

If path[1] == '\0', it would be !is_dir_sep() and we end up
inspecting past the end of the string?

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw
  2013-09-14  6:52       ` Torsten Bögershausen
@ 2013-09-17 16:19         ` Junio C Hamano
  0 siblings, 0 replies; 56+ messages in thread
From: Junio C Hamano @ 2013-09-17 16:19 UTC (permalink / raw)
  To: Torsten Bögershausen
  Cc: Jiang Xin, Git List, Tvangeste, Johannes Sixt, Karsten Blees

Torsten Bögershausen <tboegi@web.de> writes:

> Yes,
> there is a directoctory structure in / like this:
>
> /usr
> /bin
> /lib
> Then we have the drive letters mapped to single letters:
> /c/Documents and Settings
> /c/temp

Thanks.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-17  8:24               ` Jiang Xin
                                   ` (2 preceding siblings ...)
  2013-09-17  8:30                 ` [PATCH v3 3/3] Use simpler relative_path when set_git_dir Jiang Xin
@ 2013-09-17 19:32                 ` Johannes Sixt
  2013-09-18 14:29                   ` Torsten Bögershausen
  2013-09-20  1:26                   ` Jiang Xin
  3 siblings, 2 replies; 56+ messages in thread
From: Johannes Sixt @ 2013-09-17 19:32 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Junio C Hamano, Torsten Bögershausen, Git List, Tvangeste,
	Karsten Blees

Am 17.09.2013 10:24, schrieb Jiang Xin:
> I have checked the behavior of UNC path on Windows (msysGit):
> 
> * I can cd to a UNC path:
> 
>     cd //server1/share1/path
> 
> * can cd to other share:
> 
>     cd ../../share2/path
> 
> * and can cd to other server's share:
> 
>     cd ../../../server2/share/path
> 
> That means relative_path(path1, path2) support UNC paths out of the box.
> We only need to check both path1 and path2 are UNC paths, or both not.

Your tests are flawed. You issued the commands in bash, which (or rather
MSYS) does everything for you that you need to make it work. But in
reality it does not, because the system cannot apply .. to //server/share:

$ git ls-remote //srv/public/../repos/his/setups.git
fatal: '//srv/public/../repos/his/setups.git' does not appear to be a
git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

even though the repository (and //srv/public, let me assure) exists:

$ git ls-remote //srv/repos/his/setups.git
bea489b0611a72c41f133343fdccbd3e2b9f80b5        HEAD
...

The situation does not change with your latest round (v3).

Please let me suggest not to scratch where there is no itch. ;) Your
round v2 was good enough.

If you really want to check UNC paths, then you must compare two path
components after the the double-slash, not just one.

Furthermore, you should audit all code that references
is_absolute_path(), relative_path(), normalize_path_copy(), and possibly
a few others whether the functions or call sites need improvement.
That's worth a separate patch.

-- Hannes

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
  2013-09-17 16:12                   ` Junio C Hamano
@ 2013-09-18  9:02                     ` Jiang Xin
  2013-09-18 16:00                       ` Junio C Hamano
       [not found]                     ` <5239BA98.9000205@gmail.com>
  1 sibling, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-18  9:02 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

2013/9/18 Junio C Hamano <gitster@pobox.com>:
> Jiang Xin <worldhello.net@gmail.com> writes:
>
>> diff --git a/compat/mingw.h b/compat/mingw.h
>> index bd0a88b..06e9f49 100644
>> --- a/compat/mingw.h
>> +++ b/compat/mingw.h
>> @@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format
>>
>>  #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
>>  #define is_dir_sep(c) ((c) == '/' || (c) == '\\')
>> +static inline int is_unc_path(const char *path)
>> +{
>> +     if (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))
>> +             return 0;

A UNC path must start with two slashes, but not three or more slashes.

>
> If path[1] == '\0', it would be !is_dir_sep() and we end up
> inspecting past the end of the string?

The funciton "is_unc_path" will return false (0), if path is
"", "/", "//", "///three/slashes/", or "/usr/local".
So the problem is ?

-- 
Jiang Xin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-17 19:32                 ` [PATCH 1/2] relative_path should honor dos_drive_prefix Johannes Sixt
@ 2013-09-18 14:29                   ` Torsten Bögershausen
  2013-09-20  1:26                   ` Jiang Xin
  1 sibling, 0 replies; 56+ messages in thread
From: Torsten Bögershausen @ 2013-09-18 14:29 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Jiang Xin, Junio C Hamano, Torsten Bögershausen, Git List,
	Tvangeste, Karsten Blees

On 2013-09-17 21.32, Johannes Sixt wrote:
> Am 17.09.2013 10:24, schrieb Jiang Xin:
>> I have checked the behavior of UNC path on Windows (msysGit):
>>
>> * I can cd to a UNC path:
>>
>>     cd //server1/share1/path
>>
>> * can cd to other share:
>>
>>     cd ../../share2/path
>>
>> * and can cd to other server's share:
>>
>>     cd ../../../server2/share/path
>>
>> That means relative_path(path1, path2) support UNC paths out of the box.
>> We only need to check both path1 and path2 are UNC paths, or both not.
> 
> Your tests are flawed. You issued the commands in bash, which (or rather
> MSYS) does everything for you that you need to make it work. But in
> reality it does not, because the system cannot apply .. to //server/share:
> 
> $ git ls-remote //srv/public/../repos/his/setups.git
> fatal: '//srv/public/../repos/his/setups.git' does not appear to be a
> git repository
> fatal: Could not read from remote repository.
> 
> Please make sure you have the correct access rights
> and the repository exists.
> 
> even though the repository (and //srv/public, let me assure) exists:
> 
> $ git ls-remote //srv/repos/his/setups.git
> bea489b0611a72c41f133343fdccbd3e2b9f80b5        HEAD
> ...
> 
> The situation does not change with your latest round (v3).
> 
> Please let me suggest not to scratch where there is no itch. ;) Your
> round v2 was good enough.
> 
> If you really want to check UNC paths, then you must compare two path
> components after the the double-slash, not just one.
> 
> Furthermore, you should audit all code that references
> is_absolute_path(), relative_path(), normalize_path_copy(), and possibly
> a few others whether the functions or call sites need improvement.
> That's worth a separate patch.
> 
> -- Hannes

I tend to agree here.
The V2 patch fixed a regression.
This should be one commit on its own:
Documentation/SubmittingPatches:
(1) Make separate commits for logically separate changes.

Fixing a bug is a good thing, thanks for working on this,

The support for UNC paths is a new feature, and this deserves a seperate commit.
/Torsten

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
       [not found]                     ` <5239BA98.9000205@gmail.com>
@ 2013-09-18 15:09                       ` Torsten Bögershausen
  0 siblings, 0 replies; 56+ messages in thread
From: Torsten Bögershausen @ 2013-09-18 15:09 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Jiang Xin, Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

On 2013-09-18 16.37, Torsten Bögershausen wrote:
> On 2013-09-17 18.12, Junio C Hamano wrote:
>> Jiang Xin <worldhello.net@gmail.com> writes:
>>
>>> diff --git a/compat/mingw.h b/compat/mingw.h
>>> index bd0a88b..06e9f49 100644
>>> --- a/compat/mingw.h
>>> +++ b/compat/mingw.h
>>> @@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format
>>>  
>>>  #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
>>>  #define is_dir_sep(c) ((c) == '/' || (c) == '\\')
>>> +static inline int is_unc_path(const char *path)
>>> +{
>>> +	if (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))
>>> +		return 0;
>>
>> If path[1] == '\0', it would be !is_dir_sep() and we end up
>> inspecting past the end of the string?
Yes
(If there was a previous mail, it was incomplete, sorry)

I think we want to catch "2 (back)slashes followed by a letter"
<http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx>

#define is_unc_path(path) ((is_dir_sep(path)[0]) && is_dir_sep((path)[1]) && isalpha((path[2])))

Then we need 
#define is_relative_path(path)  (((path)[0]) && !is_dir_sep((path)[1]))

And may be like this:

static int have_same_root(const char *path1, const char *path2)
{
	int is_abs1, is_abs2;

	is_abs1 = is_absolute_path(path1);
	is_abs2 = is_absolute_path(path2);
	if (is_abs1 && is_abs2) {
		if (is_unc_path(path1) && !is_relative_path(path2))
			return 0;
		if (!is_relative_path(path1) && is_unc_path(path2))
			return 0;
		return tolower(path1[0]) == tolower(path2[0]);
	} else {
		return !is_abs1 && !is_abs2;
	}
}

Could that work?

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
  2013-09-18  9:02                     ` Jiang Xin
@ 2013-09-18 16:00                       ` Junio C Hamano
  0 siblings, 0 replies; 56+ messages in thread
From: Junio C Hamano @ 2013-09-18 16:00 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

Jiang Xin <worldhello.net@gmail.com> writes:

> 2013/9/18 Junio C Hamano <gitster@pobox.com>:
>>> +     if (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))
>>> +             return 0;
>> If path[1] == '\0', it would be !is_dir_sep() and we end up
>> inspecting past the end of the string?
>
> The funciton "is_unc_path" will return false (0), if path is
> "", "/", "//", "///three/slashes/", or "/usr/local".
> So the problem is ?

If path[1] == '\0' (e.g. path="/"), !is_dir_sep(path[1]) is true,
not false (as I misread earlier), so we hit an early return and will
not peek path[2].  So no problem.  Sorry for the noise.

But I agree with J6t and Torsten in near-by thread that the simpler
one that does not worry about // should be done as a separate patch
and //, if we decide to do it, should build on top.

Thanks.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
  2013-09-17 19:32                 ` [PATCH 1/2] relative_path should honor dos_drive_prefix Johannes Sixt
  2013-09-18 14:29                   ` Torsten Bögershausen
@ 2013-09-20  1:26                   ` Jiang Xin
  2013-09-20  2:38                     ` [PATCH v4 0/3] relative path regression fix Jiang Xin
                                       ` (3 more replies)
  1 sibling, 4 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-20  1:26 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Junio C Hamano, Torsten Bögershausen, Git List, Tvangeste,
	Karsten Blees

2013/9/18 Johannes Sixt <j6t@kdbg.org>:
> Am 17.09.2013 10:24, schrieb Jiang Xin:
>> I have checked the behavior of UNC path on Windows (msysGit):
>>
>> * I can cd to a UNC path:
>>
>>     cd //server1/share1/path
>>
>> * can cd to other share:
>>
>>     cd ../../share2/path
>>
>> * and can cd to other server's share:
>>
>>     cd ../../../server2/share/path
>>
>> That means relative_path(path1, path2) support UNC paths out of the box.
>> We only need to check both path1 and path2 are UNC paths, or both not.
>
> Your tests are flawed. You issued the commands in bash, which (or rather
> MSYS) does everything for you that you need to make it work. But in
> reality it does not, because the system cannot apply .. to //server/share:
>
> $ git ls-remote //srv/public/../repos/his/setups.git
> fatal: '//srv/public/../repos/his/setups.git' does not appear to be a
> git repository
> fatal: Could not read from remote repository.
>
> Please make sure you have the correct access rights
> and the repository exists.
>
> even though the repository (and //srv/public, let me assure) exists:
>
> $ git ls-remote //srv/repos/his/setups.git
> bea489b0611a72c41f133343fdccbd3e2b9f80b5        HEAD
> ...

After see this link (provided by Torsten):

    <http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx>

I find the following commands could work:

    $ git ls-remote //srv/repos/his/setups.git
    $ git ls-remote //srv/repos/his/../his/setups.git
    $ git ls-remote //?/UNC/srv/repos/his/setups.git
    $ git ls-remote //?/UNC/srv/repos/../repos/his/setups.git

But no luck for this one:

    $ git ls-remote //srv/repos/../repos/his/setups.git

I trace it using gdb, and find it failed in "stat()/mingw_stat()" call
of function "enter_repo" in path.c. But I can not find out why
"git ls-remote //?/UNC/srv/repos/../repos/his/setups.git" could
work (success in shell, failed in gdb).

> Please let me suggest not to scratch where there is no itch. ;) Your
> round v2 was good enough.
>
> If you really want to check UNC paths, then you must compare two path
> components after the the double-slash, not just one.
>

I have already try this (honor two path components after //)
during the reroll for patch v3. But I am not satisfied with it,
and it seems like over-engineered: Rename "have_same_root"
to "get_common_root_prefix_width", and it return -1 for no
same_root found, otherwize return the length of root_prefix_width.

Since restored the default behavior of setup.c in commit ("Use
simpler relative_path when set_git_dir"), function "relative_path"
are only used in "quote.c" and "builtin/clean.c", and two paths
provided to "relative_path" are always (I can not find exception)
relative paths. So no itch exist I think.

-- 
Jiang Xin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v4 0/3] relative path regression fix
  2013-09-20  1:26                   ` Jiang Xin
@ 2013-09-20  2:38                     ` Jiang Xin
  2013-09-20  2:38                     ` [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
                                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-20  2:38 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Remove implementations on UNC names in patch v3.
So patch v4 is the same like v2, but with minor
update for commit logs.

Jiang Xin (3):
  test: use unambigous leading path (/foo) for mingw
  relative_path should honor dos-driver-prefix
  Use simpler relative_path when set_git_dir

 cache.h               |  1 +
 path.c                | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++
 setup.c               |  5 +---
 t/t0060-path-utils.sh | 60 +++++++++++++++++++++++++----------------------
 4 files changed, 99 insertions(+), 32 deletions(-)

-- 
1.8.4.460.gbed9cb4

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw
  2013-09-20  1:26                   ` Jiang Xin
  2013-09-20  2:38                     ` [PATCH v4 0/3] relative path regression fix Jiang Xin
@ 2013-09-20  2:38                     ` Jiang Xin
  2013-10-10 20:32                       ` Sebastian Schuberth
  2013-09-20  2:38                     ` [PATCH v4 2/3] relative_path should honor dos-driver-prefix Jiang Xin
  2013-09-20  2:38                     ` [PATCH v4 3/3] Use simpler relative_path when set_git_dir Jiang Xin
  3 siblings, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-20  2:38 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

In test cases for relative_path, path with one leading character
(such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
such DOS drive on MINGW platform. Use an umambigous leading path
"/foo" instead.

Also change two leading slashes (//) to three leading slashes (///),
otherwize it will be recognized as UNC name on MINGW platform.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 3a48de2..92976e0 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
 	test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
 '
 
-relative_path /a/b/c/	/a/b/		c/
-relative_path /a/b/c/	/a/b		c/
-relative_path /a//b//c/	//a/b//		c/	POSIX
-relative_path /a/b	/a/b		./
-relative_path /a/b/	/a/b		./
-relative_path /a	/a/b		../
-relative_path /		/a/b/		../../
-relative_path /a/c	/a/b/		../c
-relative_path /a/c	/a/b		../c
-relative_path /x/y	/a/b/		../../x/y
-relative_path /a/b	"<empty>"	/a/b
-relative_path /a/b 	"<null>"	/a/b
-relative_path a/b/c/	a/b/		c/
-relative_path a/b/c/	a/b		c/
-relative_path a/b//c	a//b		c
-relative_path a/b/	a/b/		./
-relative_path a/b/	a/b		./
-relative_path a		a/b		../
-relative_path x/y	a/b		../../x/y
-relative_path a/c	a/b		../c
-relative_path a/b	"<empty>"	a/b
-relative_path a/b 	"<null>"	a/b
-relative_path "<empty>"	/a/b		./
-relative_path "<empty>"	"<empty>"	./
-relative_path "<empty>"	"<null>"	./
-relative_path "<null>"	"<empty>"	./
-relative_path "<null>"	"<null>"	./
-relative_path "<null>"	/a/b		./
+relative_path /foo/a/b/c/	/foo/a/b/	c/
+relative_path /foo/a/b/c/	/foo/a/b	c/
+relative_path /foo/a//b//c/	///foo/a/b//	c/		POSIX
+relative_path /foo/a/b		/foo/a/b	./
+relative_path /foo/a/b/		/foo/a/b	./
+relative_path /foo/a		/foo/a/b	../
+relative_path /			/foo/a/b/	../../../
+relative_path /foo/a/c		/foo/a/b/	../c
+relative_path /foo/a/c		/foo/a/b	../c
+relative_path /foo/x/y		/foo/a/b/	../../x/y
+relative_path /foo/a/b		"<empty>"	/foo/a/b
+relative_path /foo/a/b 		"<null>"	/foo/a/b
+relative_path foo/a/b/c/	foo/a/b/	c/
+relative_path foo/a/b/c/	foo/a/b		c/
+relative_path foo/a/b//c	foo/a//b	c
+relative_path foo/a/b/		foo/a/b/	./
+relative_path foo/a/b/		foo/a/b		./
+relative_path foo/a		foo/a/b		../
+relative_path foo/x/y		foo/a/b		../../x/y
+relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		"<empty>"	foo/a/b
+relative_path foo/a/b 		"<null>"	foo/a/b
+relative_path "<empty>"		/foo/a/b	./
+relative_path "<empty>"		"<empty>"	./
+relative_path "<empty>"		"<null>"	./
+relative_path "<null>"		"<empty>"	./
+relative_path "<null>"		"<null>"	./
+relative_path "<null>"		/foo/a/b	./
 
 test_done
-- 
1.8.4.460.gbed9cb4

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 2/3] relative_path should honor dos-driver-prefix
  2013-09-20  1:26                   ` Jiang Xin
  2013-09-20  2:38                     ` [PATCH v4 0/3] relative path regression fix Jiang Xin
  2013-09-20  2:38                     ` [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
@ 2013-09-20  2:38                     ` Jiang Xin
  2013-10-10 20:34                       ` Sebastian Schuberth
  2013-09-20  2:38                     ` [PATCH v4 3/3] Use simpler relative_path when set_git_dir Jiang Xin
  3 siblings, 1 reply; 56+ messages in thread
From: Jiang Xin @ 2013-09-20  2:38 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Tvangeste found that the "relative_path" function could not work
properly on Windows if "in" and "prefix" have DOS driver prefix
(such as "C:/windows"). ($gmane/234434)

E.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
should return "C:/a/b", but returns "../../C:/a/b", which is wrong.

So make relative_path honor dos-driver-prefix, and add test cases
for it in t0060.

Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 path.c                | 20 ++++++++++++++++++++
 t/t0060-path-utils.sh |  4 ++++
 2 files changed, 24 insertions(+)

diff --git a/path.c b/path.c
index 7f3324a..0c16dc5 100644
--- a/path.c
+++ b/path.c
@@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)
 	return 0;
 }
 
+static int have_same_root(const char *path1, const char *path2)
+{
+	int is_abs1, is_abs2;
+
+	is_abs1 = is_absolute_path(path1);
+	is_abs2 = is_absolute_path(path2);
+	return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
+	       (!is_abs1 && !is_abs2);
+}
+
 /*
  * Give path as relative to prefix.
  *
@@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,
 	else if (!prefix_len)
 		return in;
 
+	if (have_same_root(in, prefix)) {
+		/* bypass dos_drive, for "c:" is identical to "C:" */
+		if (has_dos_drive_prefix(in)) {
+			i = 2;
+			j = 2;
+		}
+	} else {
+		return in;
+	}
+
 	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
 		if (is_dir_sep(prefix[i])) {
 			while (is_dir_sep(prefix[i]))
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 92976e0..40dfa2d 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -210,6 +210,10 @@ relative_path foo/a/b/		foo/a/b		./
 relative_path foo/a		foo/a/b		../
 relative_path foo/x/y		foo/a/b		../../x/y
 relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		/foo/x/y	foo/a/b
+relative_path /foo/a/b		foo/x/y		/foo/a/b
+relative_path d:/a/b		D:/a/c		../b		MINGW
+relative_path C:/a/b		D:/a/c		C:/a/b		MINGW
 relative_path foo/a/b		"<empty>"	foo/a/b
 relative_path foo/a/b 		"<null>"	foo/a/b
 relative_path "<empty>"		/foo/a/b	./
-- 
1.8.4.460.gbed9cb4

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v4 3/3] Use simpler relative_path when set_git_dir
  2013-09-20  1:26                   ` Jiang Xin
                                       ` (2 preceding siblings ...)
  2013-09-20  2:38                     ` [PATCH v4 2/3] relative_path should honor dos-driver-prefix Jiang Xin
@ 2013-09-20  2:38                     ` Jiang Xin
  3 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-09-20  2:38 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen, Jiang Xin

Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.
It will make git_dir shorter only if git_dir is inside work_tree,
and this will increase performance. But my last refactor effort on
relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.
Always use relative_path as git_dir may bring troubles like
$gmane/234434.

Because new relative_path is a combination of original relative_path
from path.c and original path_relative from quote.c, so in order to
restore the origin implementation, save the original relative_path
as remove_leading_path, and call it in setup.c.

Suggested-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 cache.h |  1 +
 path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 setup.c |  5 +----
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index 8e42256..94475bd 100644
--- a/cache.h
+++ b/cache.h
@@ -737,6 +737,7 @@ int is_directory(const char *);
 const char *real_path(const char *path);
 const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
+const char *remove_leading_path(const char *in, const char *prefix);
 const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
 int normalize_path_copy(char *dst, const char *src);
 int longest_ancestor_length(const char *path, struct string_list *prefixes);
diff --git a/path.c b/path.c
index 0c16dc5..fa62da5 100644
--- a/path.c
+++ b/path.c
@@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,
 }
 
 /*
+ * A simpler implementation of relative_path
+ *
+ * Get relative path by removing "prefix" from "in". This function
+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
+ * to increase performance when traversing the path to work_tree.
+ */
+const char *remove_leading_path(const char *in, const char *prefix)
+{
+	static char buf[PATH_MAX + 1];
+	int i = 0, j = 0;
+
+	if (!prefix || !prefix[0])
+		return in;
+	while (prefix[i]) {
+		if (is_dir_sep(prefix[i])) {
+			if (!is_dir_sep(in[j]))
+				return in;
+			while (is_dir_sep(prefix[i]))
+				i++;
+			while (is_dir_sep(in[j]))
+				j++;
+			continue;
+		} else if (in[j] != prefix[i]) {
+			return in;
+		}
+		i++;
+		j++;
+	}
+	if (
+	    /* "/foo" is a prefix of "/foo" */
+	    in[j] &&
+	    /* "/foo" is not a prefix of "/foobar" */
+	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
+	   )
+		return in;
+	while (is_dir_sep(in[j]))
+		j++;
+	if (!in[j])
+		strcpy(buf, ".");
+	else
+		strcpy(buf, in + j);
+	return buf;
+}
+
+/*
  * It is okay if dst == src, but they should not overlap otherwise.
  *
  * Performs the following normalizations on src, storing the result in dst:
diff --git a/setup.c b/setup.c
index 0d9ea62..dad39c1 100644
--- a/setup.c
+++ b/setup.c
@@ -360,7 +360,6 @@ int is_inside_work_tree(void)
 
 void setup_work_tree(void)
 {
-	struct strbuf sb = STRBUF_INIT;
 	const char *work_tree, *git_dir;
 	static int initialized = 0;
 
@@ -380,10 +379,8 @@ void setup_work_tree(void)
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
 		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
-	set_git_dir(relative_path(git_dir, work_tree, &sb));
+	set_git_dir(remove_leading_path(git_dir, work_tree));
 	initialized = 1;
-
-	strbuf_release(&sb);
 }
 
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
-- 
1.8.4.460.gbed9cb4

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw
  2013-09-20  2:38                     ` [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
@ 2013-10-10 20:32                       ` Sebastian Schuberth
  2013-10-14  1:33                         ` Jiang Xin
                                           ` (4 more replies)
  0 siblings, 5 replies; 56+ messages in thread
From: Sebastian Schuberth @ 2013-10-10 20:32 UTC (permalink / raw)
  To: Jiang Xin, Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

On 20.09.2013 04:38, Jiang Xin wrote:

> In test cases for relative_path, path with one leading character
> (such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
> such DOS drive on MINGW platform. Use an umambigous leading path
> "/foo" instead.
 >
 > Also change two leading slashes (//) to three leading slashes (///),
 > otherwize it will be recognized as UNC name on MINGW platform.

Note that the path mangling comes from MSYS [1], not MinGW, so you 
should place "MINGW" with "MSYS" in several places. As a side-note, the 
official spelling is "MinGW", not "MINGW".

> -relative_path /a/b/c/	/a/b/		c/

> +relative_path /foo/a/b/c/	/foo/a/b/	c/

Wouldn't it have been more straight-forward to just replace "a" with 
"foo", "b" with "bar" and "c" with "baz" (or whatever)? So that the 
first line would say

relative_path /foo/bar/baz/	/foo/bar/		baz/

Thanks for the fix!

[1] http://www.mingw.org/wiki/Posix_path_conversion

-- 
Sebastian Schuberth

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v4 2/3] relative_path should honor dos-driver-prefix
  2013-09-20  2:38                     ` [PATCH v4 2/3] relative_path should honor dos-driver-prefix Jiang Xin
@ 2013-10-10 20:34                       ` Sebastian Schuberth
  0 siblings, 0 replies; 56+ messages in thread
From: Sebastian Schuberth @ 2013-10-10 20:34 UTC (permalink / raw)
  To: Jiang Xin, Junio C Hamano
  Cc: Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

On 20.09.2013 04:38, Jiang Xin wrote:

> Tvangeste found that the "relative_path" function could not work
> properly on Windows if "in" and "prefix" have DOS driver prefix
> (such as "C:/windows"). ($gmane/234434)

s/driver/drive/

> E.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
> should return "C:/a/b", but returns "../../C:/a/b", which is wrong.
>
> So make relative_path honor dos-driver-prefix, and add test cases
> for it in t0060.

s/dos-driver-prefix/DOS drive prefix/

-- 
Sebastian Schuberth

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw
  2013-10-10 20:32                       ` Sebastian Schuberth
@ 2013-10-14  1:33                         ` Jiang Xin
  2013-10-14  2:29                         ` [PATCH v5 0/3] relative path regression fix Jiang Xin
                                           ` (3 subsequent siblings)
  4 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-10-14  1:33 UTC (permalink / raw)
  To: Sebastian Schuberth
  Cc: Junio C Hamano, Git List, Tvangeste, Johannes Sixt, Karsten Blees,
	Torsten Bögershausen

2013/10/11 Sebastian Schuberth <sschuberth@gmail.com>:
>> In test cases for relative_path, path with one leading character
>> (such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
>> such DOS drive on MINGW platform. Use an umambigous leading path
>> "/foo" instead.
>>
>> Also change two leading slashes (//) to three leading slashes (///),
>> otherwize it will be recognized as UNC name on MINGW platform.
>
> Note that the path mangling comes from MSYS [1], not MinGW, so you should
> place "MINGW" with "MSYS" in several places. As a side-note, the official
> spelling is "MinGW", not "MINGW".
>

I will make a reroll. s/MINGW/MSYS/i

>> -relative_path /a/b/c/  /a/b/           c/
>
>
>> +relative_path /foo/a/b/c/      /foo/a/b/       c/
>
>
> Wouldn't it have been more straight-forward to just replace "a" with "foo",
> "b" with "bar" and "c" with "baz" (or whatever)? So that the first line
> would say
>
> relative_path /foo/bar/baz/     /foo/bar/               baz/
>

These test cases have been used in some commit logs, such as
commit: v1.8.3-rc2-13-gad66df2. And for me (a non-English speaker)
a,b,c,x,y,z are more readable than bar, baz, qux, ...

-- 
Jiang Xin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v5 0/3] relative path regression fix
  2013-10-10 20:32                       ` Sebastian Schuberth
  2013-10-14  1:33                         ` Jiang Xin
@ 2013-10-14  2:29                         ` Jiang Xin
  2013-10-14  2:29                         ` [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS Jiang Xin
                                           ` (2 subsequent siblings)
  4 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-10-14  2:29 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Git List, Sebastian Schuberth, Junio C Hamano, Johannes Sixt,
	Jiang Xin

Update since v4:

 * Update commit logs with the help from Sebastian Schuberth:

   s/MINGW/MSYS/i
   s/dos-driver-prefix/dos-drive-prefix/

Jiang Xin (3):
  test: use unambigous leading path (/foo) for MSYS
  relative_path should honor dos-drive-prefix
  Use simpler relative_path when set_git_dir

 cache.h               |  1 +
 path.c                | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++
 setup.c               |  5 +---
 t/t0060-path-utils.sh | 60 +++++++++++++++++++++++++----------------------
 4 files changed, 99 insertions(+), 32 deletions(-)

-- 
1.8.4

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS
  2013-10-10 20:32                       ` Sebastian Schuberth
  2013-10-14  1:33                         ` Jiang Xin
  2013-10-14  2:29                         ` [PATCH v5 0/3] relative path regression fix Jiang Xin
@ 2013-10-14  2:29                         ` Jiang Xin
  2013-10-14  6:50                           ` Sebastian Schuberth
  2013-10-14 19:40                           ` Eric Sunshine
  2013-10-14  2:29                         ` [PATCH v5 2/3] relative_path should honor dos-drive-prefix Jiang Xin
  2013-10-14  2:29                         ` [PATCH v5 3/3] Use simpler relative_path when set_git_dir Jiang Xin
  4 siblings, 2 replies; 56+ messages in thread
From: Jiang Xin @ 2013-10-14  2:29 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Git List, Sebastian Schuberth, Junio C Hamano, Johannes Sixt,
	Jiang Xin

In test cases for relative_path, path with one leading character
(such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
such DOS drive on MSYS platform. Use an umambigous leading path
"/foo" instead.

Also change two leading slashes (//) to three leading slashes (///),
otherwize it will be recognized as UNC name on MSYS platform.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 3a48de2..92976e0 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
 	test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
 '
 
-relative_path /a/b/c/	/a/b/		c/
-relative_path /a/b/c/	/a/b		c/
-relative_path /a//b//c/	//a/b//		c/	POSIX
-relative_path /a/b	/a/b		./
-relative_path /a/b/	/a/b		./
-relative_path /a	/a/b		../
-relative_path /		/a/b/		../../
-relative_path /a/c	/a/b/		../c
-relative_path /a/c	/a/b		../c
-relative_path /x/y	/a/b/		../../x/y
-relative_path /a/b	"<empty>"	/a/b
-relative_path /a/b 	"<null>"	/a/b
-relative_path a/b/c/	a/b/		c/
-relative_path a/b/c/	a/b		c/
-relative_path a/b//c	a//b		c
-relative_path a/b/	a/b/		./
-relative_path a/b/	a/b		./
-relative_path a		a/b		../
-relative_path x/y	a/b		../../x/y
-relative_path a/c	a/b		../c
-relative_path a/b	"<empty>"	a/b
-relative_path a/b 	"<null>"	a/b
-relative_path "<empty>"	/a/b		./
-relative_path "<empty>"	"<empty>"	./
-relative_path "<empty>"	"<null>"	./
-relative_path "<null>"	"<empty>"	./
-relative_path "<null>"	"<null>"	./
-relative_path "<null>"	/a/b		./
+relative_path /foo/a/b/c/	/foo/a/b/	c/
+relative_path /foo/a/b/c/	/foo/a/b	c/
+relative_path /foo/a//b//c/	///foo/a/b//	c/		POSIX
+relative_path /foo/a/b		/foo/a/b	./
+relative_path /foo/a/b/		/foo/a/b	./
+relative_path /foo/a		/foo/a/b	../
+relative_path /			/foo/a/b/	../../../
+relative_path /foo/a/c		/foo/a/b/	../c
+relative_path /foo/a/c		/foo/a/b	../c
+relative_path /foo/x/y		/foo/a/b/	../../x/y
+relative_path /foo/a/b		"<empty>"	/foo/a/b
+relative_path /foo/a/b 		"<null>"	/foo/a/b
+relative_path foo/a/b/c/	foo/a/b/	c/
+relative_path foo/a/b/c/	foo/a/b		c/
+relative_path foo/a/b//c	foo/a//b	c
+relative_path foo/a/b/		foo/a/b/	./
+relative_path foo/a/b/		foo/a/b		./
+relative_path foo/a		foo/a/b		../
+relative_path foo/x/y		foo/a/b		../../x/y
+relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		"<empty>"	foo/a/b
+relative_path foo/a/b 		"<null>"	foo/a/b
+relative_path "<empty>"		/foo/a/b	./
+relative_path "<empty>"		"<empty>"	./
+relative_path "<empty>"		"<null>"	./
+relative_path "<null>"		"<empty>"	./
+relative_path "<null>"		"<null>"	./
+relative_path "<null>"		/foo/a/b	./
 
 test_done
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 2/3] relative_path should honor dos-drive-prefix
  2013-10-10 20:32                       ` Sebastian Schuberth
                                           ` (2 preceding siblings ...)
  2013-10-14  2:29                         ` [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS Jiang Xin
@ 2013-10-14  2:29                         ` Jiang Xin
  2013-10-14  2:29                         ` [PATCH v5 3/3] Use simpler relative_path when set_git_dir Jiang Xin
  4 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-10-14  2:29 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Git List, Sebastian Schuberth, Junio C Hamano, Johannes Sixt,
	Jiang Xin

Tvangeste found that the "relative_path" function could not work
properly on Windows if "in" and "prefix" have DOS drive prefix
(such as "C:/windows"). ($gmane/234434)

E.g., When execute: test-path-utils relative_path "C:/a/b" "D:/x/y",
should return "C:/a/b", but returns "../../C:/a/b", which is wrong.

So make relative_path honor DOS drive prefix, and add test cases
for it in t0060.

Reported-by: Tvangeste <i.4m.l33t@yandex.ru>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 path.c                | 20 ++++++++++++++++++++
 t/t0060-path-utils.sh |  4 ++++
 2 files changed, 24 insertions(+)

diff --git a/path.c b/path.c
index 7f3324a..0c16dc5 100644
--- a/path.c
+++ b/path.c
@@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)
 	return 0;
 }
 
+static int have_same_root(const char *path1, const char *path2)
+{
+	int is_abs1, is_abs2;
+
+	is_abs1 = is_absolute_path(path1);
+	is_abs2 = is_absolute_path(path2);
+	return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
+	       (!is_abs1 && !is_abs2);
+}
+
 /*
  * Give path as relative to prefix.
  *
@@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,
 	else if (!prefix_len)
 		return in;
 
+	if (have_same_root(in, prefix)) {
+		/* bypass dos_drive, for "c:" is identical to "C:" */
+		if (has_dos_drive_prefix(in)) {
+			i = 2;
+			j = 2;
+		}
+	} else {
+		return in;
+	}
+
 	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
 		if (is_dir_sep(prefix[i])) {
 			while (is_dir_sep(prefix[i]))
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 92976e0..40dfa2d 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -210,6 +210,10 @@ relative_path foo/a/b/		foo/a/b		./
 relative_path foo/a		foo/a/b		../
 relative_path foo/x/y		foo/a/b		../../x/y
 relative_path foo/a/c		foo/a/b		../c
+relative_path foo/a/b		/foo/x/y	foo/a/b
+relative_path /foo/a/b		foo/x/y		/foo/a/b
+relative_path d:/a/b		D:/a/c		../b		MINGW
+relative_path C:/a/b		D:/a/c		C:/a/b		MINGW
 relative_path foo/a/b		"<empty>"	foo/a/b
 relative_path foo/a/b 		"<null>"	foo/a/b
 relative_path "<empty>"		/foo/a/b	./
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v5 3/3] Use simpler relative_path when set_git_dir
  2013-10-10 20:32                       ` Sebastian Schuberth
                                           ` (3 preceding siblings ...)
  2013-10-14  2:29                         ` [PATCH v5 2/3] relative_path should honor dos-drive-prefix Jiang Xin
@ 2013-10-14  2:29                         ` Jiang Xin
  4 siblings, 0 replies; 56+ messages in thread
From: Jiang Xin @ 2013-10-14  2:29 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Git List, Sebastian Schuberth, Junio C Hamano, Johannes Sixt,
	Jiang Xin

Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.
It will make git_dir shorter only if git_dir is inside work_tree,
and this will increase performance. But my last refactor effort on
relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.
Always use relative_path as git_dir may bring troubles like
$gmane/234434.

Because new relative_path is a combination of original relative_path
from path.c and original path_relative from quote.c, so in order to
restore the origin implementation, save the original relative_path
as remove_leading_path, and call it in setup.c.

Suggested-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 cache.h |  1 +
 path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 setup.c |  5 +----
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index 8e42256..94475bd 100644
--- a/cache.h
+++ b/cache.h
@@ -737,6 +737,7 @@ int is_directory(const char *);
 const char *real_path(const char *path);
 const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
+const char *remove_leading_path(const char *in, const char *prefix);
 const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
 int normalize_path_copy(char *dst, const char *src);
 int longest_ancestor_length(const char *path, struct string_list *prefixes);
diff --git a/path.c b/path.c
index 0c16dc5..fa62da5 100644
--- a/path.c
+++ b/path.c
@@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,
 }
 
 /*
+ * A simpler implementation of relative_path
+ *
+ * Get relative path by removing "prefix" from "in". This function
+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
+ * to increase performance when traversing the path to work_tree.
+ */
+const char *remove_leading_path(const char *in, const char *prefix)
+{
+	static char buf[PATH_MAX + 1];
+	int i = 0, j = 0;
+
+	if (!prefix || !prefix[0])
+		return in;
+	while (prefix[i]) {
+		if (is_dir_sep(prefix[i])) {
+			if (!is_dir_sep(in[j]))
+				return in;
+			while (is_dir_sep(prefix[i]))
+				i++;
+			while (is_dir_sep(in[j]))
+				j++;
+			continue;
+		} else if (in[j] != prefix[i]) {
+			return in;
+		}
+		i++;
+		j++;
+	}
+	if (
+	    /* "/foo" is a prefix of "/foo" */
+	    in[j] &&
+	    /* "/foo" is not a prefix of "/foobar" */
+	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
+	   )
+		return in;
+	while (is_dir_sep(in[j]))
+		j++;
+	if (!in[j])
+		strcpy(buf, ".");
+	else
+		strcpy(buf, in + j);
+	return buf;
+}
+
+/*
  * It is okay if dst == src, but they should not overlap otherwise.
  *
  * Performs the following normalizations on src, storing the result in dst:
diff --git a/setup.c b/setup.c
index 0d9ea62..dad39c1 100644
--- a/setup.c
+++ b/setup.c
@@ -360,7 +360,6 @@ int is_inside_work_tree(void)
 
 void setup_work_tree(void)
 {
-	struct strbuf sb = STRBUF_INIT;
 	const char *work_tree, *git_dir;
 	static int initialized = 0;
 
@@ -380,10 +379,8 @@ void setup_work_tree(void)
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
 		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
-	set_git_dir(relative_path(git_dir, work_tree, &sb));
+	set_git_dir(remove_leading_path(git_dir, work_tree));
 	initialized = 1;
-
-	strbuf_release(&sb);
 }
 
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS
  2013-10-14  2:29                         ` [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS Jiang Xin
@ 2013-10-14  6:50                           ` Sebastian Schuberth
  2013-10-14 19:40                           ` Eric Sunshine
  1 sibling, 0 replies; 56+ messages in thread
From: Sebastian Schuberth @ 2013-10-14  6:50 UTC (permalink / raw)
  To: Jiang Xin; +Cc: Jonathan Nieder, Git List, Junio C Hamano, Johannes Sixt

On Mon, Oct 14, 2013 at 4:29 AM, Jiang Xin <worldhello.net@gmail.com> wrote:

> In test cases for relative_path, path with one leading character
> (such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
> such DOS drive on MSYS platform. Use an umambigous leading path
> "/foo" instead.
>
> Also change two leading slashes (//) to three leading slashes (///),
> otherwize it will be recognized as UNC name on MSYS platform.
>
> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------
>  1 file changed, 28 insertions(+), 28 deletions(-)

Thanks, ack.

-- 
Sebastian Schuberth

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS
  2013-10-14  2:29                         ` [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS Jiang Xin
  2013-10-14  6:50                           ` Sebastian Schuberth
@ 2013-10-14 19:40                           ` Eric Sunshine
  1 sibling, 0 replies; 56+ messages in thread
From: Eric Sunshine @ 2013-10-14 19:40 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Jonathan Nieder, Git List, Sebastian Schuberth, Junio C Hamano,
	Johannes Sixt

On Sun, Oct 13, 2013 at 10:29 PM, Jiang Xin <worldhello.net@gmail.com> wrote:
> In test cases for relative_path, path with one leading character
> (such as /a, /x) may be recogonized as "a:/" or "x:/" if there is
> such DOS drive on MSYS platform. Use an umambigous leading path
> "/foo" instead.
>
> Also change two leading slashes (//) to three leading slashes (///),
> otherwize it will be recognized as UNC name on MSYS platform.

s/otherwize/otherwise/

> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2013-10-14 19:41 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-10 13:14 Regression in e02ca72: git svn rebase is broken on Windows Tvangeste
2013-09-10 16:13 ` Johannes Schindelin
2013-09-10 17:43   ` Tvangeste
2013-09-10 18:02     ` Johannes Schindelin
2013-09-10 20:53       ` Tvangeste
2013-09-10 16:52 ` Johannes Sixt
2013-09-10 17:44   ` Tvangeste
2013-09-10 17:06 ` Junio C Hamano
2013-09-10 22:17   ` Karsten Blees
2013-09-11  4:41     ` Jiang Xin
2013-09-11  3:19   ` Jiang Xin
2013-09-11  5:43     ` Johannes Sixt
2013-09-12  9:12   ` [PATCH 1/2] relative_path should honor dos_drive_prefix Jiang Xin
2013-09-12  9:32     ` Tvangeste
2013-09-12 14:13     ` Torsten Bögershausen
2013-09-12 15:48       ` Junio C Hamano
2013-09-12 17:22       ` Johannes Sixt
2013-09-12 19:11         ` Junio C Hamano
2013-09-13  4:55           ` Jiang Xin
2013-09-13  5:53             ` Junio C Hamano
2013-09-17  8:24               ` Jiang Xin
2013-09-17  8:30                 ` [PATCH v3 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
2013-09-17  8:30                 ` [PATCH v3 2/3] relative_path should honor DOS and UNC paths Jiang Xin
2013-09-17 16:12                   ` Junio C Hamano
2013-09-18  9:02                     ` Jiang Xin
2013-09-18 16:00                       ` Junio C Hamano
     [not found]                     ` <5239BA98.9000205@gmail.com>
2013-09-18 15:09                       ` Torsten Bögershausen
2013-09-17  8:30                 ` [PATCH v3 3/3] Use simpler relative_path when set_git_dir Jiang Xin
2013-09-17 19:32                 ` [PATCH 1/2] relative_path should honor dos_drive_prefix Johannes Sixt
2013-09-18 14:29                   ` Torsten Bögershausen
2013-09-20  1:26                   ` Jiang Xin
2013-09-20  2:38                     ` [PATCH v4 0/3] relative path regression fix Jiang Xin
2013-09-20  2:38                     ` [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
2013-10-10 20:32                       ` Sebastian Schuberth
2013-10-14  1:33                         ` Jiang Xin
2013-10-14  2:29                         ` [PATCH v5 0/3] relative path regression fix Jiang Xin
2013-10-14  2:29                         ` [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS Jiang Xin
2013-10-14  6:50                           ` Sebastian Schuberth
2013-10-14 19:40                           ` Eric Sunshine
2013-10-14  2:29                         ` [PATCH v5 2/3] relative_path should honor dos-drive-prefix Jiang Xin
2013-10-14  2:29                         ` [PATCH v5 3/3] Use simpler relative_path when set_git_dir Jiang Xin
2013-09-20  2:38                     ` [PATCH v4 2/3] relative_path should honor dos-driver-prefix Jiang Xin
2013-10-10 20:34                       ` Sebastian Schuberth
2013-09-20  2:38                     ` [PATCH v4 3/3] Use simpler relative_path when set_git_dir Jiang Xin
2013-09-13 13:59             ` [PATCH 1/2] relative_path should honor dos_drive_prefix Torsten Bögershausen
2013-09-12 15:45     ` Karsten Blees
2013-09-12  9:12   ` [PATCH 2/2] Use simpler relative_path when set_git_dir Jiang Xin
2013-09-12 17:36     ` Johannes Sixt
2013-09-13  5:08   ` [PATCH v2 0/3] fixes for relative_path Jiang Xin
2013-09-13  5:08   ` [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw Jiang Xin
2013-09-13 19:51     ` Junio C Hamano
2013-09-14  6:52       ` Torsten Bögershausen
2013-09-17 16:19         ` Junio C Hamano
2013-09-13  5:08   ` [PATCH v2 2/3] relative_path should honor dos_drive_prefix Jiang Xin
2013-09-14  6:11     ` Torsten Bögershausen
2013-09-13  5:08   ` [PATCH v2 3/3] Use simpler relative_path when set_git_dir Jiang Xin

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).