From f558f3fbc6bf7f24ee5d2356b65b7f97e025c902 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 6 Sep 2023 09:14:47 +0200 Subject: [PATCH] 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 https://github.com/git-for-windows/git/issues/4586. Signed-off-by: Johannes Schindelin --- compat/mingw.c | 7 ++++++- t/t2031-checkout-long-paths.sh | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/compat/mingw.c b/compat/mingw.c index 8b7b526d9f6fa6..41831e88163ee2 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -3851,7 +3851,12 @@ int handle_long_path(wchar_t *path, int len, int max_path, int expand) * "cwd + path" doesn't due to '..' components) */ if (result < max_path) { - wcscpy(path, buf); + /* Be careful not to add a drive prefix if there was none */ + if (is_wdir_sep(path[0]) && + !is_wdir_sep(buf[0]) && buf[1] == L':' && is_wdir_sep(buf[2])) + wcscpy(path, buf + 2); + else + wcscpy(path, buf); return result; } diff --git a/t/t2031-checkout-long-paths.sh b/t/t2031-checkout-long-paths.sh index f30f8920ca689c..15416a1d6ee8c7 100755 --- a/t/t2031-checkout-long-paths.sh +++ b/t/t2031-checkout-long-paths.sh @@ -99,4 +99,13 @@ test_expect_success SHORTABSPATH 'clean up path close to MAX_PATH' ' test ! -d "$subdir1" ' +test_expect_success SYMLINKS_WINDOWS 'leave drive-less, short paths intact' ' + printf "/Program Files" >symlink-target && + symlink_target_oid="$(git hash-object -w --stdin actual && + grep " *PF *\\[\\\\Program Files\\]" actual +' + test_done