Skip to content

Commit 713d033

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
win32(long path support): leave drive-less absolute paths intact
When trying to ensure that long paths are handled correctly, we first normalize absolute paths as we encounter them. However, if the path is a so-called "drive-less" absolute path, i.e. if it is relative to the current drive but _does_ start with a directory separator, we would want the normalized path to be such a drive-less absolute path, too. Let's do that, being careful to still include the drive prefix when we need to go through the `\\?\` dance (because there, the drive prefix is absolutely required). This fixes #4586. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent edbeb8c commit 713d033

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

compat/mingw.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,11 @@ int mingw_core_config(const char *var, const char *value,
301301
return 0;
302302
}
303303

304+
static inline int is_wdir_sep(wchar_t wchar)
305+
{
306+
return wchar == L'/' || wchar == L'\\';
307+
}
308+
304309
/* Normalizes NT paths as returned by some low-level APIs. */
305310
static wchar_t *normalize_ntpath(wchar_t *wbuf)
306311
{
@@ -3648,7 +3653,12 @@ int handle_long_path(wchar_t *path, int len, int max_path, int expand)
36483653
* "cwd + path" doesn't due to '..' components)
36493654
*/
36503655
if (result < max_path) {
3651-
wcscpy(path, buf);
3656+
/* Be careful not to add a drive prefix if there was none */
3657+
if (is_wdir_sep(path[0]) &&
3658+
!is_wdir_sep(buf[0]) && buf[1] == L':' && is_wdir_sep(buf[2]))
3659+
wcscpy(path, buf + 2);
3660+
else
3661+
wcscpy(path, buf);
36523662
return result;
36533663
}
36543664

t/t2031-checkout-long-paths.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,13 @@ test_expect_success SHORTABSPATH 'clean up path close to MAX_PATH' '
9999
test ! -d "$subdir1"
100100
'
101101

102+
test_expect_success SYMLINKS_WINDOWS 'leave drive-less, short paths intact' '
103+
printf "/Program Files" >symlink-target &&
104+
symlink_target_oid="$(git hash-object -w --stdin <symlink-target)" &&
105+
git update-index --add --cacheinfo 120000,$symlink_target_oid,PF &&
106+
git -c core.symlinks=true checkout -- PF &&
107+
cmd //c dir >actual &&
108+
grep "<SYMLINKD\\?> *PF *\\[\\\\Program Files\\]" actual
109+
'
110+
102111
test_done

0 commit comments

Comments
 (0)