Repository navigation
Conversation
…n_longpath str.lstrip removes any leading backslashes and question marks, not the '\?\' prefix, so a UNC path such as \server\share lost its leading backslashes. Compare the prefix instead, and map the '\?\UNC\' form back to a regular UNC path.
johnwparent
left a comment
There was a problem hiding this comment.
Thanks for this! Looks pretty good and catches a bone-headed bug I added.
Just a couple of small things
There was a problem hiding this comment.
Please remove this object file in general, but also from the history of this PR
| if path.startswith("\\\\?\\UNC\\"): | ||
| return "\\\\" + path[len("\\\\?\\UNC\\") :] | ||
| if path.startswith("\\\\?\\"): | ||
| return path[len("\\\\?\\") :] | ||
| return path |
There was a problem hiding this comment.
This is very close. I think the change we want to make though is to extract the long path prefix, and then make choices based on what follows it.
There are a few cases where we do want to return a path with the longpath prefix (because failing to do so would produce a broken path) like \\?\Volume{GUID}, we only want to strip the longpath if it precedes a path like a networked path or local absolute drive prefixed path.
UNC paths are also case insensitive.
| if path.startswith("\\\\?\\UNC\\"): | |
| return "\\\\" + path[len("\\\\?\\UNC\\") :] | |
| if path.startswith("\\\\?\\"): | |
| return path[len("\\\\?\\") :] | |
| return path | |
| prefix = "\\\\?\\" | |
| if not path.startswith(prefix): | |
| return path | |
| rest = path[len(prefix) :] | |
| if rest[:4].upper() == "UNC\\": | |
| return "\\\\" + rest[4:] | |
| if ntpath.splitdrive(rest)[0]: | |
| return rest | |
| return path |
Note: this suggestion requires an ntpath import.
| (r"\\server\share\spack", r"\\server\share\spack"), | ||
| (r"C:\spack\opt", r"C:\spack\opt"), | ||
| (r"?dir\file", r"?dir\file"), | ||
| ("", ""), |
There was a problem hiding this comment.
Let's add:
- drive relative paths,
- standard relative paths,
- \?\Volume{}\spack (GUID can be more or less whatever you want)
Let's also make this test Windows only pytest.mark.only_windows(...
sanitize_win_longpathusedpath.lstrip("\\\\?\\").str.lstriptakes a set of characters, not a prefix, so it removes every leading\and?:\\?\C:\spack\optC:\spack\optC:\spack\opt\\server\share\spack(UNC, no prefix)server\share\spack\\server\share\spack\\?\UNC\server\share\spackUNC\server\share\spack\\server\share\spack?dir\filedir\file?dir\fileIt is used by
_windows_readlink, so on Windows a symlink pointing to a network share came back as a relative-lookingserver\share\...(orUNC\server\...whenos.readlinkreturns the extended form). The function now checks for the prefix, and maps\\?\UNC\back to\\, the same way CPython'sntpathdoes.Added a parametrized
test_sanitize_win_longpathinlib/spack/spack/test/util/path.py(pure string checks, so it runs on any platform); three of the cases fail without the change.ruff checkandruff format --checkpass on both files.Note: I found this with a static check (ruff PLE1310) and used Claude (an AI assistant) to help write the fix and test; I reviewed and ran them.