From 1cb4e5233ee8ec2ee7bc001cddb605a74dadcb3f Mon Sep 17 00:00:00 2001 From: prd Date: Mon, 13 May 2019 19:43:52 -0600 Subject: [PATCH] path: local: str return full path on value error --- dvc/path/local.py | 6 ++++++ tests/conftest.py | 33 +++++++++++++++++++++++++++++++++ tests/func/test_add.py | 13 +++++++++++++ 3 files changed, 52 insertions(+) diff --git a/dvc/path/local.py b/dvc/path/local.py index 4d90364c5..4129be1df 100644 --- a/dvc/path/local.py +++ b/dvc/path/local.py @@ -8,4 +8,10 @@ class PathLOCAL(PathBASE): scheme = Schemes.LOCAL def __str__(self): + if os.name == "nt" and not os.path.commonprefix( + [os.getcwd(), self.path] + ): + # In case of windows, when cache is on different drive than + # workspace, we will get ValueError when trying to get relpath + return self.path return os.path.relpath(self.path) diff --git a/tests/conftest.py b/tests/conftest.py index d43bd5a48..83c650111 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -97,3 +97,36 @@ def ssh(ssh_server): port=ssh_server.port, key_filename=key_path, ) + + +@pytest.fixture +def temporary_windows_drive(repo_dir): + import string + import win32api + from ctypes import windll + from win32con import DDD_REMOVE_DEFINITION + + drives = [ + s[0].upper() + for s in win32api.GetLogicalDriveStrings().split("\000") + if len(s) > 0 + ] + + new_drive_name = [ + letter for letter in string.ascii_uppercase if letter not in drives + ][0] + new_drive = "{}:".format(new_drive_name) + + target_path = repo_dir.mkdtemp() + + set_up_result = windll.kernel32.DefineDosDeviceW(0, new_drive, target_path) + if set_up_result == 0: + raise RuntimeError("Failed to mount windows drive!") + + yield new_drive + + tear_down_result = windll.kernel32.DefineDosDeviceW( + DDD_REMOVE_DEFINITION, new_drive, target_path + ) + if tear_down_result == 0: + raise RuntimeError("Could not unmount windows drive!") diff --git a/tests/func/test_add.py b/tests/func/test_add.py index 6b0610d01..ff905d137 100644 --- a/tests/func/test_add.py +++ b/tests/func/test_add.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals import os +import pytest + import dvc import time import shutil @@ -541,3 +543,14 @@ class TestAddUnprotected(TestDvc): self.assertFalse(os.access(self.FOO, os.W_OK)) self.assertTrue(System.is_hardlink(self.FOO)) + + +@pytest.mark.skipif(os.name != "nt", reason="Windows specific") +def test_windows_should_add_when_cache_on_different_drive( + dvc, repo_dir, temporary_windows_drive +): + ret = main(["config", "cache.dir", temporary_windows_drive]) + assert ret == 0 + + ret = main(["add", repo_dir.DATA]) + assert ret == 0