{"thread":{"id":"34897","subject":"Regression in e02ca72: git svn rebase is broken on Windows","startedAt":"2013-09-10T13:14:08Z","lastAt":"2013-10-14T19:40:59Z","messageCount":48,"participants":["Tvangeste","Johannes Schindelin","Johannes Sixt","Junio C Hamano","Karsten Blees","Jiang Xin","Torsten Bögershausen","Sebastian Schuberth","Eric Sunshine"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"227319","messageId":"17231378818848@web5m.yandex.ru","threadId":"34897","inReplyTo":null,"subject":"Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Tvangeste","fromEmail":"i.4m.l33t@yandex.ru","sentAt":"2013-09-10T13:14:08Z","receivedAt":"2013-09-10T13:14:08Z","isPatch":false,"sender":{"key":"i.4m.l33t@yandex.ru","avatar":"https://gravatar.com/avatar/b40fe0cdae82b9e9153fa70da65df3a82d265376a8ee7ac5985a91e36b0bad98?d=mp&s=160"},"body":"Hi,\n\nAfter bisecting this problem I ended up with the mentioned commit that completely breaks git-svn for me on Windows (mingw/msys version).\n\n==========\n#> git svn rebase\nwarning: unable to access '': Invalid argument\nwarning: unable to access '': Invalid argument\nfatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument\nfatal: index file open failed: Invalid argument\nCannot rebase: You have unstaged changes.\nPlease commit or stash them.\nrebase refs/remotes/trunk: command returned error: 1\n==========\n\nPlease note that I use the official git repository as-is, this one (no additional patches):\ngit://git.kernel.org/pub/scm/git/git.git\n\ne02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit\ncommit e02ca72f70ed8f0268a81f72cb3230c72e538e77\nAuthor: Jiang Xin\nDate:   Tue Jun 25 23:53:43 2013 +0800\n\n    path.c: refactor relative_path(), not only strip prefix\n\nThanks,\n  --Tvangeste\n"},{"id":"227324","messageId":"alpine.DEB.1.00.1309101812450.1191@s15462909.onlinehome-server.info","threadId":"34897","inReplyTo":"17231378818848@web5m.yandex.ru","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2013-09-10T16:13:10Z","receivedAt":"2013-09-10T16:13:10Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Tvangeste,\n\nOn Tue, 10 Sep 2013, Tvangeste wrote:\n\n> After bisecting this problem I ended up with the mentioned commit that\n> completely breaks git-svn for me on Windows (mingw/msys version).\n\nHave you tried with Git for Windows yet?\n\nCiao,\nJohannes\n"},{"id":"227328","messageId":"522F4E69.5070501@kdbg.org","threadId":"34897","inReplyTo":"17231378818848@web5m.yandex.ru","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2013-09-10T16:52:57Z","receivedAt":"2013-09-10T16:52:57Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 10.09.2013 15:14, schrieb Tvangeste:\n> After bisecting this problem I ended up with the mentioned commit\n> that completely breaks git-svn for me on Windows (mingw/msys version).\n> \n> ==========\n> #> git svn rebase\n> warning: unable to access '': Invalid argument\n> warning: unable to access '': Invalid argument\n> fatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument\n> fatal: index file open failed: Invalid argument\n> Cannot rebase: You have unstaged changes.\n> Please commit or stash them.\n> rebase refs/remotes/trunk: command returned error: 1\n> ==========\n\nCan you please run the command with GIT_TRACE=2?\n\n-- Hannes\n"},{"id":"227331","messageId":"xmqq38pczjw6.fsf@gitster.dls.corp.google.com","threadId":"34897","inReplyTo":"17231378818848@web5m.yandex.ru","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-10T17:06:17Z","receivedAt":"2013-09-10T17:06:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tvangeste <i.4m.l33t@yandex.ru> writes:\n\n> Hi,\n>\n> After bisecting this problem I ended up with the mentioned commit that completely breaks git-svn for me on Windows (mingw/msys version).\n>\n> ==========\n> #> git svn rebase\n> warning: unable to access '': Invalid argument\n> warning: unable to access '': Invalid argument\n> fatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument\n> fatal: index file open failed: Invalid argument\n> Cannot rebase: You have unstaged changes.\n> Please commit or stash them.\n> rebase refs/remotes/trunk: command returned error: 1\n> ==========\n>\n> Please note that I use the official git repository as-is, this one (no additional patches):\n> git://git.kernel.org/pub/scm/git/git.git\n>\n> e02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit\n> commit e02ca72f70ed8f0268a81f72cb3230c72e538e77\n> Author: Jiang Xin\n> Date:   Tue Jun 25 23:53:43 2013 +0800\n>\n>     path.c: refactor relative_path(), not only strip prefix\n>\n> Thanks,\n>   --Tvangeste\n\nThe suspect commit and symptom look consistent.  You started from a\ndirectory whose absolute path is \"w:/work/...\" and the updated code\nmistakenly thoguht that something that begins with \"w\" (not '/') is\nnot an absolute, so added a series of ../ to make it relative, or\nsomething silly like that.\n\nJiang?\n"},{"id":"227348","messageId":"93421378835002@web20j.yandex.ru","threadId":"34897","inReplyTo":"alpine.DEB.1.00.1309101812450.1191@s15462909.onlinehome-server.info","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Tvangeste","fromEmail":"i.4m.l33t@yandex.ru","sentAt":"2013-09-10T17:43:22Z","receivedAt":"2013-09-10T17:43:22Z","isPatch":false,"sender":{"key":"i.4m.l33t@yandex.ru","avatar":"https://gravatar.com/avatar/b40fe0cdae82b9e9153fa70da65df3a82d265376a8ee7ac5985a91e36b0bad98?d=mp&s=160"},"body":"10.09.2013, 18:13, \"Johannes Schindelin\" <Johannes.Schindelin@gmx.de>:\n> Have you tried with Git for Windows yet?\n\nWhat'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).\n\nThanks,\n  --Tvangeste\n"},{"id":"227350","messageId":"94251378835065@web20j.yandex.ru","threadId":"34897","inReplyTo":"522F4E69.5070501@kdbg.org","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Tvangeste","fromEmail":"i.4m.l33t@yandex.ru","sentAt":"2013-09-10T17:44:25Z","receivedAt":"2013-09-10T17:44:25Z","isPatch":false,"sender":{"key":"i.4m.l33t@yandex.ru","avatar":"https://gravatar.com/avatar/b40fe0cdae82b9e9153fa70da65df3a82d265376a8ee7ac5985a91e36b0bad98?d=mp&s=160"},"body":"10.09.2013, 18:53, \"Johannes Sixt\" <j6t@kdbg.org>:\n> Can you please run the command with GIT_TRACE=2?\n\nSure:\n#> git --version\ntrace: built-in: git 'version'\ngit version 1.8.4.242.gbb80ee0\n\n#> git svn rebase -l\ntrace: exec: 'git-svn' 'rebase' '-l'\ntrace: run_command: 'git-svn' 'rebase' '-l'\ntrace: built-in: git 'rev-parse' '--git-dir'\ntrace: built-in: git 'rev-parse' '--show-cdup'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.fetchall'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.noauthcache'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.nocheckout'\ntrace: built-in: git 'config' '--get' 'svn.authorsprog'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.dryrun'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.preservemerges'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.followparent'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.useSvmProps'\ntrace: built-in: git 'config' '--get' 'svn.authorsfile'\ntrace: built-in: git 'config' '--get' 'svn.username'\ntrace: built-in: git 'config' '--get' 'svn.repackflags'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.localtime'\ntrace: built-in: git 'config' '--int' '--get' 'svn.repack'\ntrace: built-in: git 'config' '--get' 'svn.ignorepaths'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.verbose'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.quiet'\ntrace: built-in: git 'config' '--int' '--get' 'svn.logwindowsize'\ntrace: built-in: git 'config' '--get' 'svn.ignorerefs'\ntrace: built-in: git 'config' '--get' 'svn.configdir'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.merge'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.addauthorfrom'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.useSvnsyncProps'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.noMetadata'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.local'\ntrace: built-in: git 'config' '--get' 'svn.strategy'\ntrace: built-in: git 'config' '--get' 'svn.includepaths'\ntrace: built-in: git 'config' '--bool' '--get' 'svn.uselogauthor'\ntrace: built-in: git 'rev-parse' '--symbolic' '--all'\ntrace: built-in: git 'config' '-l'\ntrace: built-in: git 'config' '-l'\ntrace: built-in: git 'update-index' '--refresh'\ntrace: built-in: git 'rev-list' '--first-parent' '--pretty=medium' 'HEAD' '--'\ntrace: built-in: git 'config' '--bool' 'svn.useSvmProps'\ntrace: built-in: git 'config' '-l'\ntrace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'\ntrace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'\ntrace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'\ntrace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'\ntrace: built-in: git 'for-each-ref' '--format=%(refname)' 'refs/'\ntrace: built-in: git 'config' '--get' 'svn-remote.svn.rewriteRoot'\ntrace: built-in: git 'config' '--get' 'svn-remote.svn.url'\ntrace: built-in: git 'config' '--get' 'svn-remote.svn.pushurl'\ntrace: built-in: git 'config' '--get' 'svn-remote.svn.uuid'\ntrace: built-in: git 'rev-list' '--pretty=raw' '--reverse' 'cdc459d7cedcec6bb26812e24661c7318f031be4..refs/remotes/trunk' '--'\ntrace: built-in: git 'config' '--get' 'svn-remote.svn.rewriteRoot'\ntrace: built-in: git 'config' '--get' 'svn-remote.svn.rewriteUUID'\ntrace: built-in: git 'diff-index' 'HEAD' '--'\ntrace: exec: 'git-rebase' 'refs/remotes/trunk'\ntrace: run_command: 'git-rebase' 'refs/remotes/trunk'\ntrace: built-in: git 'rev-parse' '--parseopt' '--' 'refs/remotes/trunk'\ntrace: built-in: git 'rev-parse' '--git-dir'\ntrace: built-in: git 'rev-parse' '--is-bare-repository'\ntrace: built-in: git 'rev-parse' '--show-toplevel'\ntrace: built-in: git 'config' '--bool' 'rebase.stat'\ntrace: built-in: git 'config' '--bool' 'rebase.autostash'\ntrace: built-in: git 'config' '--bool' 'rebase.autosquash'\ntrace: built-in: git 'rev-parse' '--verify' 'refs/remotes/trunk^0'\ntrace: built-in: git 'rev-parse' '--verify' 'refs/remotes/trunk^0'\ntrace: built-in: git 'symbolic-ref' '-q' 'HEAD'\ntrace: built-in: git 'rev-parse' '--verify' 'HEAD'\ntrace: built-in: git 'rev-parse' '--verify' 'HEAD'\ntrace: built-in: git 'update-index' '-q' '--ignore-submodules' '--refresh'\nfatal: unable to access '../../../../w:/work/xxx/xxx-xxx-OSS.git.new/.git/config': Invalid argument\ntrace: built-in: git 'diff-files' '--quiet' '--ignore-submodules'\nfatal: index file open failed: Invalid argument\nCannot rebase: You have unstaged changes.\ntrace: built-in: git 'diff-index' '--cached' '--quiet' '--ignore-submodules' 'HEAD' '--'\nPlease commit or stash them.\nrebase refs/remotes/trunk: command returned error: 1\n\nThanks,\n  --Tvangeste\n"},{"id":"227351","messageId":"alpine.DEB.1.00.1309101958480.1191@s15462909.onlinehome-server.info","threadId":"34897","inReplyTo":"93421378835002@web20j.yandex.ru","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2013-09-10T18:02:14Z","receivedAt":"2013-09-10T18:02:14Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Tvangeste,\n\nOn Tue, 10 Sep 2013, Tvangeste wrote:\n\n> 10.09.2013, 18:13, \"Johannes Schindelin\" <Johannes.Schindelin@gmx.de>:\n> > Have you tried with Git for Windows yet?\n> \n> What's Git for Windows? If you mean msysgit,\n\nActually, they are two different things: Git for Windows is what the name\nsays, and it comes with an installer. msysGit is the development\nenvironment to *build* Git for Windows.\n\n> then I say no, because the latest msysgit version is from June 02, and\n> the change under discussion was made later on, on June 25th. So, this\n> regression is not in msysgit release (yet).\n\nGiven the explanation what msysGit is, you might suspect that I'd like you\nto try to fix this in the msysGit context: After installing\n\n\thttps://code.google.com/p/msysgit/downloads/list?q=net+installer\n\nyou will have a full build environment, including the build of our latest\nmaster. You can then \"cd /git/\" and \"git checkout pt/tentative-1.8.4 &&\nmake install\" to make sure that the version we are very close to releasing\nas the new Git for Windows version does not break your workflow.\n\nCiao,\nJohannes\n\n-- \n-- \n*** Please reply-to-all at all times ***\n*** (do not pretend to know who is subscribed and who is not) ***\n*** Please avoid top-posting. ***\nThe msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.\n\nYou received this message because you are subscribed to the Google\nGroups \"msysGit\" group.\nTo post to this group, send email to msysgit@googlegroups.com\nTo unsubscribe from this group, send email to\nmsysgit+unsubscribe@googlegroups.com\nFor more options, and view previous threads, visit this group at\nhttp://groups.google.com/group/msysgit?hl=en_US?hl=en\n\n--- \nYou received this message because you are subscribed to the Google Groups \"msysGit\" group.\nTo unsubscribe from this group and stop receiving emails from it, send an email to msysgit+unsubscribe@googlegroups.com.\nFor more options, visit https://groups.google.com/groups/opt_out.\n"},{"id":"227366","messageId":"6821378846401@web12g.yandex.ru","threadId":"34897","inReplyTo":"alpine.DEB.1.00.1309101958480.1191@s15462909.onlinehome-server.info","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Tvangeste","fromEmail":"i.4m.l33t@yandex.ru","sentAt":"2013-09-10T20:53:21Z","receivedAt":"2013-09-10T20:53:21Z","isPatch":false,"sender":{"key":"i.4m.l33t@yandex.ru","avatar":"https://gravatar.com/avatar/b40fe0cdae82b9e9153fa70da65df3a82d265376a8ee7ac5985a91e36b0bad98?d=mp&s=160"},"body":"10.09.2013, 20:02, \"Johannes Schindelin\" <Johannes.Schindelin@gmx.de>:\n>  Given the explanation what msysGit is, you might suspect that I'd like you\n>  to try to fix this in the msysGit context: After installing\n>\n>          https://code.google.com/p/msysgit/downloads/list?q=net+installer\n\nNo problem. Here's what I have so far:\n\n1. 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):\n\n1a. On CMD: everything is fine.\n1b. On msys shell: everything is fine.\n\n2. Checked out the branch you've suggested to try (pt/tentative-1.8.4) and installed it. Tried the new version:\n\n2a. On CMD: got the problem that is being discussed in this thread.\n2b. On msys shell: everything is fine.\n\nSo, 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.\n\nThanks,\n  --Tvangeste\n"},{"id":"227377","messageId":"loom.20130911T001650-550@post.gmane.org","threadId":"34897","inReplyTo":"xmqq38pczjw6.fsf@gitster.dls.corp.google.com","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Karsten Blees","fromEmail":"karsten.blees@gmail.com","sentAt":"2013-09-10T22:17:17Z","receivedAt":"2013-09-10T22:17:17Z","isPatch":false,"sender":{"key":"karsten.blees@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1111200?v=4"},"body":"Junio C Hamano <gitster <at> pobox.com> writes:\n\n> \n> Tvangeste <i.4m.l33t <at> yandex.ru> writes:\n> \n> > Hi,\n> >\n> > After bisecting this problem I ended up with the mentioned commit that\ncompletely breaks git-svn for me on\n> Windows (mingw/msys version).\n> >\n> > ==========\n> > #> git svn rebase\n> > warning: unable to access '': Invalid argument\n> > warning: unable to access '': Invalid argument\n> > fatal: unable to access '../../../../w:/work/my/repo.git/.git/config':\nInvalid argument\n> > fatal: index file open failed: Invalid argument\n> > Cannot rebase: You have unstaged changes.\n> > Please commit or stash them.\n> > rebase refs/remotes/trunk: command returned error: 1\n> > ==========\n> >\n> > Please note that I use the official git repository as-is, this one (no\nadditional patches):\n> > git://git.kernel.org/pub/scm/git/git.git\n> >\n> > e02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit\n> > commit e02ca72f70ed8f0268a81f72cb3230c72e538e77\n> > Author: Jiang Xin\n> > Date:   Tue Jun 25 23:53:43 2013 +0800\n> >\n> >     path.c: refactor relative_path(), not only strip prefix\n> >\n> > Thanks,\n> >   --Tvangeste\n> \n> The suspect commit and symptom look consistent.  You started from a\n> directory whose absolute path is \"w:/work/...\" and the updated code\n> mistakenly thoguht that something that begins with \"w\" (not '/') is\n> not an absolute, so added a series of ../ to make it relative, or\n> something silly like that.\n> \n> Jiang?\n> \n\nIndeed, this patch seems to change relative_path in a way that breaks git\ninitialization, not just on Windows.\n\nPreviously, relative_path was always called with two absolute paths, and it\nonly returned a relative path if the first was a subdir of the second (so a\nbetter name would probably have been 'relative_path_if_subdir'). The purpose\nwas to improve performance by making GIT_DIR shorter if it was a subdir of\nGIT_WORK_TREE.\n\nAfter this patch, relative_path always tries to return a relative path, even\nif both absolute paths are completely disjunct. This not only defeats the\npurpose (by making GIT_DIR longer, thus hurting performance), it is also not\npossible in general. POSIX explicitly allows for '//hostname' notation\nreferring to network resources that are not explicitly mounted under '/'.\nI.e. given two absolute paths '//hostname1/a' and '//hostname2/b', there is\nno relative path from a to b or vice versa.\n\nAdditionally, GIT_DIR now may or may not have a trailing slash, which gives\nme a slightly uneasy feeling...\n"},{"id":"227404","messageId":"CANYiYbFaNP=UUKX-5N7qQppMRehuPgn8p1uN_UOJ6bDwTjzKEQ@mail.gmail.com","threadId":"34897","inReplyTo":"xmqq38pczjw6.fsf@gitster.dls.corp.google.com","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-11T03:19:18Z","receivedAt":"2013-09-11T03:19:18Z","isPatch":false,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2013/9/11 Junio C Hamano <gitster@pobox.com>:\n> Tvangeste <i.4m.l33t@yandex.ru> writes:\n>\n>> Hi,\n>>\n>> After bisecting this problem I ended up with the mentioned commit that completely breaks git-svn for me on Windows (mingw/msys version).\n>>\n>> ==========\n>> #> git svn rebase\n>> warning: unable to access '': Invalid argument\n>> warning: unable to access '': Invalid argument\n>> fatal: unable to access '../../../../w:/work/my/repo.git/.git/config': Invalid argument\n>> fatal: index file open failed: Invalid argument\n>> Cannot rebase: You have unstaged changes.\n>> Please commit or stash them.\n>> rebase refs/remotes/trunk: command returned error: 1\n>> ==========\n>>\n>> Please note that I use the official git repository as-is, this one (no additional patches):\n>> git://git.kernel.org/pub/scm/git/git.git\n>>\n>> e02ca72f70ed8f0268a81f72cb3230c72e538e77 is the first bad commit\n>> commit e02ca72f70ed8f0268a81f72cb3230c72e538e77\n>> Author: Jiang Xin\n>> Date:   Tue Jun 25 23:53:43 2013 +0800\n>>\n>>     path.c: refactor relative_path(), not only strip prefix\n>>\n>> Thanks,\n>>   --Tvangeste\n>\n> The suspect commit and symptom look consistent.  You started from a\n> directory whose absolute path is \"w:/work/...\" and the updated code\n> mistakenly thoguht that something that begins with \"w\" (not '/') is\n> not an absolute, so added a series of ../ to make it relative, or\n> something silly like that.\n>\n> Jiang?\n\nI tested 'relative_path' function using 'test-path-utils', and got the\nfollowing result:\n\n    $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'\n    ../../../C:/a/b\n\n    $ ./test-path-utils relative_path '/a/b' 'x/y'\n    ../..//a/b\n\n    $ ./test-path-utils relative_path 'a/b' '/x/y'\n    ../../../a/b\n\nFor the first case, in and prefix are on different ROOT, and for the other\ntwo cases, one path is a relative path, and another is an absolute path.\n\nI write a patch to test whether two paths (in and prefix) have the same\nroot. The result after applied the patch:\n\n    $ ./test-path-utils relative_path 'C:/a/b' 'C:/x/y'\n    ../../a/b\n\n    $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'\n    C:/a/b\n\n    $ ./test-path-utils relative_path '/a/b' 'x/y'\n    /a/b\n\n    $ ./test-path-utils relative_path 'a/b' '/x/y'\n    a/b\n\n\ndiff --git a/path.c b/path.c\nindex 7f3324a..51f5d28 100644\n--- a/path.c\n+++ b/path.c\n@@ -441,6 +441,25 @@ int adjust_shared_perm(const char *path)\n        return 0;\n }\n\n+static int have_same_root(const char *path1, const char *path2)\n+{\n+       /* for POSIX:\n+\n+          return ((path1 && is_dir_sep(*path1)) ^\n+                  (path2 && is_dir_sep(*path2))) == 0;\n+       */\n+       return path1 && path2 && *path1 && *path2 && (\n+               (is_dir_sep(*path1) &&\n+                is_dir_sep(*path2)) ||\n+               (*(path1+1) == ':' &&\n+                *(path2+1) == ':' &&\n+                !strncasecmp(path1, path2, 1)) ||\n+               (!is_dir_sep(*path1) &&\n+                !is_dir_sep(*path2) &&\n+                *(path1+1) != ':' &&\n+                *(path2+1) != ':'));\n+}\n+\n /*\n  * Give path as relative to prefix.\n  *\n@@ -461,6 +480,9 @@ const char *relative_path(const char *in, const\nchar *prefix,\n        else if (!prefix_len)\n                return in;\n\n+       if (!have_same_root(in, prefix))\n+               return in;\n+\n\nShould I write the function have_same_root as inline function or macro\nlike 'is_dir_sep'?\n\n-- \nJiang Xin\n"},{"id":"227405","messageId":"CANYiYbECYK90Hp49rd9Ow8X_CdcnKREeSafwHTXRnut+qABMqA@mail.gmail.com","threadId":"34897","inReplyTo":"loom.20130911T001650-550@post.gmane.org","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-11T04:41:09Z","receivedAt":"2013-09-11T04:41:09Z","isPatch":false,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2013/9/11 Karsten Blees <karsten.blees@gmail.com>:\n> Junio C Hamano <gitster <at> pobox.com> writes:\n>\n>> The suspect commit and symptom look consistent.  You started from a\n>> directory whose absolute path is \"w:/work/...\" and the updated code\n>> mistakenly thoguht that something that begins with \"w\" (not '/') is\n>> not an absolute, so added a series of ../ to make it relative, or\n>> something silly like that.\n>>\n>> Jiang?\n>>\n>\n> Indeed, this patch seems to change relative_path in a way that breaks git\n> initialization, not just on Windows.\n>\n> Previously, relative_path was always called with two absolute paths, and it\n> only returned a relative path if the first was a subdir of the second (so a\n> better name would probably have been 'relative_path_if_subdir'). The purpose\n> was to improve performance by making GIT_DIR shorter if it was a subdir of\n> GIT_WORK_TREE.\n\nYes, it's what commit v1.5.6-1-g044bbbc says.\n\n> After this patch, relative_path always tries to return a relative path, even\n> if both absolute paths are completely disjunct. This not only defeats the\n> purpose (by making GIT_DIR longer, thus hurting performance), it is also not\n\nSometimes longer, sometimes shorter maybe.\n\n> possible in general. POSIX explicitly allows for '//hostname' notation\n> referring to network resources that are not explicitly mounted under '/'.\n> I.e. given two absolute paths '//hostname1/a' and '//hostname2/b', there is\n> no relative path from a to b or vice versa.\n\nYes, path like \"//hostname/path\" can be used on Windows.\nMy hack \"have_same_root\" does not cover this case, so using\na \"simple_relative_path\" function instead of \"relative_path\" in setup.c\nmay be the better.\n\n\n-- \nJiang Xin\n"},{"id":"227406","messageId":"523002EB.3010706@kdbg.org","threadId":"34897","inReplyTo":"CANYiYbFaNP=UUKX-5N7qQppMRehuPgn8p1uN_UOJ6bDwTjzKEQ@mail.gmail.com","subject":"Re: Regression in e02ca72: git svn rebase is broken on Windows","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2013-09-11T05:43:07Z","receivedAt":"2013-09-11T05:43:07Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 11.09.2013 05:19, schrieb Jiang Xin:\n> I tested 'relative_path' function using 'test-path-utils', and got the\n> following result:\n> \n>     $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'\n>     ../../../C:/a/b\n> \n>     $ ./test-path-utils relative_path '/a/b' 'x/y'\n>     ../..//a/b\n> \n>     $ ./test-path-utils relative_path 'a/b' '/x/y'\n>     ../../../a/b\n> \n> For the first case, in and prefix are on different ROOT, and for the other\n> two cases, one path is a relative path, and another is an absolute path.\n> \n> I write a patch to test whether two paths (in and prefix) have the same\n> root. The result after applied the patch:\n> \n>     $ ./test-path-utils relative_path 'C:/a/b' 'C:/x/y'\n>     ../../a/b\n> \n>     $ ./test-path-utils relative_path 'C:/a/b' 'D:/x/y'\n>     C:/a/b\n> \n>     $ ./test-path-utils relative_path '/a/b' 'x/y'\n>     /a/b\n> \n>     $ ./test-path-utils relative_path 'a/b' '/x/y'\n>     a/b\n> \n> \n> diff --git a/path.c b/path.c\n> index 7f3324a..51f5d28 100644\n> --- a/path.c\n> +++ b/path.c\n> @@ -441,6 +441,25 @@ int adjust_shared_perm(const char *path)\n>         return 0;\n>  }\n> \n> +static int have_same_root(const char *path1, const char *path2)\n> +{\n> +       /* for POSIX:\n> +\n> +          return ((path1 && is_dir_sep(*path1)) ^\n> +                  (path2 && is_dir_sep(*path2))) == 0;\n> +       */\n> +       return path1 && path2 && *path1 && *path2 && (\n> +               (is_dir_sep(*path1) &&\n> +                is_dir_sep(*path2)) ||\n> +               (*(path1+1) == ':' &&\n> +                *(path2+1) == ':' &&\n> +                !strncasecmp(path1, path2, 1)) ||\n> +               (!is_dir_sep(*path1) &&\n> +                !is_dir_sep(*path2) &&\n> +                *(path1+1) != ':' &&\n> +                *(path2+1) != ':'));\n\nI think this can be simplified to\n\n\treturn path1 && path2 &&\n\t\tis_absolute_path(path1) &&\n\t\tis_absolute_path(path2) &&\n\t\t!strncasecmp(path1, path2, 1);\n\nwhich would not mistake a path D:/foo on Unix as an absolute path.\n\n> +}\n\n-- Hannes\n\n-- \n-- \n*** Please reply-to-all at all times ***\n*** (do not pretend to know who is subscribed and who is not) ***\n*** Please avoid top-posting. ***\nThe msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.\n\nYou received this message because you are subscribed to the Google\nGroups \"msysGit\" group.\nTo post to this group, send email to msysgit@googlegroups.com\nTo unsubscribe from this group, send email to\nmsysgit+unsubscribe@googlegroups.com\nFor more options, and view previous threads, visit this group at\nhttp://groups.google.com/group/msysgit?hl=en_US?hl=en\n\n--- \nYou received this message because you are subscribed to the Google Groups \"msysGit\" group.\nTo unsubscribe from this group and stop receiving emails from it, send an email to msysgit+unsubscribe@googlegroups.com.\nFor more options, visit https://groups.google.com/groups/opt_out.\n"},{"id":"227512","messageId":"0688d5a5bd194ff5808c555e8e75132e2c687368.1378977052.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"xmqq38pczjw6.fsf@gitster.dls.corp.google.com","subject":"[PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-12T09:12:42Z","receivedAt":"2013-09-12T09:12:42Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Tvangeste found that the \"relative_path\" function could not work\nproperly on Windows if \"in\" and \"prefix\" have dos driver prefix.\n($gmane/234434)\n\ne.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\nshould return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n\nSo make relative_path honor dos_drive_prefix, and add test cases\nfor it in t0060.\n\nReported-by: Tvangeste <i.4m.l33t@yandex.ru>\nHelped-by: Johannes Sixt <j6t@kdbg.org>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n path.c                | 20 ++++++++++++++++++++\n t/t0060-path-utils.sh |  4 ++++\n 2 files changed, 24 insertions(+)\n\ndiff --git a/path.c b/path.c\nindex 7f3324a..ffcdea1 100644\n--- a/path.c\n+++ b/path.c\n@@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)\n \treturn 0;\n }\n \n+static int have_same_root(const char *path1, const char *path2)\n+{\n+\tint is_abs1, is_abs2;\n+\n+\tis_abs1 = is_absolute_path(path1);\n+\tis_abs2 = is_absolute_path(path2);\n+\treturn (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||\n+\t       (!is_abs1 && !is_abs2);\n+}\n+\n /*\n  * Give path as relative to prefix.\n  *\n@@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,\n \telse if (!prefix_len)\n \t\treturn in;\n \n+\tif (have_same_root(in, prefix)) {\n+\t\t/* bypass dos_drive, for \"c:\" is identical to \"C:\" */\n+\t\tif (has_dos_drive_prefix(in)) {\n+\t\t\ti = 2;\n+\t\t\tj = 2;\n+\t\t}\n+\t} else {\n+\t\treturn in;\n+\t}\n+\n \twhile (i < prefix_len && j < in_len && prefix[i] == in[j]) {\n \t\tif (is_dir_sep(prefix[i])) {\n \t\t\twhile (is_dir_sep(prefix[i]))\ndiff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\nindex 76c7792..c3c3b33 100755\n--- a/t/t0060-path-utils.sh\n+++ b/t/t0060-path-utils.sh\n@@ -208,6 +208,10 @@ relative_path a/b/\ta/b\t\t./\n relative_path a\t\ta/b\t\t../\n relative_path x/y\ta/b\t\t../../x/y\n relative_path a/c\ta/b\t\t../c\n+relative_path a/b\t/x/y\t\ta/b\n+relative_path /a/b\tx/y\t\t/a/b\tPOSIX\n+relative_path d:/a/b\tD:/a/c\t\t../b\tMINGW\n+relative_path C:/a/b\tD:/a/c\t\tC:/a/b\tMINGW\n relative_path a/b\t\"<empty>\"\ta/b\n relative_path a/b \t\"<null>\"\ta/b\n relative_path \"<empty>\"\t/a/b\t\t./\n-- \n1.8.3.rc2.14.g5ac1b82\n"},{"id":"227513","messageId":"121215a0837321e57c3918784d3de9597c9fc292.1378977052.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"0688d5a5bd194ff5808c555e8e75132e2c687368.1378977052.git.worldhello.net@gmail.com","subject":"[PATCH 2/2] Use simpler relative_path when set_git_dir","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-12T09:12:43Z","receivedAt":"2013-09-12T09:12:43Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.\nIt will make git_dir shorter only if git_dir is inside work_tree,\nand this will increase performance. But my last refactor effort on\nrelative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.\nAlways use relative_path as git_dir may bring troubles like\n$gmane/234434.\n\nBecause new relative_path is a combination of original relative_path\nfrom path.c and original path_relative from quote.c, so in order to\nrestore the origin implementation, save the original relative_path\nto simple_relative_path, and call it in setup.c.\n\nSuggested-by: Karsten Blees <karsten.blees@gmail.com>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n cache.h |  1 +\n path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++\n setup.c |  5 +----\n 3 files changed, 47 insertions(+), 4 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 8e42256..ab17f1d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -738,6 +738,7 @@ const char *real_path(const char *path);\n const char *real_path_if_valid(const char *path);\n const char *absolute_path(const char *path);\n const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);\n+const char *simple_relative_path(const char *in, const char *prefix);\n int normalize_path_copy(char *dst, const char *src);\n int longest_ancestor_length(const char *path, struct string_list *prefixes);\n char *strip_path_suffix(const char *path, const char *suffix);\ndiff --git a/path.c b/path.c\nindex ffcdea1..0f0c92f 100644\n--- a/path.c\n+++ b/path.c\n@@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,\n }\n \n /*\n+ * A simpler implementation of relative_path\n+ *\n+ * Get relative path by removing \"prefix\" from \"in\". This function\n+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter\n+ * to increase performance when traversing the path to work_tree.\n+ */\n+const char *simple_relative_path(const char *in, const char *prefix)\n+{\n+\tstatic char buf[PATH_MAX + 1];\n+\tint i = 0, j = 0;\n+\n+\tif (!prefix || !prefix[0])\n+\t\treturn in;\n+\twhile (prefix[i]) {\n+\t\tif (is_dir_sep(prefix[i])) {\n+\t\t\tif (!is_dir_sep(in[j]))\n+\t\t\t\treturn in;\n+\t\t\twhile (is_dir_sep(prefix[i]))\n+\t\t\t\ti++;\n+\t\t\twhile (is_dir_sep(in[j]))\n+\t\t\t\tj++;\n+\t\t\tcontinue;\n+\t\t} else if (in[j] != prefix[i]) {\n+\t\t\treturn in;\n+\t\t}\n+\t\ti++;\n+\t\tj++;\n+\t}\n+\tif (\n+\t    /* \"/foo\" is a prefix of \"/foo\" */\n+\t    in[j] &&\n+\t    /* \"/foo\" is not a prefix of \"/foobar\" */\n+\t    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])\n+\t   )\n+\t\treturn in;\n+\twhile (is_dir_sep(in[j]))\n+\t\tj++;\n+\tif (!in[j])\n+\t\tstrcpy(buf, \".\");\n+\telse\n+\t\tstrcpy(buf, in + j);\n+\treturn buf;\n+}\n+\n+/*\n  * It is okay if dst == src, but they should not overlap otherwise.\n  *\n  * Performs the following normalizations on src, storing the result in dst:\ndiff --git a/setup.c b/setup.c\nindex 0d9ea62..f4be6ff 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -360,7 +360,6 @@ int is_inside_work_tree(void)\n \n void setup_work_tree(void)\n {\n-\tstruct strbuf sb = STRBUF_INIT;\n \tconst char *work_tree, *git_dir;\n \tstatic int initialized = 0;\n \n@@ -380,10 +379,8 @@ void setup_work_tree(void)\n \tif (getenv(GIT_WORK_TREE_ENVIRONMENT))\n \t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, \".\", 1);\n \n-\tset_git_dir(relative_path(git_dir, work_tree, &sb));\n+\tset_git_dir(simple_relative_path(git_dir, work_tree));\n \tinitialized = 1;\n-\n-\tstrbuf_release(&sb);\n }\n \n static int check_repository_format_gently(const char *gitdir, int *nongit_ok)\n-- \n1.8.3.rc2.14.g5ac1b82\n"},{"id":"227517","messageId":"CAB9kjA4YdEa0RQvf9noDCr9GtBabvajBxgH=JF+Bd1ta=CxnyQ@mail.gmail.com","threadId":"34897","inReplyTo":"0688d5a5bd194ff5808c555e8e75132e2c687368.1378977052.git.worldhello.net@gmail.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Tvangeste","fromEmail":"i.4m.l33t@yandex.ru","sentAt":"2013-09-12T09:32:59Z","receivedAt":"2013-09-12T09:32:59Z","isPatch":true,"sender":{"key":"i.4m.l33t@yandex.ru","avatar":"https://gravatar.com/avatar/b40fe0cdae82b9e9153fa70da65df3a82d265376a8ee7ac5985a91e36b0bad98?d=mp&s=160"},"body":"Thank you, this fixes the problem with `git svn rebase` on Windows for me.\n\n--Tvangeste\n\nOn Thu, Sep 12, 2013 at 11:12 AM, Jiang Xin <worldhello.net@gmail.com> wrote:\n> Tvangeste found that the \"relative_path\" function could not work\n> properly on Windows if \"in\" and \"prefix\" have dos driver prefix.\n> ($gmane/234434)\n>\n> e.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\n> should return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n>\n> So make relative_path honor dos_drive_prefix, and add test cases\n> for it in t0060.\n>\n> Reported-by: Tvangeste <i.4m.l33t@yandex.ru>\n> Helped-by: Johannes Sixt <j6t@kdbg.org>\n> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>\n> ---\n>  path.c                | 20 ++++++++++++++++++++\n>  t/t0060-path-utils.sh |  4 ++++\n>  2 files changed, 24 insertions(+)\n>\n> diff --git a/path.c b/path.c\n> index 7f3324a..ffcdea1 100644\n> --- a/path.c\n> +++ b/path.c\n> @@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)\n>         return 0;\n>  }\n>\n> +static int have_same_root(const char *path1, const char *path2)\n> +{\n> +       int is_abs1, is_abs2;\n> +\n> +       is_abs1 = is_absolute_path(path1);\n> +       is_abs2 = is_absolute_path(path2);\n> +       return (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||\n> +              (!is_abs1 && !is_abs2);\n> +}\n> +\n>  /*\n>   * Give path as relative to prefix.\n>   *\n> @@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,\n>         else if (!prefix_len)\n>                 return in;\n>\n> +       if (have_same_root(in, prefix)) {\n> +               /* bypass dos_drive, for \"c:\" is identical to \"C:\" */\n> +               if (has_dos_drive_prefix(in)) {\n> +                       i = 2;\n> +                       j = 2;\n> +               }\n> +       } else {\n> +               return in;\n> +       }\n> +\n>         while (i < prefix_len && j < in_len && prefix[i] == in[j]) {\n>                 if (is_dir_sep(prefix[i])) {\n>                         while (is_dir_sep(prefix[i]))\n> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\n> index 76c7792..c3c3b33 100755\n> --- a/t/t0060-path-utils.sh\n> +++ b/t/t0060-path-utils.sh\n> @@ -208,6 +208,10 @@ relative_path a/b/ a/b             ./\n>  relative_path a                a/b             ../\n>  relative_path x/y      a/b             ../../x/y\n>  relative_path a/c      a/b             ../c\n> +relative_path a/b      /x/y            a/b\n> +relative_path /a/b     x/y             /a/b    POSIX\n> +relative_path d:/a/b   D:/a/c          ../b    MINGW\n> +relative_path C:/a/b   D:/a/c          C:/a/b  MINGW\n>  relative_path a/b      \"<empty>\"       a/b\n>  relative_path a/b      \"<null>\"        a/b\n>  relative_path \"<empty>\"        /a/b            ./\n> --\n> 1.8.3.rc2.14.g5ac1b82\n>\n"},{"id":"227532","messageId":"5231CBFA.3070806@web.de","threadId":"34897","inReplyTo":"0688d5a5bd194ff5808c555e8e75132e2c687368.1378977052.git.worldhello.net@gmail.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2013-09-12T14:13:14Z","receivedAt":"2013-09-12T14:13:14Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2013-09-12 11.12, Jiang Xin wrote:\n> Tvangeste found that the \"relative_path\" function could not work\n> properly on Windows if \"in\" and \"prefix\" have dos driver prefix.\n> ($gmane/234434)\n> \n> e.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\n> should return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n> \n> So make relative_path honor dos_drive_prefix, and add test cases\n> for it in t0060.\n> \n> Reported-by: Tvangeste <i.4m.l33t@yandex.ru>\n> Helped-by: Johannes Sixt <j6t@kdbg.org>\n> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>\n> ---\n>  path.c                | 20 ++++++++++++++++++++\n>  t/t0060-path-utils.sh |  4 ++++\n>  2 files changed, 24 insertions(+)\n> \n> diff --git a/path.c b/path.c\n> index 7f3324a..ffcdea1 100644\n> --- a/path.c\n> +++ b/path.c\n> @@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)\n>  \treturn 0;\n>  }\n>  \n> +static int have_same_root(const char *path1, const char *path2)\n> +{\n> +\tint is_abs1, is_abs2;\n> +\n> +\tis_abs1 = is_absolute_path(path1);\n> +\tis_abs2 = is_absolute_path(path2);\n> +\treturn (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||\n                                       ^^^^^^^^^^^\nI wonder: should strncasecmp() be replaced with strncmp_icase() ?\n\nSee dir.c: \nint strncmp_icase(const char *a, const char *b, size_t count)\n{\n\treturn ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);\n}\n/Torsten\n\n\n\n\n\n\n\n\n\n\n\n> +\t       (!is_abs1 && !is_abs2);\n> +}\n> +\n>  /*\n>   * Give path as relative to prefix.\n>   *\n> @@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,\n>  \telse if (!prefix_len)\n>  \t\treturn in;\n>  \n> +\tif (have_same_root(in, prefix)) {\n> +\t\t/* bypass dos_drive, for \"c:\" is identical to \"C:\" */\n> +\t\tif (has_dos_drive_prefix(in)) {\n> +\t\t\ti = 2;\n> +\t\t\tj = 2;\n> +\t\t}\n> +\t} else {\n> +\t\treturn in;\n> +\t}\n> +\n>  \twhile (i < prefix_len && j < in_len && prefix[i] == in[j]) {\n>  \t\tif (is_dir_sep(prefix[i])) {\n>  \t\t\twhile (is_dir_sep(prefix[i]))\n> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\n> index 76c7792..c3c3b33 100755\n> --- a/t/t0060-path-utils.sh\n> +++ b/t/t0060-path-utils.sh\n> @@ -208,6 +208,10 @@ relative_path a/b/\ta/b\t\t./\n>  relative_path a\t\ta/b\t\t../\n>  relative_path x/y\ta/b\t\t../../x/y\n>  relative_path a/c\ta/b\t\t../c\n> +relative_path a/b\t/x/y\t\ta/b\n> +relative_path /a/b\tx/y\t\t/a/b\tPOSIX\n> +relative_path d:/a/b\tD:/a/c\t\t../b\tMINGW\n> +relative_path C:/a/b\tD:/a/c\t\tC:/a/b\tMINGW\n>  relative_path a/b\t\"<empty>\"\ta/b\n>  relative_path a/b \t\"<null>\"\ta/b\n>  relative_path \"<empty>\"\t/a/b\t\t./\n> \n"},{"id":"227539","messageId":"5231E1AD.6090206@gmail.com","threadId":"34897","inReplyTo":"0688d5a5bd194ff5808c555e8e75132e2c687368.1378977052.git.worldhello.net@gmail.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Karsten Blees","fromEmail":"karsten.blees@gmail.com","sentAt":"2013-09-12T15:45:49Z","receivedAt":"2013-09-12T15:45:49Z","isPatch":true,"sender":{"key":"karsten.blees@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1111200?v=4"},"body":"Am 12.09.2013 11:12, schrieb Jiang Xin:\n> Tvangeste found that the \"relative_path\" function could not work\n> properly on Windows if \"in\" and \"prefix\" have dos driver prefix.\n> ($gmane/234434)\n> \n> e.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\n> should return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n> \n> So make relative_path honor dos_drive_prefix, and add test cases\n> for it in t0060.\n> \n\nI 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.\n\nPOSIX says the meaning of '//' is implementation-defined [1].\n\nCygwin supports //hostname/share/directory/file. You cannot cd to the hostname (i.e. root would be //hostname/share).\n\nOn Windows, we have drive letters, UNC paths and namespaces:\nC:\\directory\\file\n\\\\hostname\\share\\directory\\file (same as cygwin)\n\\\\?\\C:\\directory\\file\n\\\\?\\UNC\\hostname\\share\\directory\\file\n\nI'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).\n\n\nYou 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).\n\n[1] http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_12\n"},{"id":"227540","messageId":"xmqqwqmmoxc0.fsf@gitster.dls.corp.google.com","threadId":"34897","inReplyTo":"5231CBFA.3070806@web.de","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-12T15:48:15Z","receivedAt":"2013-09-12T15:48:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Torsten Bögershausen <tboegi@web.de> writes:\n\n>> +static int have_same_root(const char *path1, const char *path2)\n>> +{\n>> +\tint is_abs1, is_abs2;\n>> +\n>> +\tis_abs1 = is_absolute_path(path1);\n>> +\tis_abs2 = is_absolute_path(path2);\n>> +\treturn (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||\n>                                        ^^^^^^^^^^^\n> I wonder: should strncasecmp() be replaced with strncmp_icase() ?\n\nTrue.\n\n> See dir.c: \n> int strncmp_icase(const char *a, const char *b, size_t count)\n> {\n> \treturn ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);\n> }\n"},{"id":"227542","messageId":"5231F839.3080208@kdbg.org","threadId":"34897","inReplyTo":"5231CBFA.3070806@web.de","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2013-09-12T17:22:01Z","receivedAt":"2013-09-12T17:22:01Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 12.09.2013 16:13, schrieb Torsten Bögershausen:\n> On 2013-09-12 11.12, Jiang Xin wrote:\n>> +static int have_same_root(const char *path1, const char *path2)\n>> +{\n>> +\tint is_abs1, is_abs2;\n>> +\n>> +\tis_abs1 = is_absolute_path(path1);\n>> +\tis_abs2 = is_absolute_path(path2);\n>> +\treturn (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||\n>                                        ^^^^^^^^^^^\n> I wonder: should strncasecmp() be replaced with strncmp_icase() ?\n\nI don't think so: On POSIX, it is irrelevant, because the call will only\ncompare a slash to a slash. On Windows, it compares the drive letters\n(or a slash); it is *always* case-insensitive, even if the volume\nmounted is NTFS with case-sensitivity enabled and core.ignorecase is false.\n\n> See dir.c: \n> int strncmp_icase(const char *a, const char *b, size_t count)\n> {\n> \treturn ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);\n> }\n\n-- Hannes\n"},{"id":"227543","messageId":"5231FB82.5010107@kdbg.org","threadId":"34897","inReplyTo":"121215a0837321e57c3918784d3de9597c9fc292.1378977052.git.worldhello.net@gmail.com","subject":"Re: [PATCH 2/2] Use simpler relative_path when set_git_dir","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2013-09-12T17:36:02Z","receivedAt":"2013-09-12T17:36:02Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 12.09.2013 11:12, schrieb Jiang Xin:\n> Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.\n> It will make git_dir shorter only if git_dir is inside work_tree,\n> and this will increase performance. But my last refactor effort on\n> relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.\n> Always use relative_path as git_dir may bring troubles like\n> $gmane/234434.\n> \n> Because new relative_path is a combination of original relative_path\n> from path.c and original path_relative from quote.c, so in order to\n> restore the origin implementation, save the original relative_path\n> to simple_relative_path, and call it in setup.c.\n> \n> Suggested-by: Karsten Blees <karsten.blees@gmail.com>\n> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>\n> ---\n>  cache.h |  1 +\n>  path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++\n>  setup.c |  5 +----\n>  3 files changed, 47 insertions(+), 4 deletions(-)\n> \n> diff --git a/cache.h b/cache.h\n> index 8e42256..ab17f1d 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -738,6 +738,7 @@ const char *real_path(const char *path);\n>  const char *real_path_if_valid(const char *path);\n>  const char *absolute_path(const char *path);\n>  const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);\n> +const char *simple_relative_path(const char *in, const char *prefix);\n>  int normalize_path_copy(char *dst, const char *src);\n>  int longest_ancestor_length(const char *path, struct string_list *prefixes);\n>  char *strip_path_suffix(const char *path, const char *suffix);\n> diff --git a/path.c b/path.c\n> index ffcdea1..0f0c92f 100644\n> --- a/path.c\n> +++ b/path.c\n> @@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,\n>  }\n>  \n>  /*\n> + * A simpler implementation of relative_path\n\nSo we have a heavy-duty function relative_path(), but it is not capable\nof doing the \"simple\" operations that this function does?\n\nThere must be something wrong.\n\nThis function were easier to sell if it were named\nremove_optional_prefix() or something.\n\n> + *\n> + * Get relative path by removing \"prefix\" from \"in\". This function\n> + * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter\n> + * to increase performance when traversing the path to work_tree.\n> + */\n> +const char *simple_relative_path(const char *in, const char *prefix)\n> +{\n> +\tstatic char buf[PATH_MAX + 1];\n> +\tint i = 0, j = 0;\n> +\n> +\tif (!prefix || !prefix[0])\n> +\t\treturn in;\n> +\twhile (prefix[i]) {\n> +\t\tif (is_dir_sep(prefix[i])) {\n> +\t\t\tif (!is_dir_sep(in[j]))\n> +\t\t\t\treturn in;\n> +\t\t\twhile (is_dir_sep(prefix[i]))\n> +\t\t\t\ti++;\n> +\t\t\twhile (is_dir_sep(in[j]))\n> +\t\t\t\tj++;\n> +\t\t\tcontinue;\n> +\t\t} else if (in[j] != prefix[i]) {\n> +\t\t\treturn in;\n> +\t\t}\n> +\t\ti++;\n> +\t\tj++;\n> +\t}\n> +\tif (\n> +\t    /* \"/foo\" is a prefix of \"/foo\" */\n> +\t    in[j] &&\n> +\t    /* \"/foo\" is not a prefix of \"/foobar\" */\n> +\t    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])\n> +\t   )\n> +\t\treturn in;\n> +\twhile (is_dir_sep(in[j]))\n> +\t\tj++;\n> +\tif (!in[j])\n> +\t\tstrcpy(buf, \".\");\n> +\telse\n> +\t\tstrcpy(buf, in + j);\n> +\treturn buf;\n> +}\n> ...\n"},{"id":"227555","messageId":"xmqq8uz1q2i4.fsf@gitster.dls.corp.google.com","threadId":"34897","inReplyTo":"5231F839.3080208@kdbg.org","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-12T19:11:15Z","receivedAt":"2013-09-12T19:11:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j6t@kdbg.org> writes:\n\n> Am 12.09.2013 16:13, schrieb Torsten Bögershausen:\n>> On 2013-09-12 11.12, Jiang Xin wrote:\n>>> +static int have_same_root(const char *path1, const char *path2)\n>>> +{\n>>> +\tint is_abs1, is_abs2;\n>>> +\n>>> +\tis_abs1 = is_absolute_path(path1);\n>>> +\tis_abs2 = is_absolute_path(path2);\n>>> +\treturn (is_abs1 && is_abs2 && !strncasecmp(path1, path2, 1)) ||\n>>                                        ^^^^^^^^^^^\n>> I wonder: should strncasecmp() be replaced with strncmp_icase() ?\n>\n> I don't think so: On POSIX, it is irrelevant, because the call will only\n> compare a slash to a slash. On Windows, it compares the drive letters\n> (or a slash); it is *always* case-insensitive, even if the volume\n> mounted is NTFS with case-sensitivity enabled and core.ignorecase is false.\n\nAh, you are right, of course.  We could even do\n\n\ttolower(path1[0]) == tolower(path2[0])\n\nwhich might be more explicit.\n\nFor systems that need POSIX escape hatch for Apollo Domain ;-), we\nwould need a bit more work.  When both path1 and path2 begin with a\ndouble-dash, we would need to check if they match up to the next\nslash, so that\n\n - //host1/usr/src and //host1/usr/lib share the same root and the\n   former can be made to ../src relative to the latter;\n\n - //host1/usr/src and //host2/usr/lib are of separate roots.\n\nor something.\n"},{"id":"227606","messageId":"CANYiYbE6nT+9LrekWp7mryJ13RxQBSQ+p6EyQspAKBMj7oG0zQ@mail.gmail.com","threadId":"34897","inReplyTo":"xmqq8uz1q2i4.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-13T04:55:10Z","receivedAt":"2013-09-13T04:55:10Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2013/9/13 Junio C Hamano <gitster@pobox.com>:\n>\n> For systems that need POSIX escape hatch for Apollo Domain ;-), we\n> would need a bit more work.  When both path1 and path2 begin with a\n> double-dash, we would need to check if they match up to the next\n> slash, so that\n>\n>  - //host1/usr/src and //host1/usr/lib share the same root and the\n>    former can be made to ../src relative to the latter;\n>\n>  - //host1/usr/src and //host2/usr/lib are of separate roots.\n>\n> or something.\n>\n>\n\nBut how could we know which platform supports network pathnames and\nneeds such implementation.\n\n-- \nJiang Xin\n"},{"id":"227612","messageId":"xmqq7gelmfm5.fsf@gitster.dls.corp.google.com","threadId":"34897","inReplyTo":"CANYiYbE6nT+9LrekWp7mryJ13RxQBSQ+p6EyQspAKBMj7oG0zQ@mail.gmail.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-13T05:53:54Z","receivedAt":"2013-09-13T05:53:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jiang Xin <worldhello.net@gmail.com> writes:\n\n> 2013/9/13 Junio C Hamano <gitster@pobox.com>:\n>>\n>> For systems that need POSIX escape hatch for Apollo Domain ;-), we\n>> would need a bit more work.  When both path1 and path2 begin with a\n>> double-dash, we would need to check if they match up to the next\n>> slash, so that\n>>\n>>  - //host1/usr/src and //host1/usr/lib share the same root and the\n>>    former can be made to ../src relative to the latter;\n>>\n>>  - //host1/usr/src and //host2/usr/lib are of separate roots.\n>>\n>> or something.\n>\n> But how could we know which platform supports network pathnames and\n> needs such implementation.\n\nNear the end of\n\nhttp://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12\n\nis this:\n\n    If a pathname begins with two successive <slash> characters, the\n    first component following the leading <slash> characters may be\n    interpreted in an implementation-defined manner, although more than\n    two leading <slash> characters shall be treated as a single <slash>\n    character.\n\nTwo points to note are\n\n (1) Only paths that begin with exactly two slashes are special.\n\n (2) As it is \"implementation-defined\", we are not even allowed to\n     treat that //host1/usr/src and //host1/usr/lib as sharing \"the\n     same root\", and make the former to ../src relative to the\n     latter.\n\nSo in the strictest sense, we do not have to bother. As long as we\nmake sure we do not molest anything that begins with exactly two\nslashes.\n"},{"id":"227633","messageId":"52331A52.3010300@web.de","threadId":"34897","inReplyTo":"CANYiYbE6nT+9LrekWp7mryJ13RxQBSQ+p6EyQspAKBMj7oG0zQ@mail.gmail.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2013-09-13T13:59:46Z","receivedAt":"2013-09-13T13:59:46Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 13.09.13 06:55, Jiang Xin wrote:\n> 2013/9/13 Junio C Hamano <gitster@pobox.com>:\n>> For systems that need POSIX escape hatch for Apollo Domain ;-), we\n>> would need a bit more work.  When both path1 and path2 begin with a\n>> double-dash, we would need to check if they match up to the next\n>> slash, so that\n>>\n>>  - //host1/usr/src and //host1/usr/lib share the same root and the\n>>    former can be made to ../src relative to the latter;\n>>\n>>  - //host1/usr/src and //host2/usr/lib are of separate roots.\n>>\n>> or something.\n>>\n>>\n> But how could we know which platform supports network pathnames and\n> needs such implementation.\nSimilar to the has_dos_drive_prefix:\n\nFor Windows/Mingw we do like this\n\nmingw.h\n#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')\n\nAnd all other platforms defines has_dos_drive_prefix() to be 0 here\ngit-compat-util.h\n#ifndef has_dos_drive_prefix\n#define has_dos_drive_prefix(path) 0\n#endif\n\nmingw.h:\n#define has_unc_path_prefix(path) ((path)[0] == '/' && (path)[1] == '/')\n(Or may be)\n#define has_unc_path_prefix(path) (is_dir_sep((path)[0])   && is_dir_sep((path)[1]))\n \n"},{"id":"227733","messageId":"CANYiYbH9pLMx4gu1qONhy-+++ojUhPSd9F=sdRTmGWH3pSUTqQ@mail.gmail.com","threadId":"34897","inReplyTo":"xmqq7gelmfm5.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-17T08:24:13Z","receivedAt":"2013-09-17T08:24:13Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2013/9/13 Junio C Hamano <gitster@pobox.com>:\n> Jiang Xin <worldhello.net@gmail.com> writes:\n>\n>> 2013/9/13 Junio C Hamano <gitster@pobox.com>:\n>>>\n>>> For systems that need POSIX escape hatch for Apollo Domain ;-), we\n>>> would need a bit more work.  When both path1 and path2 begin with a\n>>> double-dash, we would need to check if they match up to the next\n>>> slash, so that\n>>>\n>>>  - //host1/usr/src and //host1/usr/lib share the same root and the\n>>>    former can be made to ../src relative to the latter;\n>>>\n>>>  - //host1/usr/src and //host2/usr/lib are of separate roots.\n>>>\n>>> or something.\n>>\n>> But how could we know which platform supports network pathnames and\n>> needs such implementation.\n>\n> Near the end of\n>\n> http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12\n>\n> is this:\n>\n>     If a pathname begins with two successive <slash> characters, the\n>     first component following the leading <slash> characters may be\n>     interpreted in an implementation-defined manner, although more than\n>     two leading <slash> characters shall be treated as a single <slash>\n>     character.\n>\n> Two points to note are\n>\n>  (1) Only paths that begin with exactly two slashes are special.\n>\n>  (2) As it is \"implementation-defined\", we are not even allowed to\n>      treat that //host1/usr/src and //host1/usr/lib as sharing \"the\n>      same root\", and make the former to ../src relative to the\n>      latter.\n>\n> So in the strictest sense, we do not have to bother. As long as we\n> make sure we do not molest anything that begins with exactly two\n> slashes.\n>\n\nI have checked the behavior of UNC path on Windows (msysGit):\n\n* I can cd to a UNC path:\n\n    cd //server1/share1/path\n\n* can cd to other share:\n\n    cd ../../share2/path\n\n* and can cd to other server's share:\n\n    cd ../../../server2/share/path\n\nThat means relative_path(path1, path2) support UNC paths out of the box.\nWe only need to check both path1 and path2 are UNC paths, or both not.\n\nSo, funciton “have_same_root\" will write like this:\n\n\n+static int have_same_root(const char *path1, const char *path2)\n+{\n+       int is_abs1, is_abs2;\n+\n+       is_abs1 = is_absolute_path(path1);\n+       is_abs2 = is_absolute_path(path2);\n+       if (is_abs1 && is_abs2) {\n+               if (is_unc_path(path1) ^ is_unc_path(path2))\n+                       return 0;\n+               return tolower(path1[0]) == tolower(path2[0]);\n+       } else {\n+               return !is_abs1 && !is_abs2;\n+       }\n+}\n\n\n-- \nJiang Xin\n"},{"id":"227734","messageId":"1c0d845aca9a9ca65a7e1d481a75a0f6f4220a89.1379406453.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"CANYiYbH9pLMx4gu1qONhy-+++ojUhPSd9F=sdRTmGWH3pSUTqQ@mail.gmail.com","subject":"[PATCH v3 1/3] test: use unambigous leading path (/foo) for mingw","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-17T08:30:22Z","receivedAt":"2013-09-17T08:30:22Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"In test cases for relative_path, path with one leading character\n(such as /a, /x) may be recogonized as \"a:/\" or \"x:/\" if there is\nsuch DOS drive on MINGW platform. Use an umambigous leading path\n\"/foo\" instead.\n\nAlso change two leading slashes (//) to three leading slashes (///),\notherwize it will be recognized as UNC path on MINGW platform.\n\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------\n 1 file changed, 28 insertions(+), 28 deletions(-)\n\ndiff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\nindex 3a48de2..92976e0 100755\n--- a/t/t0060-path-utils.sh\n+++ b/t/t0060-path-utils.sh\n@@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '\n \ttest \"$sym\" = \"$(test-path-utils real_path \"$dir2/syml\")\"\n '\n \n-relative_path /a/b/c/\t/a/b/\t\tc/\n-relative_path /a/b/c/\t/a/b\t\tc/\n-relative_path /a//b//c/\t//a/b//\t\tc/\tPOSIX\n-relative_path /a/b\t/a/b\t\t./\n-relative_path /a/b/\t/a/b\t\t./\n-relative_path /a\t/a/b\t\t../\n-relative_path /\t\t/a/b/\t\t../../\n-relative_path /a/c\t/a/b/\t\t../c\n-relative_path /a/c\t/a/b\t\t../c\n-relative_path /x/y\t/a/b/\t\t../../x/y\n-relative_path /a/b\t\"<empty>\"\t/a/b\n-relative_path /a/b \t\"<null>\"\t/a/b\n-relative_path a/b/c/\ta/b/\t\tc/\n-relative_path a/b/c/\ta/b\t\tc/\n-relative_path a/b//c\ta//b\t\tc\n-relative_path a/b/\ta/b/\t\t./\n-relative_path a/b/\ta/b\t\t./\n-relative_path a\t\ta/b\t\t../\n-relative_path x/y\ta/b\t\t../../x/y\n-relative_path a/c\ta/b\t\t../c\n-relative_path a/b\t\"<empty>\"\ta/b\n-relative_path a/b \t\"<null>\"\ta/b\n-relative_path \"<empty>\"\t/a/b\t\t./\n-relative_path \"<empty>\"\t\"<empty>\"\t./\n-relative_path \"<empty>\"\t\"<null>\"\t./\n-relative_path \"<null>\"\t\"<empty>\"\t./\n-relative_path \"<null>\"\t\"<null>\"\t./\n-relative_path \"<null>\"\t/a/b\t\t./\n+relative_path /foo/a/b/c/\t/foo/a/b/\tc/\n+relative_path /foo/a/b/c/\t/foo/a/b\tc/\n+relative_path /foo/a//b//c/\t///foo/a/b//\tc/\t\tPOSIX\n+relative_path /foo/a/b\t\t/foo/a/b\t./\n+relative_path /foo/a/b/\t\t/foo/a/b\t./\n+relative_path /foo/a\t\t/foo/a/b\t../\n+relative_path /\t\t\t/foo/a/b/\t../../../\n+relative_path /foo/a/c\t\t/foo/a/b/\t../c\n+relative_path /foo/a/c\t\t/foo/a/b\t../c\n+relative_path /foo/x/y\t\t/foo/a/b/\t../../x/y\n+relative_path /foo/a/b\t\t\"<empty>\"\t/foo/a/b\n+relative_path /foo/a/b \t\t\"<null>\"\t/foo/a/b\n+relative_path foo/a/b/c/\tfoo/a/b/\tc/\n+relative_path foo/a/b/c/\tfoo/a/b\t\tc/\n+relative_path foo/a/b//c\tfoo/a//b\tc\n+relative_path foo/a/b/\t\tfoo/a/b/\t./\n+relative_path foo/a/b/\t\tfoo/a/b\t\t./\n+relative_path foo/a\t\tfoo/a/b\t\t../\n+relative_path foo/x/y\t\tfoo/a/b\t\t../../x/y\n+relative_path foo/a/c\t\tfoo/a/b\t\t../c\n+relative_path foo/a/b\t\t\"<empty>\"\tfoo/a/b\n+relative_path foo/a/b \t\t\"<null>\"\tfoo/a/b\n+relative_path \"<empty>\"\t\t/foo/a/b\t./\n+relative_path \"<empty>\"\t\t\"<empty>\"\t./\n+relative_path \"<empty>\"\t\t\"<null>\"\t./\n+relative_path \"<null>\"\t\t\"<empty>\"\t./\n+relative_path \"<null>\"\t\t\"<null>\"\t./\n+relative_path \"<null>\"\t\t/foo/a/b\t./\n \n test_done\n-- \n1.8.4.460.g2f083d1\n"},{"id":"227735","messageId":"2c56935842ceef4d5933c299dd2d55286eb0ba3a.1379406453.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"1c0d845aca9a9ca65a7e1d481a75a0f6f4220a89.1379406453.git.worldhello.net@gmail.com","subject":"[PATCH v3 2/3] relative_path should honor DOS and UNC paths","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-17T08:30:23Z","receivedAt":"2013-09-17T08:30:23Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Tvangeste found that the \"relative_path\" function could not work\nproperly on Windows if \"in\" and \"prefix\" have DOS driver prefix\n(such as \"C:/windows\"). And the \"relative_path\" function won't\nwork properly if either \"in\" or \"prefix\" is a UNC path (like\n\"//host/share\"). ($gmane/234434)\n\nE.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\nshould return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n\nSo make relative_path honor DOS and UNC paths, and add test cases\nfor it in t0060.\n\nReported-by: Tvangeste <i.4m.l33t@yandex.ru>\nHelped-by: Johannes Sixt <j6t@kdbg.org>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n compat/mingw.h        |  9 +++++++++\n git-compat-util.h     |  4 ++++\n path.c                | 25 +++++++++++++++++++++++++\n t/t0060-path-utils.sh |  8 ++++++++\n 4 files changed, 46 insertions(+)\n\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex bd0a88b..06e9f49 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format\n \n #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')\n #define is_dir_sep(c) ((c) == '/' || (c) == '\\\\')\n+static inline int is_unc_path(const char *path)\n+{\n+\tif (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))\n+\t\treturn 0;\n+\tfor (path += 2; *path; path++)\n+\t\tif (is_dir_sep(*path))\n+\t\t\treturn 1;\n+\treturn 0;\n+}\n static inline char *mingw_find_last_dir_sep(const char *path)\n {\n \tchar *ret = NULL;\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 9549de6..93c2206 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -274,6 +274,10 @@ extern char *gitbasename(char *);\n #define is_dir_sep(c) ((c) == '/')\n #endif\n \n+#ifndef is_unc_path\n+#define is_unc_path(path) 0\n+#endif\n+\n #ifndef find_last_dir_sep\n #define find_last_dir_sep(path) strrchr(path, '/')\n #endif\ndiff --git a/path.c b/path.c\nindex 9fd28bcd..544d10d 100644\n--- a/path.c\n+++ b/path.c\n@@ -434,6 +434,21 @@ int adjust_shared_perm(const char *path)\n \treturn 0;\n }\n \n+static int have_same_root(const char *path1, const char *path2)\n+{\n+\tint is_abs1, is_abs2;\n+\n+\tis_abs1 = is_absolute_path(path1);\n+\tis_abs2 = is_absolute_path(path2);\n+\tif (is_abs1 && is_abs2) {\n+\t\tif (is_unc_path(path1) ^ is_unc_path(path2))\n+\t\t\treturn 0;\n+\t\treturn tolower(path1[0]) == tolower(path2[0]);\n+\t} else {\n+\t\treturn !is_abs1 && !is_abs2;\n+\t}\n+}\n+\n /*\n  * Give path as relative to prefix.\n  *\n@@ -454,6 +469,16 @@ const char *relative_path(const char *in, const char *prefix,\n \telse if (!prefix_len)\n \t\treturn in;\n \n+\tif (have_same_root(in, prefix)) {\n+\t\t/* bypass dos_drive, for \"c:\" is identical to \"C:\" */\n+\t\tif (has_dos_drive_prefix(in)) {\n+\t\t\ti = 2;\n+\t\t\tj = 2;\n+\t\t}\n+\t} else {\n+\t\treturn in;\n+\t}\n+\n \twhile (i < prefix_len && j < in_len && prefix[i] == in[j]) {\n \t\tif (is_dir_sep(prefix[i])) {\n \t\t\twhile (is_dir_sep(prefix[i]))\ndiff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\nindex 92976e0..830b6d5 100755\n--- a/t/t0060-path-utils.sh\n+++ b/t/t0060-path-utils.sh\n@@ -210,6 +210,14 @@ relative_path foo/a/b/\t\tfoo/a/b\t\t./\n relative_path foo/a\t\tfoo/a/b\t\t../\n relative_path foo/x/y\t\tfoo/a/b\t\t../../x/y\n relative_path foo/a/c\t\tfoo/a/b\t\t../c\n+relative_path foo/a/b\t\t/foo/x/y\tfoo/a/b\n+relative_path /foo/a/b\t\tfoo/x/y\t\t/foo/a/b\n+relative_path d:/a/b\t\tD:/a/c\t\t../b\t\tMINGW\n+relative_path C:/a/b\t\tD:/a/c\t\tC:/a/b\t\tMINGW\n+relative_path //host1/a/b\t//host1/a/c\t../b\n+relative_path //host1/a/b\t//host2/a/c\t../../../host1/a/b\n+relative_path //host1/a/b\t/foo/a/c\t//host1/a/b\tMINGW\n+relative_path /foo/a/b\t\t//host2/a/c\t/foo/a/b\tMINGW\n relative_path foo/a/b\t\t\"<empty>\"\tfoo/a/b\n relative_path foo/a/b \t\t\"<null>\"\tfoo/a/b\n relative_path \"<empty>\"\t\t/foo/a/b\t./\n-- \n1.8.4.460.g2f083d1\n"},{"id":"227736","messageId":"2f083d1bc55db70bdc1692cdebcef8eadcceb521.1379406453.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"1c0d845aca9a9ca65a7e1d481a75a0f6f4220a89.1379406453.git.worldhello.net@gmail.com","subject":"[PATCH v3 3/3] Use simpler relative_path when set_git_dir","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-17T08:30:24Z","receivedAt":"2013-09-17T08:30:24Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.\nIt will make git_dir shorter only if git_dir is inside work_tree,\nand this will increase performance. But my last refactor effort on\nrelative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.\nAlways use relative_path as git_dir may bring troubles like\n$gmane/234434.\n\nBecause new relative_path is a combination of original relative_path\nfrom path.c and original path_relative from quote.c, so in order to\nrestore the origin implementation, save the original relative_path\nas remove_leading_path, and call it in setup.c.\n\nSuggested-by: Karsten Blees <karsten.blees@gmail.com>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n cache.h |  1 +\n path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++\n setup.c |  5 +----\n 3 files changed, 47 insertions(+), 4 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex a47b9c0..73fa334 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -747,6 +747,7 @@ int is_directory(const char *);\n const char *real_path(const char *path);\n const char *real_path_if_valid(const char *path);\n const char *absolute_path(const char *path);\n+const char *remove_leading_path(const char *in, const char *prefix);\n const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);\n int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);\n int normalize_path_copy(char *dst, const char *src);\ndiff --git a/path.c b/path.c\nindex 544d10d..5ad3554 100644\n--- a/path.c\n+++ b/path.c\n@@ -556,6 +556,51 @@ const char *relative_path(const char *in, const char *prefix,\n }\n \n /*\n+ * A simpler implementation of relative_path\n+ *\n+ * Get relative path by removing \"prefix\" from \"in\". This function\n+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter\n+ * to increase performance when traversing the path to work_tree.\n+ */\n+const char *remove_leading_path(const char *in, const char *prefix)\n+{\n+\tstatic char buf[PATH_MAX + 1];\n+\tint i = 0, j = 0;\n+\n+\tif (!prefix || !prefix[0])\n+\t\treturn in;\n+\twhile (prefix[i]) {\n+\t\tif (is_dir_sep(prefix[i])) {\n+\t\t\tif (!is_dir_sep(in[j]))\n+\t\t\t\treturn in;\n+\t\t\twhile (is_dir_sep(prefix[i]))\n+\t\t\t\ti++;\n+\t\t\twhile (is_dir_sep(in[j]))\n+\t\t\t\tj++;\n+\t\t\tcontinue;\n+\t\t} else if (in[j] != prefix[i]) {\n+\t\t\treturn in;\n+\t\t}\n+\t\ti++;\n+\t\tj++;\n+\t}\n+\tif (\n+\t    /* \"/foo\" is a prefix of \"/foo\" */\n+\t    in[j] &&\n+\t    /* \"/foo\" is not a prefix of \"/foobar\" */\n+\t    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])\n+\t   )\n+\t\treturn in;\n+\twhile (is_dir_sep(in[j]))\n+\t\tj++;\n+\tif (!in[j])\n+\t\tstrcpy(buf, \".\");\n+\telse\n+\t\tstrcpy(buf, in + j);\n+\treturn buf;\n+}\n+\n+/*\n  * It is okay if dst == src, but they should not overlap otherwise.\n  *\n  * Performs the following normalizations on src, storing the result in dst:\ndiff --git a/setup.c b/setup.c\nindex f08dd64..dbf4138 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -227,7 +227,6 @@ int is_inside_work_tree(void)\n \n void setup_work_tree(void)\n {\n-\tstruct strbuf sb = STRBUF_INIT;\n \tconst char *work_tree, *git_dir;\n \tstatic int initialized = 0;\n \n@@ -247,10 +246,8 @@ void setup_work_tree(void)\n \tif (getenv(GIT_WORK_TREE_ENVIRONMENT))\n \t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, \".\", 1);\n \n-\tset_git_dir(relative_path(git_dir, work_tree, &sb));\n+\tset_git_dir(remove_leading_path(git_dir, work_tree));\n \tinitialized = 1;\n-\n-\tstrbuf_release(&sb);\n }\n \n static int check_repository_format_gently(const char *gitdir, int *nongit_ok)\n-- \n1.8.4.460.g2f083d1\n"},{"id":"227752","messageId":"xmqqli2v1l7f.fsf@gitster.dls.corp.google.com","threadId":"34897","inReplyTo":"2c56935842ceef4d5933c299dd2d55286eb0ba3a.1379406453.git.worldhello.net@gmail.com","subject":"Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-17T16:12:20Z","receivedAt":"2013-09-17T16:12:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jiang Xin <worldhello.net@gmail.com> writes:\n\n> diff --git a/compat/mingw.h b/compat/mingw.h\n> index bd0a88b..06e9f49 100644\n> --- a/compat/mingw.h\n> +++ b/compat/mingw.h\n> @@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format\n>  \n>  #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')\n>  #define is_dir_sep(c) ((c) == '/' || (c) == '\\\\')\n> +static inline int is_unc_path(const char *path)\n> +{\n> +\tif (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))\n> +\t\treturn 0;\n\nIf path[1] == '\\0', it would be !is_dir_sep() and we end up\ninspecting past the end of the string?\n"},{"id":"227778","messageId":"5238AE60.1010700@kdbg.org","threadId":"34897","inReplyTo":"CANYiYbH9pLMx4gu1qONhy-+++ojUhPSd9F=sdRTmGWH3pSUTqQ@mail.gmail.com","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2013-09-17T19:32:48Z","receivedAt":"2013-09-17T19:32:48Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 17.09.2013 10:24, schrieb Jiang Xin:\n> I have checked the behavior of UNC path on Windows (msysGit):\n> \n> * I can cd to a UNC path:\n> \n>     cd //server1/share1/path\n> \n> * can cd to other share:\n> \n>     cd ../../share2/path\n> \n> * and can cd to other server's share:\n> \n>     cd ../../../server2/share/path\n> \n> That means relative_path(path1, path2) support UNC paths out of the box.\n> We only need to check both path1 and path2 are UNC paths, or both not.\n\nYour tests are flawed. You issued the commands in bash, which (or rather\nMSYS) does everything for you that you need to make it work. But in\nreality it does not, because the system cannot apply .. to //server/share:\n\n$ git ls-remote //srv/public/../repos/his/setups.git\nfatal: '//srv/public/../repos/his/setups.git' does not appear to be a\ngit repository\nfatal: Could not read from remote repository.\n\nPlease make sure you have the correct access rights\nand the repository exists.\n\neven though the repository (and //srv/public, let me assure) exists:\n\n$ git ls-remote //srv/repos/his/setups.git\nbea489b0611a72c41f133343fdccbd3e2b9f80b5        HEAD\n...\n\nThe situation does not change with your latest round (v3).\n\nPlease let me suggest not to scratch where there is no itch. ;) Your\nround v2 was good enough.\n\nIf you really want to check UNC paths, then you must compare two path\ncomponents after the the double-slash, not just one.\n\nFurthermore, you should audit all code that references\nis_absolute_path(), relative_path(), normalize_path_copy(), and possibly\na few others whether the functions or call sites need improvement.\nThat's worth a separate patch.\n\n-- Hannes\n"},{"id":"227829","messageId":"CANYiYbF1XwKbD13AMZhE1c4hGMqVzpH9hZ-J8Gk-8AVFUCnn0g@mail.gmail.com","threadId":"34897","inReplyTo":"xmqqli2v1l7f.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-18T09:02:12Z","receivedAt":"2013-09-18T09:02:12Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2013/9/18 Junio C Hamano <gitster@pobox.com>:\n> Jiang Xin <worldhello.net@gmail.com> writes:\n>\n>> diff --git a/compat/mingw.h b/compat/mingw.h\n>> index bd0a88b..06e9f49 100644\n>> --- a/compat/mingw.h\n>> +++ b/compat/mingw.h\n>> @@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format\n>>\n>>  #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')\n>>  #define is_dir_sep(c) ((c) == '/' || (c) == '\\\\')\n>> +static inline int is_unc_path(const char *path)\n>> +{\n>> +     if (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))\n>> +             return 0;\n\nA UNC path must start with two slashes, but not three or more slashes.\n\n>\n> If path[1] == '\\0', it would be !is_dir_sep() and we end up\n> inspecting past the end of the string?\n\nThe funciton \"is_unc_path\" will return false (0), if path is\n\"\", \"/\", \"//\", \"///three/slashes/\", or \"/usr/local\".\nSo the problem is ?\n\n-- \nJiang Xin\n"},{"id":"227837","messageId":"5239B8B1.5050605@web.de","threadId":"34897","inReplyTo":"5238AE60.1010700@kdbg.org","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2013-09-18T14:29:05Z","receivedAt":"2013-09-18T14:29:05Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2013-09-17 21.32, Johannes Sixt wrote:\n> Am 17.09.2013 10:24, schrieb Jiang Xin:\n>> I have checked the behavior of UNC path on Windows (msysGit):\n>>\n>> * I can cd to a UNC path:\n>>\n>>     cd //server1/share1/path\n>>\n>> * can cd to other share:\n>>\n>>     cd ../../share2/path\n>>\n>> * and can cd to other server's share:\n>>\n>>     cd ../../../server2/share/path\n>>\n>> That means relative_path(path1, path2) support UNC paths out of the box.\n>> We only need to check both path1 and path2 are UNC paths, or both not.\n> \n> Your tests are flawed. You issued the commands in bash, which (or rather\n> MSYS) does everything for you that you need to make it work. But in\n> reality it does not, because the system cannot apply .. to //server/share:\n> \n> $ git ls-remote //srv/public/../repos/his/setups.git\n> fatal: '//srv/public/../repos/his/setups.git' does not appear to be a\n> git repository\n> fatal: Could not read from remote repository.\n> \n> Please make sure you have the correct access rights\n> and the repository exists.\n> \n> even though the repository (and //srv/public, let me assure) exists:\n> \n> $ git ls-remote //srv/repos/his/setups.git\n> bea489b0611a72c41f133343fdccbd3e2b9f80b5        HEAD\n> ...\n> \n> The situation does not change with your latest round (v3).\n> \n> Please let me suggest not to scratch where there is no itch. ;) Your\n> round v2 was good enough.\n> \n> If you really want to check UNC paths, then you must compare two path\n> components after the the double-slash, not just one.\n> \n> Furthermore, you should audit all code that references\n> is_absolute_path(), relative_path(), normalize_path_copy(), and possibly\n> a few others whether the functions or call sites need improvement.\n> That's worth a separate patch.\n> \n> -- Hannes\n\nI tend to agree here.\nThe V2 patch fixed a regression.\nThis should be one commit on its own:\nDocumentation/SubmittingPatches:\n(1) Make separate commits for logically separate changes.\n\nFixing a bug is a good thing, thanks for working on this,\n\nThe support for UNC paths is a new feature, and this deserves a seperate commit.\n/Torsten\n"},{"id":"227840","messageId":"5239C247.4030909@web.de","threadId":"34897","inReplyTo":"5239BA98.9000205@gmail.com","subject":"Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2013-09-18T15:09:59Z","receivedAt":"2013-09-18T15:09:59Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2013-09-18 16.37, Torsten Bögershausen wrote:\n> On 2013-09-17 18.12, Junio C Hamano wrote:\n>> Jiang Xin <worldhello.net@gmail.com> writes:\n>>\n>>> diff --git a/compat/mingw.h b/compat/mingw.h\n>>> index bd0a88b..06e9f49 100644\n>>> --- a/compat/mingw.h\n>>> +++ b/compat/mingw.h\n>>> @@ -311,6 +311,15 @@ int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format\n>>>  \n>>>  #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')\n>>>  #define is_dir_sep(c) ((c) == '/' || (c) == '\\\\')\n>>> +static inline int is_unc_path(const char *path)\n>>> +{\n>>> +\tif (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))\n>>> +\t\treturn 0;\n>>\n>> If path[1] == '\\0', it would be !is_dir_sep() and we end up\n>> inspecting past the end of the string?\nYes\n(If there was a previous mail, it was incomplete, sorry)\n\nI think we want to catch \"2 (back)slashes followed by a letter\"\n<http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx>\n\n#define is_unc_path(path) ((is_dir_sep(path)[0]) && is_dir_sep((path)[1]) && isalpha((path[2])))\n\nThen we need \n#define is_relative_path(path)  (((path)[0]) && !is_dir_sep((path)[1]))\n\nAnd may be like this:\n\nstatic int have_same_root(const char *path1, const char *path2)\n{\n\tint is_abs1, is_abs2;\n\n\tis_abs1 = is_absolute_path(path1);\n\tis_abs2 = is_absolute_path(path2);\n\tif (is_abs1 && is_abs2) {\n\t\tif (is_unc_path(path1) && !is_relative_path(path2))\n\t\t\treturn 0;\n\t\tif (!is_relative_path(path1) && is_unc_path(path2))\n\t\t\treturn 0;\n\t\treturn tolower(path1[0]) == tolower(path2[0]);\n\t} else {\n\t\treturn !is_abs1 && !is_abs2;\n\t}\n}\n\nCould that work?\n"},{"id":"227842","messageId":"xmqq4n9iw24q.fsf@gitster.dls.corp.google.com","threadId":"34897","inReplyTo":"CANYiYbF1XwKbD13AMZhE1c4hGMqVzpH9hZ-J8Gk-8AVFUCnn0g@mail.gmail.com","subject":"Re: [PATCH v3 2/3] relative_path should honor DOS and UNC paths","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-18T16:00:53Z","receivedAt":"2013-09-18T16:00:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jiang Xin <worldhello.net@gmail.com> writes:\n\n> 2013/9/18 Junio C Hamano <gitster@pobox.com>:\n>>> +     if (!is_dir_sep(*path) || !is_dir_sep(*(path+1)) || is_dir_sep(*(path+2)))\n>>> +             return 0;\n>> If path[1] == '\\0', it would be !is_dir_sep() and we end up\n>> inspecting past the end of the string?\n>\n> The funciton \"is_unc_path\" will return false (0), if path is\n> \"\", \"/\", \"//\", \"///three/slashes/\", or \"/usr/local\".\n> So the problem is ?\n\nIf path[1] == '\\0' (e.g. path=\"/\"), !is_dir_sep(path[1]) is true,\nnot false (as I misread earlier), so we hit an early return and will\nnot peek path[2].  So no problem.  Sorry for the noise.\n\nBut I agree with J6t and Torsten in near-by thread that the simpler\none that does not worry about // should be done as a separate patch\nand //, if we decide to do it, should build on top.\n\nThanks.\n"},{"id":"227912","messageId":"CANYiYbGK_KdF5Yvcus5C_cGz3EyGTaFvirsUH5q4Eu=3VC4=Wg@mail.gmail.com","threadId":"34897","inReplyTo":"5238AE60.1010700@kdbg.org","subject":"Re: [PATCH 1/2] relative_path should honor dos_drive_prefix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-20T01:26:41Z","receivedAt":"2013-09-20T01:26:41Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2013/9/18 Johannes Sixt <j6t@kdbg.org>:\n> Am 17.09.2013 10:24, schrieb Jiang Xin:\n>> I have checked the behavior of UNC path on Windows (msysGit):\n>>\n>> * I can cd to a UNC path:\n>>\n>>     cd //server1/share1/path\n>>\n>> * can cd to other share:\n>>\n>>     cd ../../share2/path\n>>\n>> * and can cd to other server's share:\n>>\n>>     cd ../../../server2/share/path\n>>\n>> That means relative_path(path1, path2) support UNC paths out of the box.\n>> We only need to check both path1 and path2 are UNC paths, or both not.\n>\n> Your tests are flawed. You issued the commands in bash, which (or rather\n> MSYS) does everything for you that you need to make it work. But in\n> reality it does not, because the system cannot apply .. to //server/share:\n>\n> $ git ls-remote //srv/public/../repos/his/setups.git\n> fatal: '//srv/public/../repos/his/setups.git' does not appear to be a\n> git repository\n> fatal: Could not read from remote repository.\n>\n> Please make sure you have the correct access rights\n> and the repository exists.\n>\n> even though the repository (and //srv/public, let me assure) exists:\n>\n> $ git ls-remote //srv/repos/his/setups.git\n> bea489b0611a72c41f133343fdccbd3e2b9f80b5        HEAD\n> ...\n\nAfter see this link (provided by Torsten):\n\n    <http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx>\n\nI find the following commands could work:\n\n    $ git ls-remote //srv/repos/his/setups.git\n    $ git ls-remote //srv/repos/his/../his/setups.git\n    $ git ls-remote //?/UNC/srv/repos/his/setups.git\n    $ git ls-remote //?/UNC/srv/repos/../repos/his/setups.git\n\nBut no luck for this one:\n\n    $ git ls-remote //srv/repos/../repos/his/setups.git\n\nI trace it using gdb, and find it failed in \"stat()/mingw_stat()\" call\nof function \"enter_repo\" in path.c. But I can not find out why\n\"git ls-remote //?/UNC/srv/repos/../repos/his/setups.git\" could\nwork (success in shell, failed in gdb).\n\n> Please let me suggest not to scratch where there is no itch. ;) Your\n> round v2 was good enough.\n>\n> If you really want to check UNC paths, then you must compare two path\n> components after the the double-slash, not just one.\n>\n\nI have already try this (honor two path components after //)\nduring the reroll for patch v3. But I am not satisfied with it,\nand it seems like over-engineered: Rename \"have_same_root\"\nto \"get_common_root_prefix_width\", and it return -1 for no\nsame_root found, otherwize return the length of root_prefix_width.\n\nSince restored the default behavior of setup.c in commit (\"Use\nsimpler relative_path when set_git_dir\"), function \"relative_path\"\nare only used in \"quote.c\" and \"builtin/clean.c\", and two paths\nprovided to \"relative_path\" are always (I can not find exception)\nrelative paths. So no itch exist I think.\n\n-- \nJiang Xin\n"},{"id":"227915","messageId":"cover.1379644482.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"CANYiYbGK_KdF5Yvcus5C_cGz3EyGTaFvirsUH5q4Eu=3VC4=Wg@mail.gmail.com","subject":"[PATCH v4 0/3] relative path regression fix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-20T02:38:45Z","receivedAt":"2013-09-20T02:38:45Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Remove implementations on UNC names in patch v3.\nSo patch v4 is the same like v2, but with minor\nupdate for commit logs.\n\nJiang Xin (3):\n  test: use unambigous leading path (/foo) for mingw\n  relative_path should honor dos-driver-prefix\n  Use simpler relative_path when set_git_dir\n\n cache.h               |  1 +\n path.c                | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++\n setup.c               |  5 +---\n t/t0060-path-utils.sh | 60 +++++++++++++++++++++++++----------------------\n 4 files changed, 99 insertions(+), 32 deletions(-)\n\n-- \n1.8.4.460.gbed9cb4\n"},{"id":"227917","messageId":"15724e27cbef5067902ebebb93aa77d3605402c8.1379644482.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"cover.1379644482.git.worldhello.net@gmail.com","subject":"[PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-20T02:38:46Z","receivedAt":"2013-09-20T02:38:46Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"In test cases for relative_path, path with one leading character\n(such as /a, /x) may be recogonized as \"a:/\" or \"x:/\" if there is\nsuch DOS drive on MINGW platform. Use an umambigous leading path\n\"/foo\" instead.\n\nAlso change two leading slashes (//) to three leading slashes (///),\notherwize it will be recognized as UNC name on MINGW platform.\n\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------\n 1 file changed, 28 insertions(+), 28 deletions(-)\n\ndiff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\nindex 3a48de2..92976e0 100755\n--- a/t/t0060-path-utils.sh\n+++ b/t/t0060-path-utils.sh\n@@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '\n \ttest \"$sym\" = \"$(test-path-utils real_path \"$dir2/syml\")\"\n '\n \n-relative_path /a/b/c/\t/a/b/\t\tc/\n-relative_path /a/b/c/\t/a/b\t\tc/\n-relative_path /a//b//c/\t//a/b//\t\tc/\tPOSIX\n-relative_path /a/b\t/a/b\t\t./\n-relative_path /a/b/\t/a/b\t\t./\n-relative_path /a\t/a/b\t\t../\n-relative_path /\t\t/a/b/\t\t../../\n-relative_path /a/c\t/a/b/\t\t../c\n-relative_path /a/c\t/a/b\t\t../c\n-relative_path /x/y\t/a/b/\t\t../../x/y\n-relative_path /a/b\t\"<empty>\"\t/a/b\n-relative_path /a/b \t\"<null>\"\t/a/b\n-relative_path a/b/c/\ta/b/\t\tc/\n-relative_path a/b/c/\ta/b\t\tc/\n-relative_path a/b//c\ta//b\t\tc\n-relative_path a/b/\ta/b/\t\t./\n-relative_path a/b/\ta/b\t\t./\n-relative_path a\t\ta/b\t\t../\n-relative_path x/y\ta/b\t\t../../x/y\n-relative_path a/c\ta/b\t\t../c\n-relative_path a/b\t\"<empty>\"\ta/b\n-relative_path a/b \t\"<null>\"\ta/b\n-relative_path \"<empty>\"\t/a/b\t\t./\n-relative_path \"<empty>\"\t\"<empty>\"\t./\n-relative_path \"<empty>\"\t\"<null>\"\t./\n-relative_path \"<null>\"\t\"<empty>\"\t./\n-relative_path \"<null>\"\t\"<null>\"\t./\n-relative_path \"<null>\"\t/a/b\t\t./\n+relative_path /foo/a/b/c/\t/foo/a/b/\tc/\n+relative_path /foo/a/b/c/\t/foo/a/b\tc/\n+relative_path /foo/a//b//c/\t///foo/a/b//\tc/\t\tPOSIX\n+relative_path /foo/a/b\t\t/foo/a/b\t./\n+relative_path /foo/a/b/\t\t/foo/a/b\t./\n+relative_path /foo/a\t\t/foo/a/b\t../\n+relative_path /\t\t\t/foo/a/b/\t../../../\n+relative_path /foo/a/c\t\t/foo/a/b/\t../c\n+relative_path /foo/a/c\t\t/foo/a/b\t../c\n+relative_path /foo/x/y\t\t/foo/a/b/\t../../x/y\n+relative_path /foo/a/b\t\t\"<empty>\"\t/foo/a/b\n+relative_path /foo/a/b \t\t\"<null>\"\t/foo/a/b\n+relative_path foo/a/b/c/\tfoo/a/b/\tc/\n+relative_path foo/a/b/c/\tfoo/a/b\t\tc/\n+relative_path foo/a/b//c\tfoo/a//b\tc\n+relative_path foo/a/b/\t\tfoo/a/b/\t./\n+relative_path foo/a/b/\t\tfoo/a/b\t\t./\n+relative_path foo/a\t\tfoo/a/b\t\t../\n+relative_path foo/x/y\t\tfoo/a/b\t\t../../x/y\n+relative_path foo/a/c\t\tfoo/a/b\t\t../c\n+relative_path foo/a/b\t\t\"<empty>\"\tfoo/a/b\n+relative_path foo/a/b \t\t\"<null>\"\tfoo/a/b\n+relative_path \"<empty>\"\t\t/foo/a/b\t./\n+relative_path \"<empty>\"\t\t\"<empty>\"\t./\n+relative_path \"<empty>\"\t\t\"<null>\"\t./\n+relative_path \"<null>\"\t\t\"<empty>\"\t./\n+relative_path \"<null>\"\t\t\"<null>\"\t./\n+relative_path \"<null>\"\t\t/foo/a/b\t./\n \n test_done\n-- \n1.8.4.460.gbed9cb4\n"},{"id":"227916","messageId":"b7d2432db756e16e9addb2fcccf5538c6fad342f.1379644482.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"cover.1379644482.git.worldhello.net@gmail.com","subject":"[PATCH v4 2/3] relative_path should honor dos-driver-prefix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-20T02:38:47Z","receivedAt":"2013-09-20T02:38:47Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Tvangeste found that the \"relative_path\" function could not work\nproperly on Windows if \"in\" and \"prefix\" have DOS driver prefix\n(such as \"C:/windows\"). ($gmane/234434)\n\nE.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\nshould return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n\nSo make relative_path honor dos-driver-prefix, and add test cases\nfor it in t0060.\n\nReported-by: Tvangeste <i.4m.l33t@yandex.ru>\nHelped-by: Johannes Sixt <j6t@kdbg.org>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n path.c                | 20 ++++++++++++++++++++\n t/t0060-path-utils.sh |  4 ++++\n 2 files changed, 24 insertions(+)\n\ndiff --git a/path.c b/path.c\nindex 7f3324a..0c16dc5 100644\n--- a/path.c\n+++ b/path.c\n@@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)\n \treturn 0;\n }\n \n+static int have_same_root(const char *path1, const char *path2)\n+{\n+\tint is_abs1, is_abs2;\n+\n+\tis_abs1 = is_absolute_path(path1);\n+\tis_abs2 = is_absolute_path(path2);\n+\treturn (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||\n+\t       (!is_abs1 && !is_abs2);\n+}\n+\n /*\n  * Give path as relative to prefix.\n  *\n@@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,\n \telse if (!prefix_len)\n \t\treturn in;\n \n+\tif (have_same_root(in, prefix)) {\n+\t\t/* bypass dos_drive, for \"c:\" is identical to \"C:\" */\n+\t\tif (has_dos_drive_prefix(in)) {\n+\t\t\ti = 2;\n+\t\t\tj = 2;\n+\t\t}\n+\t} else {\n+\t\treturn in;\n+\t}\n+\n \twhile (i < prefix_len && j < in_len && prefix[i] == in[j]) {\n \t\tif (is_dir_sep(prefix[i])) {\n \t\t\twhile (is_dir_sep(prefix[i]))\ndiff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\nindex 92976e0..40dfa2d 100755\n--- a/t/t0060-path-utils.sh\n+++ b/t/t0060-path-utils.sh\n@@ -210,6 +210,10 @@ relative_path foo/a/b/\t\tfoo/a/b\t\t./\n relative_path foo/a\t\tfoo/a/b\t\t../\n relative_path foo/x/y\t\tfoo/a/b\t\t../../x/y\n relative_path foo/a/c\t\tfoo/a/b\t\t../c\n+relative_path foo/a/b\t\t/foo/x/y\tfoo/a/b\n+relative_path /foo/a/b\t\tfoo/x/y\t\t/foo/a/b\n+relative_path d:/a/b\t\tD:/a/c\t\t../b\t\tMINGW\n+relative_path C:/a/b\t\tD:/a/c\t\tC:/a/b\t\tMINGW\n relative_path foo/a/b\t\t\"<empty>\"\tfoo/a/b\n relative_path foo/a/b \t\t\"<null>\"\tfoo/a/b\n relative_path \"<empty>\"\t\t/foo/a/b\t./\n-- \n1.8.4.460.gbed9cb4\n"},{"id":"227918","messageId":"a323d5582ec9e09a91ef6f2ad1827547a5335c62.1379644482.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"cover.1379644482.git.worldhello.net@gmail.com","subject":"[PATCH v4 3/3] Use simpler relative_path when set_git_dir","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-09-20T02:38:48Z","receivedAt":"2013-09-20T02:38:48Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.\nIt will make git_dir shorter only if git_dir is inside work_tree,\nand this will increase performance. But my last refactor effort on\nrelative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.\nAlways use relative_path as git_dir may bring troubles like\n$gmane/234434.\n\nBecause new relative_path is a combination of original relative_path\nfrom path.c and original path_relative from quote.c, so in order to\nrestore the origin implementation, save the original relative_path\nas remove_leading_path, and call it in setup.c.\n\nSuggested-by: Karsten Blees <karsten.blees@gmail.com>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n cache.h |  1 +\n path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++\n setup.c |  5 +----\n 3 files changed, 47 insertions(+), 4 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 8e42256..94475bd 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -737,6 +737,7 @@ int is_directory(const char *);\n const char *real_path(const char *path);\n const char *real_path_if_valid(const char *path);\n const char *absolute_path(const char *path);\n+const char *remove_leading_path(const char *in, const char *prefix);\n const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);\n int normalize_path_copy(char *dst, const char *src);\n int longest_ancestor_length(const char *path, struct string_list *prefixes);\ndiff --git a/path.c b/path.c\nindex 0c16dc5..fa62da5 100644\n--- a/path.c\n+++ b/path.c\n@@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,\n }\n \n /*\n+ * A simpler implementation of relative_path\n+ *\n+ * Get relative path by removing \"prefix\" from \"in\". This function\n+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter\n+ * to increase performance when traversing the path to work_tree.\n+ */\n+const char *remove_leading_path(const char *in, const char *prefix)\n+{\n+\tstatic char buf[PATH_MAX + 1];\n+\tint i = 0, j = 0;\n+\n+\tif (!prefix || !prefix[0])\n+\t\treturn in;\n+\twhile (prefix[i]) {\n+\t\tif (is_dir_sep(prefix[i])) {\n+\t\t\tif (!is_dir_sep(in[j]))\n+\t\t\t\treturn in;\n+\t\t\twhile (is_dir_sep(prefix[i]))\n+\t\t\t\ti++;\n+\t\t\twhile (is_dir_sep(in[j]))\n+\t\t\t\tj++;\n+\t\t\tcontinue;\n+\t\t} else if (in[j] != prefix[i]) {\n+\t\t\treturn in;\n+\t\t}\n+\t\ti++;\n+\t\tj++;\n+\t}\n+\tif (\n+\t    /* \"/foo\" is a prefix of \"/foo\" */\n+\t    in[j] &&\n+\t    /* \"/foo\" is not a prefix of \"/foobar\" */\n+\t    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])\n+\t   )\n+\t\treturn in;\n+\twhile (is_dir_sep(in[j]))\n+\t\tj++;\n+\tif (!in[j])\n+\t\tstrcpy(buf, \".\");\n+\telse\n+\t\tstrcpy(buf, in + j);\n+\treturn buf;\n+}\n+\n+/*\n  * It is okay if dst == src, but they should not overlap otherwise.\n  *\n  * Performs the following normalizations on src, storing the result in dst:\ndiff --git a/setup.c b/setup.c\nindex 0d9ea62..dad39c1 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -360,7 +360,6 @@ int is_inside_work_tree(void)\n \n void setup_work_tree(void)\n {\n-\tstruct strbuf sb = STRBUF_INIT;\n \tconst char *work_tree, *git_dir;\n \tstatic int initialized = 0;\n \n@@ -380,10 +379,8 @@ void setup_work_tree(void)\n \tif (getenv(GIT_WORK_TREE_ENVIRONMENT))\n \t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, \".\", 1);\n \n-\tset_git_dir(relative_path(git_dir, work_tree, &sb));\n+\tset_git_dir(remove_leading_path(git_dir, work_tree));\n \tinitialized = 1;\n-\n-\tstrbuf_release(&sb);\n }\n \n static int check_repository_format_gently(const char *gitdir, int *nongit_ok)\n-- \n1.8.4.460.gbed9cb4\n"},{"id":"228713","messageId":"52570EC8.3050207@gmail.com","threadId":"34897","inReplyTo":"15724e27cbef5067902ebebb93aa77d3605402c8.1379644482.git.worldhello.net@gmail.com","subject":"Re: [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2013-10-10T20:32:08Z","receivedAt":"2013-10-10T20:32:08Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On 20.09.2013 04:38, Jiang Xin wrote:\n\n> In test cases for relative_path, path with one leading character\n> (such as /a, /x) may be recogonized as \"a:/\" or \"x:/\" if there is\n> such DOS drive on MINGW platform. Use an umambigous leading path\n> \"/foo\" instead.\n >\n > Also change two leading slashes (//) to three leading slashes (///),\n > otherwize it will be recognized as UNC name on MINGW platform.\n\nNote that the path mangling comes from MSYS [1], not MinGW, so you \nshould place \"MINGW\" with \"MSYS\" in several places. As a side-note, the \nofficial spelling is \"MinGW\", not \"MINGW\".\n\n> -relative_path /a/b/c/\t/a/b/\t\tc/\n\n> +relative_path /foo/a/b/c/\t/foo/a/b/\tc/\n\nWouldn't it have been more straight-forward to just replace \"a\" with \n\"foo\", \"b\" with \"bar\" and \"c\" with \"baz\" (or whatever)? So that the \nfirst line would say\n\nrelative_path /foo/bar/baz/\t/foo/bar/\t\tbaz/\n\nThanks for the fix!\n\n[1] http://www.mingw.org/wiki/Posix_path_conversion\n\n-- \nSebastian Schuberth\n"},{"id":"228714","messageId":"52570F3C.20509@gmail.com","threadId":"34897","inReplyTo":"b7d2432db756e16e9addb2fcccf5538c6fad342f.1379644482.git.worldhello.net@gmail.com","subject":"Re: [PATCH v4 2/3] relative_path should honor dos-driver-prefix","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2013-10-10T20:34:04Z","receivedAt":"2013-10-10T20:34:04Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On 20.09.2013 04:38, Jiang Xin wrote:\n\n> Tvangeste found that the \"relative_path\" function could not work\n> properly on Windows if \"in\" and \"prefix\" have DOS driver prefix\n> (such as \"C:/windows\"). ($gmane/234434)\n\ns/driver/drive/\n\n> E.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\n> should return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n>\n> So make relative_path honor dos-driver-prefix, and add test cases\n> for it in t0060.\n\ns/dos-driver-prefix/DOS drive prefix/\n\n-- \nSebastian Schuberth\n"},{"id":"228913","messageId":"CANYiYbFGhiztU8=oM3WC8CQSKZ1KuKZtwobJdaNzapZAvPDdzA@mail.gmail.com","threadId":"34897","inReplyTo":"52570EC8.3050207@gmail.com","subject":"Re: [PATCH v4 1/3] test: use unambigous leading path (/foo) for mingw","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-10-14T01:33:40Z","receivedAt":"2013-10-14T01:33:40Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2013/10/11 Sebastian Schuberth <sschuberth@gmail.com>:\n>> In test cases for relative_path, path with one leading character\n>> (such as /a, /x) may be recogonized as \"a:/\" or \"x:/\" if there is\n>> such DOS drive on MINGW platform. Use an umambigous leading path\n>> \"/foo\" instead.\n>>\n>> Also change two leading slashes (//) to three leading slashes (///),\n>> otherwize it will be recognized as UNC name on MINGW platform.\n>\n> Note that the path mangling comes from MSYS [1], not MinGW, so you should\n> place \"MINGW\" with \"MSYS\" in several places. As a side-note, the official\n> spelling is \"MinGW\", not \"MINGW\".\n>\n\nI will make a reroll. s/MINGW/MSYS/i\n\n>> -relative_path /a/b/c/  /a/b/           c/\n>\n>\n>> +relative_path /foo/a/b/c/      /foo/a/b/       c/\n>\n>\n> Wouldn't it have been more straight-forward to just replace \"a\" with \"foo\",\n> \"b\" with \"bar\" and \"c\" with \"baz\" (or whatever)? So that the first line\n> would say\n>\n> relative_path /foo/bar/baz/     /foo/bar/               baz/\n>\n\nThese test cases have been used in some commit logs, such as\ncommit: v1.8.3-rc2-13-gad66df2. And for me (a non-English speaker)\na,b,c,x,y,z are more readable than bar, baz, qux, ...\n\n-- \nJiang Xin\n"},{"id":"228914","messageId":"cover.1381717700.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"52570EC8.3050207@gmail.com","subject":"[PATCH v5 0/3] relative path regression fix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-10-14T02:29:37Z","receivedAt":"2013-10-14T02:29:37Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Update since v4:\n\n * Update commit logs with the help from Sebastian Schuberth:\n\n   s/MINGW/MSYS/i\n   s/dos-driver-prefix/dos-drive-prefix/\n\nJiang Xin (3):\n  test: use unambigous leading path (/foo) for MSYS\n  relative_path should honor dos-drive-prefix\n  Use simpler relative_path when set_git_dir\n\n cache.h               |  1 +\n path.c                | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++\n setup.c               |  5 +---\n t/t0060-path-utils.sh | 60 +++++++++++++++++++++++++----------------------\n 4 files changed, 99 insertions(+), 32 deletions(-)\n\n-- \n1.8.4\n"},{"id":"228915","messageId":"4a078e41976b25488571b1478a51e287ffdd55c8.1381717700.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"cover.1381717700.git.worldhello.net@gmail.com","subject":"[PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-10-14T02:29:38Z","receivedAt":"2013-10-14T02:29:38Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"In test cases for relative_path, path with one leading character\n(such as /a, /x) may be recogonized as \"a:/\" or \"x:/\" if there is\nsuch DOS drive on MSYS platform. Use an umambigous leading path\n\"/foo\" instead.\n\nAlso change two leading slashes (//) to three leading slashes (///),\notherwize it will be recognized as UNC name on MSYS platform.\n\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------\n 1 file changed, 28 insertions(+), 28 deletions(-)\n\ndiff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\nindex 3a48de2..92976e0 100755\n--- a/t/t0060-path-utils.sh\n+++ b/t/t0060-path-utils.sh\n@@ -190,33 +190,33 @@ test_expect_success SYMLINKS 'real path works on symlinks' '\n \ttest \"$sym\" = \"$(test-path-utils real_path \"$dir2/syml\")\"\n '\n \n-relative_path /a/b/c/\t/a/b/\t\tc/\n-relative_path /a/b/c/\t/a/b\t\tc/\n-relative_path /a//b//c/\t//a/b//\t\tc/\tPOSIX\n-relative_path /a/b\t/a/b\t\t./\n-relative_path /a/b/\t/a/b\t\t./\n-relative_path /a\t/a/b\t\t../\n-relative_path /\t\t/a/b/\t\t../../\n-relative_path /a/c\t/a/b/\t\t../c\n-relative_path /a/c\t/a/b\t\t../c\n-relative_path /x/y\t/a/b/\t\t../../x/y\n-relative_path /a/b\t\"<empty>\"\t/a/b\n-relative_path /a/b \t\"<null>\"\t/a/b\n-relative_path a/b/c/\ta/b/\t\tc/\n-relative_path a/b/c/\ta/b\t\tc/\n-relative_path a/b//c\ta//b\t\tc\n-relative_path a/b/\ta/b/\t\t./\n-relative_path a/b/\ta/b\t\t./\n-relative_path a\t\ta/b\t\t../\n-relative_path x/y\ta/b\t\t../../x/y\n-relative_path a/c\ta/b\t\t../c\n-relative_path a/b\t\"<empty>\"\ta/b\n-relative_path a/b \t\"<null>\"\ta/b\n-relative_path \"<empty>\"\t/a/b\t\t./\n-relative_path \"<empty>\"\t\"<empty>\"\t./\n-relative_path \"<empty>\"\t\"<null>\"\t./\n-relative_path \"<null>\"\t\"<empty>\"\t./\n-relative_path \"<null>\"\t\"<null>\"\t./\n-relative_path \"<null>\"\t/a/b\t\t./\n+relative_path /foo/a/b/c/\t/foo/a/b/\tc/\n+relative_path /foo/a/b/c/\t/foo/a/b\tc/\n+relative_path /foo/a//b//c/\t///foo/a/b//\tc/\t\tPOSIX\n+relative_path /foo/a/b\t\t/foo/a/b\t./\n+relative_path /foo/a/b/\t\t/foo/a/b\t./\n+relative_path /foo/a\t\t/foo/a/b\t../\n+relative_path /\t\t\t/foo/a/b/\t../../../\n+relative_path /foo/a/c\t\t/foo/a/b/\t../c\n+relative_path /foo/a/c\t\t/foo/a/b\t../c\n+relative_path /foo/x/y\t\t/foo/a/b/\t../../x/y\n+relative_path /foo/a/b\t\t\"<empty>\"\t/foo/a/b\n+relative_path /foo/a/b \t\t\"<null>\"\t/foo/a/b\n+relative_path foo/a/b/c/\tfoo/a/b/\tc/\n+relative_path foo/a/b/c/\tfoo/a/b\t\tc/\n+relative_path foo/a/b//c\tfoo/a//b\tc\n+relative_path foo/a/b/\t\tfoo/a/b/\t./\n+relative_path foo/a/b/\t\tfoo/a/b\t\t./\n+relative_path foo/a\t\tfoo/a/b\t\t../\n+relative_path foo/x/y\t\tfoo/a/b\t\t../../x/y\n+relative_path foo/a/c\t\tfoo/a/b\t\t../c\n+relative_path foo/a/b\t\t\"<empty>\"\tfoo/a/b\n+relative_path foo/a/b \t\t\"<null>\"\tfoo/a/b\n+relative_path \"<empty>\"\t\t/foo/a/b\t./\n+relative_path \"<empty>\"\t\t\"<empty>\"\t./\n+relative_path \"<empty>\"\t\t\"<null>\"\t./\n+relative_path \"<null>\"\t\t\"<empty>\"\t./\n+relative_path \"<null>\"\t\t\"<null>\"\t./\n+relative_path \"<null>\"\t\t/foo/a/b\t./\n \n test_done\n-- \n1.8.4\n"},{"id":"228916","messageId":"f352b224b01bc0e99c793eb505c429562894a067.1381717700.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"cover.1381717700.git.worldhello.net@gmail.com","subject":"[PATCH v5 2/3] relative_path should honor dos-drive-prefix","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-10-14T02:29:39Z","receivedAt":"2013-10-14T02:29:39Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Tvangeste found that the \"relative_path\" function could not work\nproperly on Windows if \"in\" and \"prefix\" have DOS drive prefix\n(such as \"C:/windows\"). ($gmane/234434)\n\nE.g., When execute: test-path-utils relative_path \"C:/a/b\" \"D:/x/y\",\nshould return \"C:/a/b\", but returns \"../../C:/a/b\", which is wrong.\n\nSo make relative_path honor DOS drive prefix, and add test cases\nfor it in t0060.\n\nReported-by: Tvangeste <i.4m.l33t@yandex.ru>\nHelped-by: Johannes Sixt <j6t@kdbg.org>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n path.c                | 20 ++++++++++++++++++++\n t/t0060-path-utils.sh |  4 ++++\n 2 files changed, 24 insertions(+)\n\ndiff --git a/path.c b/path.c\nindex 7f3324a..0c16dc5 100644\n--- a/path.c\n+++ b/path.c\n@@ -441,6 +441,16 @@ int adjust_shared_perm(const char *path)\n \treturn 0;\n }\n \n+static int have_same_root(const char *path1, const char *path2)\n+{\n+\tint is_abs1, is_abs2;\n+\n+\tis_abs1 = is_absolute_path(path1);\n+\tis_abs2 = is_absolute_path(path2);\n+\treturn (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||\n+\t       (!is_abs1 && !is_abs2);\n+}\n+\n /*\n  * Give path as relative to prefix.\n  *\n@@ -461,6 +471,16 @@ const char *relative_path(const char *in, const char *prefix,\n \telse if (!prefix_len)\n \t\treturn in;\n \n+\tif (have_same_root(in, prefix)) {\n+\t\t/* bypass dos_drive, for \"c:\" is identical to \"C:\" */\n+\t\tif (has_dos_drive_prefix(in)) {\n+\t\t\ti = 2;\n+\t\t\tj = 2;\n+\t\t}\n+\t} else {\n+\t\treturn in;\n+\t}\n+\n \twhile (i < prefix_len && j < in_len && prefix[i] == in[j]) {\n \t\tif (is_dir_sep(prefix[i])) {\n \t\t\twhile (is_dir_sep(prefix[i]))\ndiff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh\nindex 92976e0..40dfa2d 100755\n--- a/t/t0060-path-utils.sh\n+++ b/t/t0060-path-utils.sh\n@@ -210,6 +210,10 @@ relative_path foo/a/b/\t\tfoo/a/b\t\t./\n relative_path foo/a\t\tfoo/a/b\t\t../\n relative_path foo/x/y\t\tfoo/a/b\t\t../../x/y\n relative_path foo/a/c\t\tfoo/a/b\t\t../c\n+relative_path foo/a/b\t\t/foo/x/y\tfoo/a/b\n+relative_path /foo/a/b\t\tfoo/x/y\t\t/foo/a/b\n+relative_path d:/a/b\t\tD:/a/c\t\t../b\t\tMINGW\n+relative_path C:/a/b\t\tD:/a/c\t\tC:/a/b\t\tMINGW\n relative_path foo/a/b\t\t\"<empty>\"\tfoo/a/b\n relative_path foo/a/b \t\t\"<null>\"\tfoo/a/b\n relative_path \"<empty>\"\t\t/foo/a/b\t./\n-- \n1.8.4\n"},{"id":"228917","messageId":"f4c0808819d91003a90860b67e2b4121c673a5db.1381717700.git.worldhello.net@gmail.com","threadId":"34897","inReplyTo":"cover.1381717700.git.worldhello.net@gmail.com","subject":"[PATCH v5 3/3] Use simpler relative_path when set_git_dir","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2013-10-14T02:29:40Z","receivedAt":"2013-10-14T02:29:40Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.\nIt will make git_dir shorter only if git_dir is inside work_tree,\nand this will increase performance. But my last refactor effort on\nrelative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.\nAlways use relative_path as git_dir may bring troubles like\n$gmane/234434.\n\nBecause new relative_path is a combination of original relative_path\nfrom path.c and original path_relative from quote.c, so in order to\nrestore the origin implementation, save the original relative_path\nas remove_leading_path, and call it in setup.c.\n\nSuggested-by: Karsten Blees <karsten.blees@gmail.com>\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n cache.h |  1 +\n path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++\n setup.c |  5 +----\n 3 files changed, 47 insertions(+), 4 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 8e42256..94475bd 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -737,6 +737,7 @@ int is_directory(const char *);\n const char *real_path(const char *path);\n const char *real_path_if_valid(const char *path);\n const char *absolute_path(const char *path);\n+const char *remove_leading_path(const char *in, const char *prefix);\n const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);\n int normalize_path_copy(char *dst, const char *src);\n int longest_ancestor_length(const char *path, struct string_list *prefixes);\ndiff --git a/path.c b/path.c\nindex 0c16dc5..fa62da5 100644\n--- a/path.c\n+++ b/path.c\n@@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,\n }\n \n /*\n+ * A simpler implementation of relative_path\n+ *\n+ * Get relative path by removing \"prefix\" from \"in\". This function\n+ * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter\n+ * to increase performance when traversing the path to work_tree.\n+ */\n+const char *remove_leading_path(const char *in, const char *prefix)\n+{\n+\tstatic char buf[PATH_MAX + 1];\n+\tint i = 0, j = 0;\n+\n+\tif (!prefix || !prefix[0])\n+\t\treturn in;\n+\twhile (prefix[i]) {\n+\t\tif (is_dir_sep(prefix[i])) {\n+\t\t\tif (!is_dir_sep(in[j]))\n+\t\t\t\treturn in;\n+\t\t\twhile (is_dir_sep(prefix[i]))\n+\t\t\t\ti++;\n+\t\t\twhile (is_dir_sep(in[j]))\n+\t\t\t\tj++;\n+\t\t\tcontinue;\n+\t\t} else if (in[j] != prefix[i]) {\n+\t\t\treturn in;\n+\t\t}\n+\t\ti++;\n+\t\tj++;\n+\t}\n+\tif (\n+\t    /* \"/foo\" is a prefix of \"/foo\" */\n+\t    in[j] &&\n+\t    /* \"/foo\" is not a prefix of \"/foobar\" */\n+\t    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])\n+\t   )\n+\t\treturn in;\n+\twhile (is_dir_sep(in[j]))\n+\t\tj++;\n+\tif (!in[j])\n+\t\tstrcpy(buf, \".\");\n+\telse\n+\t\tstrcpy(buf, in + j);\n+\treturn buf;\n+}\n+\n+/*\n  * It is okay if dst == src, but they should not overlap otherwise.\n  *\n  * Performs the following normalizations on src, storing the result in dst:\ndiff --git a/setup.c b/setup.c\nindex 0d9ea62..dad39c1 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -360,7 +360,6 @@ int is_inside_work_tree(void)\n \n void setup_work_tree(void)\n {\n-\tstruct strbuf sb = STRBUF_INIT;\n \tconst char *work_tree, *git_dir;\n \tstatic int initialized = 0;\n \n@@ -380,10 +379,8 @@ void setup_work_tree(void)\n \tif (getenv(GIT_WORK_TREE_ENVIRONMENT))\n \t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, \".\", 1);\n \n-\tset_git_dir(relative_path(git_dir, work_tree, &sb));\n+\tset_git_dir(remove_leading_path(git_dir, work_tree));\n \tinitialized = 1;\n-\n-\tstrbuf_release(&sb);\n }\n \n static int check_repository_format_gently(const char *gitdir, int *nongit_ok)\n-- \n1.8.4\n"},{"id":"228924","messageId":"CAHGBnuPE7z=rGmuNorMJsMn1kd92yheR=ZH=80GPRFATBC1g0A@mail.gmail.com","threadId":"34897","inReplyTo":"4a078e41976b25488571b1478a51e287ffdd55c8.1381717700.git.worldhello.net@gmail.com","subject":"Re: [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2013-10-14T06:50:42Z","receivedAt":"2013-10-14T06:50:42Z","isPatch":true,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On Mon, Oct 14, 2013 at 4:29 AM, Jiang Xin <worldhello.net@gmail.com> wrote:\n\n> In test cases for relative_path, path with one leading character\n> (such as /a, /x) may be recogonized as \"a:/\" or \"x:/\" if there is\n> such DOS drive on MSYS platform. Use an umambigous leading path\n> \"/foo\" instead.\n>\n> Also change two leading slashes (//) to three leading slashes (///),\n> otherwize it will be recognized as UNC name on MSYS platform.\n>\n> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  t/t0060-path-utils.sh | 56 +++++++++++++++++++++++++--------------------------\n>  1 file changed, 28 insertions(+), 28 deletions(-)\n\nThanks, ack.\n\n-- \nSebastian Schuberth\n"},{"id":"228942","messageId":"CAPig+cT+TQoO6tS-bbzstVbJSw=+B=_pbGzHo20+86+RCvf39w@mail.gmail.com","threadId":"34897","inReplyTo":"4a078e41976b25488571b1478a51e287ffdd55c8.1381717700.git.worldhello.net@gmail.com","subject":"Re: [PATCH v5 1/3] test: use unambigous leading path (/foo) for MSYS","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-10-14T19:40:59Z","receivedAt":"2013-10-14T19:40:59Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Oct 13, 2013 at 10:29 PM, Jiang Xin <worldhello.net@gmail.com> wrote:\n> In test cases for relative_path, path with one leading character\n> (such as /a, /x) may be recogonized as \"a:/\" or \"x:/\" if there is\n> such DOS drive on MSYS platform. Use an umambigous leading path\n> \"/foo\" instead.\n>\n> Also change two leading slashes (//) to three leading slashes (///),\n> otherwize it will be recognized as UNC name on MSYS platform.\n\ns/otherwize/otherwise/\n\n> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n"}]}