Skip to content

Commit

Permalink
When looking at potentially long paths: leave drive-less absolute pat…
Browse files Browse the repository at this point in the history
…hs 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.
  • Loading branch information
dscho authored and Git for Windows Build Agent committed Nov 3, 2023
2 parents 2512387 + 04f0eca commit 3909cc1
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
7 changes: 6 additions & 1 deletion compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

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 3909cc1

Please sign in to comment.