Skip to content

Commit 1cadad6

Browse files
tboegigitster
authored andcommitted
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 <[email protected]> Helped-by: Johannes Schindelin <[email protected]> Signed-off-by: Torsten Bögershausen <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 98cdfbb commit 1cadad6

File tree

9 files changed

+54
-72
lines changed

9 files changed

+54
-72
lines changed

compat/cygwin.c

Lines changed: 0 additions & 19 deletions
This file was deleted.

compat/cygwin.h

Lines changed: 0 additions & 2 deletions
This file was deleted.

compat/mingw.c

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ static inline int needs_hiding(const char *path)
294294
return 0;
295295

296296
/* We cannot use basename(), as it would remove trailing slashes */
297-
mingw_skip_dos_drive_prefix((char **)&path);
297+
win32_skip_dos_drive_prefix((char **)&path);
298298
if (!*path)
299299
return 0;
300300

@@ -2043,33 +2043,6 @@ pid_t waitpid(pid_t pid, int *status, int options)
20432043
return -1;
20442044
}
20452045

2046-
int mingw_skip_dos_drive_prefix(char **path)
2047-
{
2048-
int ret = has_dos_drive_prefix(*path);
2049-
*path += ret;
2050-
return ret;
2051-
}
2052-
2053-
int mingw_offset_1st_component(const char *path)
2054-
{
2055-
char *pos = (char *)path;
2056-
2057-
/* unc paths */
2058-
if (!skip_dos_drive_prefix(&pos) &&
2059-
is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
2060-
/* skip server name */
2061-
pos = strpbrk(pos + 2, "\\/");
2062-
if (!pos)
2063-
return 0; /* Error: malformed unc path */
2064-
2065-
do {
2066-
pos++;
2067-
} while (*pos && !is_dir_sep(*pos));
2068-
}
2069-
2070-
return pos + is_dir_sep(*pos) - path;
2071-
}
2072-
20732046
int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
20742047
{
20752048
int upos = 0, wpos = 0;

compat/mingw.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -397,32 +397,12 @@ HANDLE winansi_get_osfhandle(int fd);
397397
* git specific compatibility
398398
*/
399399

400-
#define has_dos_drive_prefix(path) \
401-
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
402-
int mingw_skip_dos_drive_prefix(char **path);
403-
#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
404-
static inline int mingw_is_dir_sep(int c)
405-
{
406-
return c == '/' || c == '\\';
407-
}
408-
#define is_dir_sep mingw_is_dir_sep
409-
static inline char *mingw_find_last_dir_sep(const char *path)
410-
{
411-
char *ret = NULL;
412-
for (; *path; ++path)
413-
if (is_dir_sep(*path))
414-
ret = (char *)path;
415-
return ret;
416-
}
417400
static inline void convert_slashes(char *path)
418401
{
419402
for (; *path; path++)
420403
if (*path == '\\')
421404
*path = '/';
422405
}
423-
#define find_last_dir_sep mingw_find_last_dir_sep
424-
int mingw_offset_1st_component(const char *path);
425-
#define offset_1st_component mingw_offset_1st_component
426406
#define PATH_SEP ';'
427407
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
428408
#define PRIuMAX "I64u"

compat/win32/path-utils.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "../../git-compat-util.h"
2+
3+
int win32_skip_dos_drive_prefix(char **path)
4+
{
5+
int ret = has_dos_drive_prefix(*path);
6+
*path += ret;
7+
return ret;
8+
}
9+
10+
int win32_offset_1st_component(const char *path)
11+
{
12+
char *pos = (char *)path;
13+
14+
/* unc paths */
15+
if (!skip_dos_drive_prefix(&pos) &&
16+
is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
17+
/* skip server name */
18+
pos = strpbrk(pos + 2, "\\/");
19+
if (!pos)
20+
return 0; /* Error: malformed unc path */
21+
22+
do {
23+
pos++;
24+
} while (*pos && !is_dir_sep(*pos));
25+
}
26+
27+
return pos + is_dir_sep(*pos) - path;
28+
}

compat/win32/path-utils.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#define has_dos_drive_prefix(path) \
2+
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
3+
int win32_skip_dos_drive_prefix(char **path);
4+
#define skip_dos_drive_prefix win32_skip_dos_drive_prefix
5+
static inline int win32_is_dir_sep(int c)
6+
{
7+
return c == '/' || c == '\\';
8+
}
9+
#define is_dir_sep win32_is_dir_sep
10+
static inline char *win32_find_last_dir_sep(const char *path)
11+
{
12+
char *ret = NULL;
13+
for (; *path; ++path)
14+
if (is_dir_sep(*path))
15+
ret = (char *)path;
16+
return ret;
17+
}
18+
#define find_last_dir_sep win32_find_last_dir_sep
19+
int win32_offset_1st_component(const char *path);
20+
#define offset_1st_component win32_offset_1st_component

config.mak.uname

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ ifeq ($(uname_O),Cygwin)
187187
UNRELIABLE_FSTAT = UnfortunatelyYes
188188
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
189189
MMAP_PREVENTS_DELETE = UnfortunatelyYes
190-
COMPAT_OBJS += compat/cygwin.o
190+
COMPAT_OBJS += compat/win32/path-utils.o
191191
FREAD_READS_DIRECTORIES = UnfortunatelyYes
192192
endif
193193
ifeq ($(uname_S),FreeBSD)
@@ -536,6 +536,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
536536
COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
537537
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
538538
COMPAT_OBJS += compat/mingw.o compat/winansi.o \
539+
compat/win32/path-utils.o \
539540
compat/win32/pthread.o compat/win32/syslog.o \
540541
compat/win32/dirent.o
541542
BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1

git-compat-util.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,11 @@
190190
#endif
191191

192192
#if defined(__CYGWIN__)
193-
#include "compat/cygwin.h"
193+
#include "compat/win32/path-utils.h"
194194
#endif
195195
#if defined(__MINGW32__)
196196
/* pull in Windows compatibility stuff */
197+
#include "compat/win32/path-utils.h"
197198
#include "compat/mingw.h"
198199
#elif defined(_MSC_VER)
199200
#include "compat/msvc.h"

t/t5601-clone.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ test_clone_url () {
487487
expect_ssh "$@"
488488
}
489489

490-
test_expect_success !MINGW 'clone c:temp is ssl' '
490+
test_expect_success !MINGW,!CYGWIN 'clone c:temp is ssl' '
491491
test_clone_url c:temp c temp
492492
'
493493

0 commit comments

Comments
 (0)