Skip to content

Commit

Permalink
win32(long path support): leave drive-less absolute paths intact
Browse files Browse the repository at this point in the history
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 <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Sep 18, 2024
1 parent f0c7c00 commit 2a1b191
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
12 changes: 11 additions & 1 deletion compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -3416,7 +3421,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;
}

Expand Down
9 changes: 9 additions & 0 deletions t/t2031-checkout-long-paths.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 2a1b191

Please sign in to comment.