Re: [PATCH] fix pushing to //server/share/dir paths on Windows
From: Junio C Hamano <hidden>
Date: 2016-12-13 22:48:55
Johannes Sixt [off-list ref] writes:
There is a change in behavior: \\server\share is not transformed into //server/share anymore, but all subsequent directory separators are rewritten to '/'. This should not make a difference; Windows can handle the mix.
I saw Dscho had a similar "windows can handle the mix" change in an earlier development cycle, I think, and this is being consistent.
Another long-standing bug uncovered by the quarantine series. Dscho, it looks like this could fix the original report at https://github.com/git-for-windows/git/issues/979 This patch should cook well because of the change in behavior. I would not be surprised if there is some fall-out. The other bug I'm alluding to, I still have to investigate. I do not think that it can be counted as fall-out. path.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
Thanks.
quoted hunk
diff --git a/path.c b/path.c index 52d889c88e..02dc70fb92 100644 --- a/path.c +++ b/path.c@@ -991,7 +991,7 @@ const char *remove_leading_path(const char *in, const char *prefix) * * Performs the following normalizations on src, storing the result in dst: * - Ensures that components are separated by '/' (Windows only) - * - Squashes sequences of '/'. + * - Squashes sequences of '/' except "//server/share" on Windows
"on windows" because offset_1st_component() does the magic only there? Makes sense.
quoted hunk
* - Removes "." components. * - Removes ".." components, and the components the precede them. * Returns failure (non-zero) if a ".." component appears as first path@@ -1014,17 +1014,23 @@ const char *remove_leading_path(const char *in, const char *prefix) int normalize_path_copy_len(char *dst, const char *src, int *prefix_len) { char *dst0; - int i; - - for (i = has_dos_drive_prefix(src); i > 0; i--) - *dst++ = *src++; - dst0 = dst; + int offset; - if (is_dir_sep(*src)) { + /* + * Handle initial part of absolute path: "/", "C:/", "\\server\share/". + */ + offset = offset_1st_component(src); + if (offset) { + /* Convert the trailing separator to '/' on Windows. */ + memcpy(dst, src, offset - 1); + dst += offset - 1; *dst++ = '/'; - while (is_dir_sep(*src)) - src++; + src += offset; } + dst0 = dst;
By resetting dst0 here, we ensure that up_one that is triggered by seeing "../" will not escape the \\server\share\ part, which makes sense to me.
+ while (is_dir_sep(*src))
+ src++;
for (;;) {
char c = *src;