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; | 		return 0; | ||||||
|  |  | ||||||
| 	/* We cannot use basename(), as it would remove trailing slashes */ | 	/* 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) | 	if (!*path) | ||||||
| 		return 0; | 		return 0; | ||||||
|  |  | ||||||
|  | @ -2043,33 +2043,6 @@ pid_t waitpid(pid_t pid, int *status, int options) | ||||||
| 	return -1; | 	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 xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen) | ||||||
| { | { | ||||||
| 	int upos = 0, wpos = 0; | 	int upos = 0, wpos = 0; | ||||||
|  |  | ||||||
|  | @ -397,32 +397,12 @@ HANDLE winansi_get_osfhandle(int fd); | ||||||
|  * git specific compatibility |  * 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) | static inline void convert_slashes(char *path) | ||||||
| { | { | ||||||
| 	for (; *path; path++) | 	for (; *path; path++) | ||||||
| 		if (*path == '\\') | 		if (*path == '\\') | ||||||
| 			*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 ';' | #define PATH_SEP ';' | ||||||
| #if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800) | #if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800) | ||||||
| #define PRIuMAX "I64u" | #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 | 	UNRELIABLE_FSTAT = UnfortunatelyYes | ||||||
| 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo | 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo | ||||||
| 	MMAP_PREVENTS_DELETE = UnfortunatelyYes | 	MMAP_PREVENTS_DELETE = UnfortunatelyYes | ||||||
| 	COMPAT_OBJS += compat/cygwin.o | 	COMPAT_OBJS += compat/win32/path-utils.o | ||||||
| 	FREAD_READS_DIRECTORIES = UnfortunatelyYes | 	FREAD_READS_DIRECTORIES = UnfortunatelyYes | ||||||
| endif | endif | ||||||
| ifeq ($(uname_S),FreeBSD) | ifeq ($(uname_S),FreeBSD) | ||||||
|  | @ -536,6 +536,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) | ||||||
| 	COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32 | 	COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32 | ||||||
| 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" | 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" | ||||||
| 	COMPAT_OBJS += compat/mingw.o compat/winansi.o \ | 	COMPAT_OBJS += compat/mingw.o compat/winansi.o \ | ||||||
|  | 		compat/win32/path-utils.o \ | ||||||
| 		compat/win32/pthread.o compat/win32/syslog.o \ | 		compat/win32/pthread.o compat/win32/syslog.o \ | ||||||
| 		compat/win32/dirent.o | 		compat/win32/dirent.o | ||||||
| 	BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1 | 	BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1 | ||||||
|  |  | ||||||
|  | @ -190,10 +190,11 @@ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined(__CYGWIN__) | #if defined(__CYGWIN__) | ||||||
| #include "compat/cygwin.h" | #include "compat/win32/path-utils.h" | ||||||
| #endif | #endif | ||||||
| #if defined(__MINGW32__) | #if defined(__MINGW32__) | ||||||
| /* pull in Windows compatibility stuff */ | /* pull in Windows compatibility stuff */ | ||||||
|  | #include "compat/win32/path-utils.h" | ||||||
| #include "compat/mingw.h" | #include "compat/mingw.h" | ||||||
| #elif defined(_MSC_VER) | #elif defined(_MSC_VER) | ||||||
| #include "compat/msvc.h" | #include "compat/msvc.h" | ||||||
|  |  | ||||||
|  | @ -487,7 +487,7 @@ test_clone_url () { | ||||||
| 	expect_ssh "$@" | 	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 | 	test_clone_url c:temp c temp | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Torsten Bögershausen
						Torsten Bögershausen