mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-10 15:28:34 +01:00
add: prevent crash while getting relpath (#5837)
* add: prevent crash while getting relpath Since python 3.8 os.path.realpath has resolved windows network shares to UNC paths. This breaks the logic for relpath as the UNC and mapped drive paths don't have an obvious common prefix. As it is not easy to go back to the mapped drive path from UNC path, this is resolved by always using the UNC paths for calculating relative paths in windows. Fixes #5832 * relpath: Update changes following review Two changes: - use pytest.mark.skipif rather than if statement inside test to make it clearer that test is windows specific - Use tail rather than upper_path to denote rest of path after drive name taken off (to match python documentation) Pull request: #5837 * tests, linter: update to add test case and apply linter though pre-commit Co-authored-by: Tom Rutter <[email protected]>
This commit is contained in:
+13
-4
@@ -319,10 +319,19 @@ def relpath(path, start=os.curdir):
|
||||
start = os.path.abspath(os.fspath(start))
|
||||
|
||||
# Windows path on different drive than curdir doesn't have relpath
|
||||
if os.name == "nt" and not os.path.commonprefix(
|
||||
[start, os.path.abspath(path)]
|
||||
):
|
||||
return path
|
||||
if os.name == "nt":
|
||||
# Since python 3.8 os.realpath resolves network shares to their UNC
|
||||
# path. So, to be certain that relative paths correctly captured,
|
||||
# we need to resolve to UNC path first. We resolve only the drive
|
||||
# name so that we don't follow any 'real' symlinks on the path
|
||||
def resolve_network_drive_windows(path_to_resolve):
|
||||
drive, tail = os.path.splitdrive(path_to_resolve)
|
||||
return os.path.join(os.path.realpath(drive), tail)
|
||||
|
||||
path = resolve_network_drive_windows(os.path.abspath(path))
|
||||
start = resolve_network_drive_windows(start)
|
||||
if not os.path.commonprefix([start, path]):
|
||||
return path
|
||||
return os.path.relpath(path, start)
|
||||
|
||||
|
||||
|
||||
@@ -113,6 +113,27 @@ def test_relpath():
|
||||
assert relpath(path) == relpath(path_info)
|
||||
|
||||
|
||||
@pytest.mark.skipif(os.name != "nt", reason="Windows specific")
|
||||
def test_relpath_windows(monkeypatch):
|
||||
"""test that relpath correctly generated when run on a
|
||||
windows network share. The drive mapped path is mapped
|
||||
to a UNC path by os.path.realpath"""
|
||||
|
||||
def dummy_realpath(path):
|
||||
return path.replace("x:", "\\\\server\\share")
|
||||
|
||||
monkeypatch.setattr(os.path, "realpath", dummy_realpath)
|
||||
assert (
|
||||
relpath("x:\\dir1\\dir2\\file.txt", "\\\\server\\share\\dir1")
|
||||
== "dir2\\file.txt"
|
||||
)
|
||||
|
||||
assert (
|
||||
relpath("y:\\dir1\\dir2\\file.txt", "\\\\server\\share\\dir1")
|
||||
== "y:\\dir1\\dir2\\file.txt"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"inp,out,is_dir,expected",
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user