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 <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin 2023-09-06 09:14:47 +02:00
Родитель 347dbbeb5a
Коммит 617101aab7
2 изменённых файлов: 20 добавлений и 1 удалений

Просмотреть файл

@ -304,6 +304,11 @@ int mingw_core_config(const char *var, const char *value,
return 0;
}
static inline int is_wdir_sep(wchar_t wchar)
{
return wchar == L'/' || wchar == L'\\';
}
/* Normalizes NT paths as returned by some low-level APIs. */
static wchar_t *normalize_ntpath(wchar_t *wbuf)
{
@ -3412,7 +3417,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;
}

Просмотреть файл

@ -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 <symlink-target)" &&
git update-index --add --cacheinfo 120000,$symlink_target_oid,PF &&
git -c core.symlinks=true checkout -- PF &&
cmd //c dir >actual &&
grep "<SYMLINKD\\?> *PF *\\[\\\\Program Files\\]" actual
'
test_done