diff --git a/dvc/config.py b/dvc/config.py index 1fc63acbb3..224e1ac28a 100644 --- a/dvc/config.py +++ b/dvc/config.py @@ -1,16 +1,27 @@ """DVC config objects.""" -from contextlib import contextmanager import logging import os import re +from contextlib import contextmanager +from functools import partial from urllib.parse import urlparse -from funcy import cached_property, re_find, walk_values, compact import configobj -from voluptuous import Schema, Optional, Invalid, ALLOW_EXTRA -from voluptuous import All, Any, Lower, Range, Coerce +from funcy import cached_property, compact, re_find, walk_values +from voluptuous import ( + ALLOW_EXTRA, + All, + Any, + Coerce, + Invalid, + Lower, + Optional, + Range, + Schema, +) from dvc.exceptions import DvcException, NotDvcRepoError +from dvc.path_info import PathInfo from dvc.utils import relpath logger = logging.getLogger(__name__) @@ -312,16 +323,19 @@ def resolve(path): return Config._map_dirs(conf, resolve) @staticmethod - def _save_paths(conf, filename): - conf_dir = os.path.dirname(filename) + def _to_relpath(conf_dir, path): + if re.match(r"\w+://", path): + return path - def rel(path): - if re.match(r"\w+://", path): - return path + if isinstance(path, RelPath) or not os.path.isabs(path): + path = relpath(path, conf_dir) - if isinstance(path, RelPath) or not os.path.isabs(path): - return relpath(path, conf_dir) - return path + return PathInfo(path).as_posix() + + @staticmethod + def _save_paths(conf, filename): + conf_dir = os.path.dirname(filename) + rel = partial(Config._to_relpath, conf_dir) return Config._map_dirs(conf, rel) diff --git a/tests/func/test_cache.py b/tests/func/test_cache.py index 8d692938d2..841e06f1cd 100644 --- a/tests/func/test_cache.py +++ b/tests/func/test_cache.py @@ -8,8 +8,7 @@ from dvc.main import main from dvc.remote.base import DirCacheError from dvc.utils import relpath -from tests.basic_env import TestDir -from tests.basic_env import TestDvc +from tests.basic_env import TestDir, TestDvc class TestCache(TestDvc): @@ -155,7 +154,7 @@ def test_abs_path(self): self.assertEqual(ret, 0) config = configobj.ConfigObj(self.dvc.config.files["repo"]) - self.assertEqual(config["cache"]["dir"], dname) + self.assertEqual(config["cache"]["dir"], dname.replace("\\", "/")) def test_relative_path(self): tmpdir = self.mkdtemp() @@ -167,7 +166,7 @@ def test_relative_path(self): # dir path written to config should be just one level above. rel = os.path.join("..", dname) config = configobj.ConfigObj(self.dvc.config.files["repo"]) - self.assertEqual(config["cache"]["dir"], rel) + self.assertEqual(config["cache"]["dir"], rel.replace("\\", "/")) ret = main(["add", self.FOO]) self.assertEqual(ret, 0) diff --git a/tests/func/test_remote.py b/tests/func/test_remote.py index 4369203dd7..0d3f9e9f54 100644 --- a/tests/func/test_remote.py +++ b/tests/func/test_remote.py @@ -47,7 +47,9 @@ def test_relative_path(self): # dir path written to config should be just one level above. rel = os.path.join("..", dname) config = configobj.ConfigObj(self.dvc.config.files["repo"]) - self.assertEqual(config['remote "mylocal"']["url"], rel) + self.assertEqual( + config['remote "mylocal"']["url"], rel.replace("\\", "/") + ) def test_overwrite(self): remote_name = "a" diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py new file mode 100644 index 0000000000..e0899cbf3e --- /dev/null +++ b/tests/unit/test_config.py @@ -0,0 +1,17 @@ +import os +import pytest + +from dvc.config import Config + + +@pytest.mark.parametrize( + "path, expected", + [ + ("cache", "../cache"), + (os.path.join("..", "cache"), "../../cache"), + (os.getcwd(), os.getcwd().replace("\\", "/")), + ("ssh://some/path", "ssh://some/path"), + ], +) +def test_to_relpath(path, expected): + assert Config._to_relpath(os.path.join(".", "config"), path) == expected