Skip to content

Commit ae4aeb2

Browse files
committed
fix: make resolve_links_on_windows config-flagged functionality longpath-aware.
Signed-off-by: Stephen Mackenzie <maxnbk@users.noreply.github.com>
1 parent f92bd15 commit ae4aeb2

1 file changed

Lines changed: 22 additions & 2 deletions

File tree

src/rez/utils/filesystem.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,9 @@ def to_posixpath(path: str):
490490
return posixpath.sep.join(path.split(ntpath.sep))
491491

492492

493+
_WINDOWS_MAX_PATH = 259 # Win32 MAX_PATH minus the null terminator
494+
495+
493496
def _windows_realpath(path: str) -> str:
494497
"""Resolve symlinks and junctions on Windows without expanding mapped drives.
495498
@@ -513,14 +516,31 @@ def _windows_realpath(path: str) -> str:
513516
target = os.readlink(candidate)
514517
# os.readlink on Windows may return an extended-length path
515518
# (\\?\C:\... or \\?\UNC\server\share\...). Strip the prefix so
516-
# subsequent abspath/normpath calls produce ordinary paths.
519+
# we can work with ordinary path strings.
517520
if target.startswith("\\\\?\\UNC\\"):
518521
target = "\\\\" + target[8:]
519522
elif target.startswith("\\\\?\\"):
520523
target = target[4:]
521524
if not os.path.isabs(target):
522525
target = os.path.join(os.path.dirname(candidate), target)
523-
candidate = os.path.normpath(os.path.abspath(target))
526+
# For paths that exceed MAX_PATH, re-add the extended-length
527+
# prefix before calling abspath so the Win32 API (GetFullPathNameW)
528+
# can handle the length on hosts without LongPathsEnabled in the
529+
# registry. We strip the prefix again afterwards so the rest of
530+
# the walk operates on ordinary path strings.
531+
if len(target) > _WINDOWS_MAX_PATH:
532+
if target.startswith("\\\\"):
533+
target = "\\\\?\\UNC\\" + target[2:]
534+
else:
535+
target = "\\\\?\\" + target
536+
candidate = os.path.abspath(target)
537+
if candidate.startswith("\\\\?\\UNC\\"):
538+
candidate = "\\\\" + candidate[8:]
539+
elif candidate.startswith("\\\\?\\"):
540+
candidate = candidate[4:]
541+
candidate = os.path.normpath(candidate)
542+
else:
543+
candidate = os.path.normpath(os.path.abspath(target))
524544
depth += 1
525545
result = candidate
526546
return result

0 commit comments

Comments
 (0)