Regression in e02ca72: git svn rebase is broken on Windows
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
Am 10.09.2013 15:14, schrieb Tvangeste:
Quoted 13 lines
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
10.09.2013, 18:53, "Johannes Sixt" <[email protected]>:
Quoted 1 line
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
Hi Tvangeste,
Quoted 2 lines · Tvangeste
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
10.09.2013, 18:13, "Johannes Schindelin" <[email protected]>:
Quoted 1 line
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
Hi Tvangeste,
Quoted 4 lines · Tvangeste
10.09.2013, 18:13, "Johannes Schindelin" <[email protected]>:
Quoted 1 line
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.
Quoted 3 lines
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
Signature · 18 lines
-- *** 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 [email protected] To unsubscribe from this group, send email to [email protected] 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 [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
10.09.2013, 20:02, "Johannes Schindelin" <[email protected]>:
Quoted 4 lines
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
Quoted 20 lines · Tvangeste
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
e02ca72f70ed8f0268a81f72cb3230c72e538e77is the first bad commit commite02ca72f70ed8f0268a81f72cb3230c72e538e77
Quoted 7 lines
Author: Jiang Xin Date: Tue Jun 25 23:53:43 2013 +0800
path.c: refactorrelative_path(), not only strip prefixThanks,
--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?
2013/9/11 Junio C Hamano <[email protected]>:
Quoted 30 lines
Quoted 20 lines · Tvangeste
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
e02ca72f70ed8f0268a81f72cb3230c72e538e77is the first bad commit commite02ca72f70ed8f0268a81f72cb3230c72e538e77Quoted 7 lines
Author: Jiang Xin Date: Tue Jun 25 23:53:43 2013 +0800
path.c: refactorrelative_path(), not only strip prefixThanks,
--Tvangeste
Quoted 7 lines
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/bFor 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/bpath.c +19 -0
@@ -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'?
Signature · 1 line
Jiang Xin
Am 11.09.2013 05:19, schrieb Jiang Xin:
Quoted 46 lines
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/bFor 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/bpath.c +7
-0@@ -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; +*/
path.c int adjust_shared_perm(const char *path) · line 460
Quoted 10 lines
path.c +10
-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.
path.c int adjust_shared_perm(const char *path) · line 461
Quoted 1 line
path.c +1
-0+}
-- Hannes
Signature · 18 lines
-- *** 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 [email protected] To unsubscribe from this group, send email to [email protected] 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 [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
Quoted 6 lines · Junio C Hamano <gitster <at> pobox.com> writes:
Quoted 3 lines · 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
Quoted 7 lines
Windows (mingw/msys version).
Quoted 6 lines
==========
#> 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
Quoted 7 lines
Quoted 7 lines
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):
Quoted 12 lines
Quoted 11 lines
git://git.kernel.org/pub/scm/git/git.git
e02ca72f70ed8f0268a81f72cb3230c72e538e77is the first bad commit commite02ca72f70ed8f0268a81f72cb3230c72e538e77Author: Jiang Xin Date: Tue Jun 25 23:53:43 2013 +0800
path.c: refactorrelative_path(), not only strip prefixThanks,
--Tvangeste
Quoted 8 lines
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...
2013/9/11 Karsten Blees <[email protected]>:
Quoted 11 lines
Quoted 8 lines · 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?
Quoted 8 lines
Indeed, this patch seems to change
relative_pathin a way that breaks git initialization, not just on Windows.Previously,
relative_pathwas 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 makingGIT_DIRshorter if it was a subdir ofGIT_WORK_TREE.
Yes, it's what commit v1.5.6-1-g044bbbc says.
Quoted 3 lines
After this patch,
relative_pathalways tries to return a relative path, even if both absolute paths are completely disjunct. This not only defeats the purpose (by makingGIT_DIRlonger, thus hurting performance), it is also not
Sometimes longer, sometimes shorter maybe.
Quoted 4 lines
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.
Signature · 1 line
Jiang Xin
PATCH 1/2 relative_path should honor dos_drive_prefix
In reply to Junio C HamanoTvangeste 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.
--- path.c | 20 ++++++++++++++++++++ t/t0060-path-utils.sh | 4 ++++ 2 files changed, 24 insertions(+)
path.c +20 -0
@@ -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]))
t/t0060-path-utils.sh +4 -0
@@ -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 ./
Signature · 1 line
1.8.3.rc2.14.g5ac1b82
PATCH 2/2 Use simpler relative_path when set_git_dir
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.
--- cache.h | 1 + path.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ setup.c | 5 +---- 3 files changed, 47 insertions(+), 4 deletions(-)
cache.h +1 -0
@@ -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);
path.c +45 -0
51 lines not on this page · raw message
setup.c +1 -4
@@ -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)
Signature · 1 line
1.8.3.rc2.14.g5ac1b82
Re: [PATCH 2/2] Use simpler relative_path when set_git_dir
Am 12.09.2013 11:12, schrieb Jiang Xin:
Quoted 37 lines
Using a
relative_pathasgit_dirfirst appears in v1.5.6-1-g044bbbc. It will makegit_dirshorter only ifgit_diris insidework_tree, and this will increase performance. But my last refactor effort onrelative_pathfunction (commit v1.8.3-rc2-12-ge02ca72) changed that. Always userelative_pathasgit_dirmay bring troubles like $gmane/234434.Because new
relative_pathis a combination of originalrelative_pathfrompath.cand originalpath_relativefromquote.c, so in order to restore the origin implementation, save the originalrelative_pathtosimple_relative_path, and call it insetup.c.Suggested-by Karsten Blees <[email protected]>Signed-off-by Jiang Xin <[email protected]>--- cache.h | 1 + path.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ setup.c | 5 +---- 3 files changed, 47 insertions(+), 4 deletions(-)cache.h +1
-0@@ -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);path.c +0
-0
path.c const char *relative_path(const char *in, const char *prefix, · line 561
Quoted 4 lines
path.c +1
-0@@ -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.
Quoted 43 lines
path.c +42
-0+* +* 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; +}
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
In reply to Jiang XinQuoted 23 lines · 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_pathhonordos_drive_prefix, and add test cases for it in t0060.Reported-by Tvangeste <[email protected]>Helped-by Johannes Sixt <[email protected]>Signed-off-by Jiang Xin <[email protected]>--- path.c | 20 ++++++++++++++++++++ t/t0060-path-utils.sh | 4 ++++ 2 files changed, 24 insertions(+)path.c +0
-0
path.c int adjust_shared_perm(const char *path) · line 450
Quoted 10 lines
path.c +7
-0@@ -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
Quoted 39 lines
path.c +13
-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]))t/t0060-path-utils.sh +4
-0@@ -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 ./
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
Am 12.09.2013 16:13, schrieb Torsten Bögershausen:
Quoted 10 lines · Jiang Xin
path.c int adjust_shared_perm(const char *path) · line 450
Quoted 7 lines
path.c +7
-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 withstrncmp_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.
Quoted 5 lines
See
dir.c:
intstrncmp_icase(const char *a, const char *b, size_t count){ return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count); }
-- Hannes
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
Quoted 12 lines · Johannes Sixt
Am 12.09.2013 16:13, schrieb Torsten Bögershausen:
Quoted 10 lines · Jiang Xin
path.c int adjust_shared_perm(const char *path) · line 450
Quoted 7 lines
path.c +7
-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 withstrncmp_icase()?
Quoted 4 lines
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.
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
2013/9/13 Junio C Hamano <[email protected]>:
Quoted 6 lines
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
Quoted 8 lines
- //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.
Signature · 1 line
Jiang Xin
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
Quoted 9 lines · Jiang Xin
2013/9/13 Junio C Hamano <[email protected]>:
Quoted 8 lines
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;
Quoted 7 lines
Quoted 5 lines
- //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]))
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
In reply to Jiang XinQuoted 10 lines · Jiang Xin
2013/9/13 Junio C Hamano <[email protected]>:
Quoted 9 lines
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;
Quoted 6 lines
Quoted 3 lines
- //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.
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
2013/9/13 Junio C Hamano <[email protected]>:
Quoted 35 lines
Quoted 10 lines · Jiang Xin
2013/9/13 Junio C Hamano <[email protected]>:
Quoted 9 lines
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;
Quoted 6 lines
Quoted 3 lines
- //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.
Quoted 9 lines
(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;
+ }
+}
Signature · 1 line
Jiang Xin
PATCH v3 1/3 test: use unambigous leading path (/foo) for mingw
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.
--- t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-)
t/t0060-path-utils.sh +28 -28
@@ -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
Signature · 1 line
1.8.4.460.g2f083d1
PATCH v3 2/3 relative_path should honor DOS and UNC paths
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.
--- compat/mingw.h | 9 +++++++++ git-compat-util.h | 4 ++++ path.c | 25 +++++++++++++++++++++++++ t/t0060-path-utils.sh | 8 ++++++++ 4 files changed, 46 insertions(+)
compat/mingw.h +9 -0
@@ -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 ;
git-compat-util.h +4 -0
@@ -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
path.c +25 -0
@@ -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]))
t/t0060-path-utils.sh +8 -0
@@ -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 ./
Signature · 1 line
1.8.4.460.g2f083d1
Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
compat/mingw.h int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format · line 317
Quoted 12 lines · Jiang Xin
compat/mingw.h +4
-0@@ -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?
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
Quoted 9 lines · Torsten Bögershausen
Quoted 8 lines · Junio C Hamano
Quoted 6 lines · Jiang Xin
compat/mingw.h +0
-0@@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format
Quoted 9 lines
Quoted 9 lines
compat/mingw.h int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format · line 317
Quoted 6 lines
compat/mingw.h +4
-0#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?
Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
In reply to Junio C Hamano2013/9/18 Junio C Hamano <[email protected]>:
Quoted 8 lines
Quoted 6 lines · Jiang Xin
compat/mingw.h +0
-0@@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format
Quoted 6 lines
compat/mingw.h int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format · line 317
Quoted 6 lines
compat/mingw.h +4
-0#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.
Quoted 3 lines
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 ?
Signature · 1 line
Jiang Xin
Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths
Quoted 9 lines · Jiang Xin
2013/9/18 Junio C Hamano <[email protected]>:
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ 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.
PATCH v3 3/3 Use simpler relative_path when set_git_dir
In reply to Jiang XinUsing 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.
--- cache.h | 1 + path.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ setup.c | 5 +---- 3 files changed, 47 insertions(+), 4 deletions(-)
cache.h +1 -0
@@ -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);
path.c +45 -0
51 lines not on this page · raw message
setup.c +1 -4
@@ -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)
Signature · 1 line
1.8.4.460.g2f083d1
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
In reply to Jiang XinAm 17.09.2013 10:24, schrieb Jiang Xin:
Quoted 8 lines
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:
Quoted 8 lines
cd ../../share2/path* and can cd to other server's share:
cd ../../../server2/share/pathThat 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
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
Quoted 44 lines · Johannes Sixt
Am 17.09.2013 10:24, schrieb Jiang Xin:
Quoted 8 lines
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:
Quoted 8 lines
cd ../../share2/path* and can cd to other server's share:
cd ../../../server2/share/pathThat 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.
Quoted 6 lines
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
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
In reply to Johannes Sixt2013/9/18 Johannes Sixt <[email protected]>:
Quoted 27 lines
Am 17.09.2013 10:24, schrieb Jiang Xin:
Quoted 8 lines
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:
Quoted 8 lines
cd ../../share2/path* and can cd to other server's share:
cd ../../../server2/share/pathThat 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.
Quoted 8 lines
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.gitBut 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).
Quoted 6 lines
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.
Signature · 1 line
Jiang Xin
v4 cover relative path regression fix
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(-)
Signature · 1 line
1.8.4.460.gbed9cb4
PATCH v4 1/3 test: use unambigous leading path (/foo) for mingw
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.
--- t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-)
t/t0060-path-utils.sh +28 -28
@@ -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
Signature · 1 line
1.8.4.460.gbed9cb4
Re: [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw
Quoted 7 lines · 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.
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".
t/t0060-path-utils.sh test_expect_success SYMLINKS 'real path works on symlinks' '
Quoted 3 lines
t/t0060-path-utils.sh +1
-1-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
Signature · 1 line
Sebastian Schuberth
Re: [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw
2013/10/11 Sebastian Schuberth <[email protected]>:
Quoted 5 lines
Quoted 5 lines
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.
Quoted 7 lines
Quoted 2 lines
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
Quoted 12 lines
t/t0060-path-utils.sh test_expect_success SYMLINKS 'real path works on symlinks' '
Quoted 4 lines
t/t0060-path-utils.sh +1
-1-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, ...
Signature · 1 line
Jiang Xin
v5 cover relative path regression fix
In reply to Sebastian SchuberthUpdate 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(-)
Signature · 1 line
1.8.4
PATCH v5 1/3 test: use unambigous leading path (/foo) for MSYS
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.
--- t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-)
t/t0060-path-utils.sh +28 -28
@@ -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
Signature · 1 line
1.8.4
Re: [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS
Quoted 5 lines · 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.
Quoted 8 lines
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 <[email protected]>Signed-off-by Junio C Hamano <[email protected]>--- t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-)
Thanks, ack.
Signature · 1 line
Sebastian Schuberth
Re: [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS
In reply to Jiang XinQuoted 7 lines · 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.
s/otherwize/otherwise/
Quoted 2 lines
Signed-off-by Jiang Xin <[email protected]>Signed-off-by Junio C Hamano <[email protected]>
PATCH v5 2/3 relative_path should honor dos-drive-prefix
In reply to Jiang XinTvangeste 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.
--- path.c | 20 ++++++++++++++++++++ t/t0060-path-utils.sh | 4 ++++ 2 files changed, 24 insertions(+)
path.c +20 -0
@@ -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]))
t/t0060-path-utils.sh +4 -0
@@ -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 ./
Signature · 1 line
1.8.4
PATCH v5 3/3 Use simpler relative_path when set_git_dir
In reply to Jiang XinUsing 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.
--- cache.h | 1 + path.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ setup.c | 5 +---- 3 files changed, 47 insertions(+), 4 deletions(-)
cache.h +1 -0
@@ -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);
path.c +45 -0
51 lines not on this page · raw message
setup.c +1 -4
@@ -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)
Signature · 1 line
1.8.4
PATCH v4 2/3 relative_path should honor dos-driver-prefix
In reply to Jiang XinTvangeste 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.
--- path.c | 20 ++++++++++++++++++++ t/t0060-path-utils.sh | 4 ++++ 2 files changed, 24 insertions(+)
path.c +20 -0
@@ -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]))
t/t0060-path-utils.sh +4 -0
@@ -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 ./
Signature · 1 line
1.8.4.460.gbed9cb4
Re: [PATCH v4 2/3] relative_path should honor dos-driver-prefix
Quoted 3 lines · 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)
s/driver/drive/
Quoted 5 lines
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_pathhonor dos-driver-prefix, and add test cases for it in t0060.
s/dos-driver-prefix/DOS drive prefix/
Signature · 1 line
Sebastian Schuberth
PATCH v4 3/3 Use simpler relative_path when set_git_dir
In reply to Jiang XinUsing 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.
--- cache.h | 1 + path.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ setup.c | 5 +---- 3 files changed, 47 insertions(+), 4 deletions(-)
cache.h +1 -0
@@ -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);
path.c +45 -0
51 lines not on this page · raw message
setup.c +1 -4
@@ -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)
Signature · 1 line
1.8.4.460.gbed9cb4
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
In reply to Torsten BögershausenQuoted 9 lines · Torsten Bögershausen
path.c int adjust_shared_perm(const char *path) · line 450
Quoted 7 lines
path.c +7
-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 withstrncmp_icase()?
True.
Quoted 5 lines
See
dir.c:
intstrncmp_icase(const char *a, const char *b, size_t count){ return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count); }
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
In reply to Jiang XinAm 12.09.2013 11:12, schrieb Jiang Xin:
Quoted 10 lines
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_pathhonordos_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
Re: [PATCH 1/2] relative_path should honor dos_drive_prefix
In reply to Jiang XinThank you, this fixes the problem with git svn rebase on Windows for me.
--Tvangeste
Quoted 74 lines · 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_pathhonordos_drive_prefix, and add test cases for it in t0060.Reported-by Tvangeste <[email protected]>Helped-by Johannes Sixt <[email protected]>Signed-off-by Jiang Xin <[email protected]>--- path.c | 20 ++++++++++++++++++++ t/t0060-path-utils.sh | 4 ++++ 2 files changed, 24 insertions(+)path.c +20
-0@@ -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]))t/t0060-path-utils.sh +4
-1@@ -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
v2 cover fixes for relative_path
In reply to Junio C HamanoUpdates 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(-)
Signature · 1 line
1.8.4.459.gd80d422
PATCH v2 1/3 test: use unambigous leading path (/foo) for mingw
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.
--- t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-)
t/t0060-path-utils.sh +28 -28
@@ -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
Signature · 1 line
1.8.4.459.gd80d422
Re: [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw
Quoted 4 lines · 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.
"DOS drive", you mean?
Are they really spelled as /a or /x (not e.g. //a or something)?
Just double-checking.
Quoted 71 lines
Signed-off-by Jiang Xin <[email protected]>--- t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-)t/t0060-path-utils.sh +28
-28@@ -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
Re: [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw
Quoted 7 lines · Junio C Hamano
Quoted 4 lines · 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.
Quoted 5 lines
"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
Re: [PATCH v2 1/3] test: use unambigous leading path (/foo) for mingw
Quoted 9 lines · Torsten Bögershausen
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.
PATCH v2 2/3 relative_path should honor dos_drive_prefix
In reply to Jiang XinTvangeste 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.
--- path.c | 20 ++++++++++++++++++++ t/t0060-path-utils.sh | 4 ++++ 2 files changed, 24 insertions(+)
path.c +20 -0
@@ -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]))
t/t0060-path-utils.sh +4 -0
@@ -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 ./
Signature · 1 line
1.8.4.459.gd80d422
Re: [PATCH v2 2/3] relative_path should honor dos_drive_prefix
Quoted 26 lines · 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_pathhonordos_drive_prefix, and add test cases for it in t0060.Reported-by Tvangeste <[email protected]>Helped-by Johannes Sixt <[email protected]>Signed-off-by Jiang Xin <[email protected]>--- path.c | 20 ++++++++++++++++++++ t/t0060-path-utils.sh | 4 ++++ 2 files changed, 24 insertions(+)path.c +0
-0@@ -434,6 +434,16 @@ int adjust_shared_perm(const char *path)return 0 ; }
path.c int adjust_shared_perm(const char *path) · line 446
Quoted 10 lines
path.c +10
-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]
Quoted 8 lines
path.c +0
-0while (i < prefix_len && j < in_len && prefix[i] == in[j]) {if (is_dir_sep (prefix[i])) {while (is_dir_sep (prefix[i]))t/t0060-path-utils.sh +0
-0
t/t0060-path-utils.sh relative_path foo/a/b/ foo/a/b ./ · line 216
Quoted 7 lines
t/t0060-path-utils.sh +4
-0@@ -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.
PATCH v2 3/3 Use simpler relative_path when set_git_dir
In reply to Jiang XinUsing 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.
--- cache.h | 1 + path.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ setup.c | 5 +---- 3 files changed, 47 insertions(+), 4 deletions(-)
cache.h +1 -0
@@ -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);
path.c +45 -0
51 lines not on this page · raw message
setup.c +1 -4
@@ -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)
Signature · 1 line
1.8.4.459.gd80d422