Skip to content

Commit 3909cc1

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
When looking at potentially long paths: leave drive-less absolute paths intact (#4592)
Git for Windows does not handle symbolic links correctly when their target is an absolute path without a drive prefix: a drive prefix is added. These type of paths, however, are completely legitimate on Windows, they are _kind of_ absolute paths, as they are still relative to the current directory's drive. So let's handle them as intended: by ensuring that targets that have no drive prefix _before_ normalization still don't have a drive prefix _after_ normalization. Oddly enough, the code that needs to be patched seems to have nothing to do with symbolic links, but all with long paths. Yet this is precisely the code path taken by `win32_create_symlink()` that adds that drive prefix (via normalization). The reason why only symbolic links seem to be affected is that this is the only usage where the resulting path is persisted instead of merely used in subsequent function calls. This fixes #4586.
2 parents 2512387 + 04f0eca commit 3909cc1

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

compat/mingw.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -3851,7 +3851,12 @@ int handle_long_path(wchar_t *path, int len, int max_path, int expand)
38513851
* "cwd + path" doesn't due to '..' components)
38523852
*/
38533853
if (result < max_path) {
3854-
wcscpy(path, buf);
3854+
/* Be careful not to add a drive prefix if there was none */
3855+
if (is_wdir_sep(path[0]) &&
3856+
!is_wdir_sep(buf[0]) && buf[1] == L':' && is_wdir_sep(buf[2]))
3857+
wcscpy(path, buf + 2);
3858+
else
3859+
wcscpy(path, buf);
38553860
return result;
38563861
}
38573862

t/t2031-checkout-long-paths.sh

+9
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)