Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
git clone <url> C:\cygwin\home\USER\repo' is working (again)
A regression for cygwin users was introduced with commit 05b458c, "real_path: resolve symlinks by hand". In the the commit message we read: The current implementation of real_path uses chdir() in order to resolve symlinks. Unfortunately this isn't thread-safe as chdir() affects a process as a whole... The old (and non-thread-save) OS calls chdir()/pwd() had been replaced by a string operation. The cygwin layer "knows" that "C:\cygwin" is an absolute path, but the new string operation does not. "git clone <url> C:\cygwin\home\USER\repo" fails like this: fatal: Invalid path '/home/USER/repo/C:\cygwin\home\USER\repo' The solution is to implement has_dos_drive_prefix(), skip_dos_drive_prefix() is_dir_sep(), offset_1st_component() and convert_slashes() for cygwin in the same way as it is done in 'Git for Windows' in compat/mingw.[ch] Extract the needed code into compat/win32/path-utils.[ch] and use it for cygwin as well. Reported-by: Steven Penny <svnpenn@gmail.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Torsten Bögershausen <tboegi@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Showing
with
54 additions
and 72 deletions.
- +0 −19 compat/cygwin.c
- +0 −2 compat/cygwin.h
- +1 −28 compat/mingw.c
- +0 −20 compat/mingw.h
- +28 −0 compat/win32/path-utils.c
- +20 −0 compat/win32/path-utils.h
- +2 −1 config.mak.uname
- +2 −1 git-compat-util.h
- +1 −1 t/t5601-clone.sh
| @@ -0,0 +1,28 @@ | ||
| #include "../../git-compat-util.h" | ||
|
|
||
| int win32_skip_dos_drive_prefix(char **path) | ||
| { | ||
| int ret = has_dos_drive_prefix(*path); | ||
| *path += ret; | ||
| return ret; | ||
| } | ||
|
|
||
| int win32_offset_1st_component(const char *path) | ||
| { | ||
| char *pos = (char *)path; | ||
|
|
||
| /* unc paths */ | ||
| if (!skip_dos_drive_prefix(&pos) && | ||
| is_dir_sep(pos[0]) && is_dir_sep(pos[1])) { | ||
| /* skip server name */ | ||
| pos = strpbrk(pos + 2, "\\/"); | ||
| if (!pos) | ||
| return 0; /* Error: malformed unc path */ | ||
|
|
||
| do { | ||
| pos++; | ||
| } while (*pos && !is_dir_sep(*pos)); | ||
| } | ||
|
|
||
| return pos + is_dir_sep(*pos) - path; | ||
| } |
| @@ -0,0 +1,20 @@ | ||
| #define has_dos_drive_prefix(path) \ | ||
| (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0) | ||
| int win32_skip_dos_drive_prefix(char **path); | ||
| #define skip_dos_drive_prefix win32_skip_dos_drive_prefix | ||
| static inline int win32_is_dir_sep(int c) | ||
| { | ||
| return c == '/' || c == '\\'; | ||
| } | ||
| #define is_dir_sep win32_is_dir_sep | ||
| static inline char *win32_find_last_dir_sep(const char *path) | ||
| { | ||
| char *ret = NULL; | ||
| for (; *path; ++path) | ||
| if (is_dir_sep(*path)) | ||
| ret = (char *)path; | ||
| return ret; | ||
| } | ||
| #define find_last_dir_sep win32_find_last_dir_sep | ||
| int win32_offset_1st_component(const char *path); | ||
| #define offset_1st_component win32_offset_1st_component |