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>
			
			
				maint
			
			
		
							parent
							
								
									98cdfbb84a
								
							
						
					
					
						commit
						1cadad6f65
					
				|  | @ -1,19 +0,0 @@ | |||
| #include "../git-compat-util.h" | ||||
| #include "../cache.h" | ||||
|  | ||||
| int cygwin_offset_1st_component(const char *path) | ||||
| { | ||||
| 	const char *pos = path; | ||||
| 	/* unc paths */ | ||||
| 	if (is_dir_sep(pos[0]) && is_dir_sep(pos[1])) { | ||||
| 		/* skip server name */ | ||||
| 		pos = strchr(pos + 2, '/'); | ||||
| 		if (!pos) | ||||
| 			return 0; /* Error: malformed unc path */ | ||||
|  | ||||
| 		do { | ||||
| 			pos++; | ||||
| 		} while (*pos && pos[0] != '/'); | ||||
| 	} | ||||
| 	return pos + is_dir_sep(*pos) - path; | ||||
| } | ||||
|  | @ -1,2 +0,0 @@ | |||
| int cygwin_offset_1st_component(const char *path); | ||||
| #define offset_1st_component cygwin_offset_1st_component | ||||
|  | @ -294,7 +294,7 @@ static inline int needs_hiding(const char *path) | |||
| 		return 0; | ||||
|  | ||||
| 	/* We cannot use basename(), as it would remove trailing slashes */ | ||||
| 	mingw_skip_dos_drive_prefix((char **)&path); | ||||
| 	win32_skip_dos_drive_prefix((char **)&path); | ||||
| 	if (!*path) | ||||
| 		return 0; | ||||
|  | ||||
|  | @ -2043,33 +2043,6 @@ pid_t waitpid(pid_t pid, int *status, int options) | |||
| 	return -1; | ||||
| } | ||||
|  | ||||
| int mingw_skip_dos_drive_prefix(char **path) | ||||
| { | ||||
| 	int ret = has_dos_drive_prefix(*path); | ||||
| 	*path += ret; | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int mingw_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; | ||||
| } | ||||
|  | ||||
| int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen) | ||||
| { | ||||
| 	int upos = 0, wpos = 0; | ||||
|  |  | |||
|  | @ -397,32 +397,12 @@ HANDLE winansi_get_osfhandle(int fd); | |||
|  * git specific compatibility | ||||
|  */ | ||||
|  | ||||
| #define has_dos_drive_prefix(path) \ | ||||
| 	(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0) | ||||
| int mingw_skip_dos_drive_prefix(char **path); | ||||
| #define skip_dos_drive_prefix mingw_skip_dos_drive_prefix | ||||
| static inline int mingw_is_dir_sep(int c) | ||||
| { | ||||
| 	return c == '/' || c == '\\'; | ||||
| } | ||||
| #define is_dir_sep mingw_is_dir_sep | ||||
| static inline char *mingw_find_last_dir_sep(const char *path) | ||||
| { | ||||
| 	char *ret = NULL; | ||||
| 	for (; *path; ++path) | ||||
| 		if (is_dir_sep(*path)) | ||||
| 			ret = (char *)path; | ||||
| 	return ret; | ||||
| } | ||||
| static inline void convert_slashes(char *path) | ||||
| { | ||||
| 	for (; *path; path++) | ||||
| 		if (*path == '\\') | ||||
| 			*path = '/'; | ||||
| } | ||||
| #define find_last_dir_sep mingw_find_last_dir_sep | ||||
| int mingw_offset_1st_component(const char *path); | ||||
| #define offset_1st_component mingw_offset_1st_component | ||||
| #define PATH_SEP ';' | ||||
| #if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800) | ||||
| #define PRIuMAX "I64u" | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -187,7 +187,7 @@ ifeq ($(uname_O),Cygwin) | |||
| 	UNRELIABLE_FSTAT = UnfortunatelyYes | ||||
| 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo | ||||
| 	MMAP_PREVENTS_DELETE = UnfortunatelyYes | ||||
| 	COMPAT_OBJS += compat/cygwin.o | ||||
| 	COMPAT_OBJS += compat/win32/path-utils.o | ||||
| 	FREAD_READS_DIRECTORIES = UnfortunatelyYes | ||||
| endif | ||||
| ifeq ($(uname_S),FreeBSD) | ||||
|  | @ -536,6 +536,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) | |||
| 	COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32 | ||||
| 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" | ||||
| 	COMPAT_OBJS += compat/mingw.o compat/winansi.o \ | ||||
| 		compat/win32/path-utils.o \ | ||||
| 		compat/win32/pthread.o compat/win32/syslog.o \ | ||||
| 		compat/win32/dirent.o | ||||
| 	BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1 | ||||
|  |  | |||
|  | @ -190,10 +190,11 @@ | |||
| #endif | ||||
|  | ||||
| #if defined(__CYGWIN__) | ||||
| #include "compat/cygwin.h" | ||||
| #include "compat/win32/path-utils.h" | ||||
| #endif | ||||
| #if defined(__MINGW32__) | ||||
| /* pull in Windows compatibility stuff */ | ||||
| #include "compat/win32/path-utils.h" | ||||
| #include "compat/mingw.h" | ||||
| #elif defined(_MSC_VER) | ||||
| #include "compat/msvc.h" | ||||
|  |  | |||
|  | @ -487,7 +487,7 @@ test_clone_url () { | |||
| 	expect_ssh "$@" | ||||
| } | ||||
|  | ||||
| test_expect_success !MINGW 'clone c:temp is ssl' ' | ||||
| test_expect_success !MINGW,!CYGWIN 'clone c:temp is ssl' ' | ||||
| 	test_clone_url c:temp c temp | ||||
| ' | ||||
|  | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Torsten Bögershausen
						Torsten Bögershausen