From 39c0bdbe794b8784daf74980cb3c1d6230409d43 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Fri, 24 Jul 2020 14:44:04 +0300 Subject: [PATCH] dvc: properly handle relative symlinks (#4275) Fix #4160 --- dvc/utils/fs.py | 3 +-- tests/func/test_add.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/dvc/utils/fs.py b/dvc/utils/fs.py index 637f2b964b..d80bce6ede 100644 --- a/dvc/utils/fs.py +++ b/dvc/utils/fs.py @@ -96,8 +96,7 @@ def move(src, dst, mode=None): tmp = f"{dst}.{uuid()}" if os.path.islink(src): - # readlink does not accept path-like obj for Windows in Python <3.8 - shutil.copy(os.readlink(os.fspath(src)), tmp) + shutil.copy(src, tmp) os.unlink(src) else: shutil.move(src, tmp) diff --git a/tests/func/test_add.py b/tests/func/test_add.py index 2e7c48182b..92f9525e97 100644 --- a/tests/func/test_add.py +++ b/tests/func/test_add.py @@ -806,3 +806,23 @@ def test_add_pipeline_file(tmp_dir, dvc, run_copy): with pytest.raises(OutputIsStageFileError): dvc.add(PIPELINE_FILE) + + +def test_add_symlink(tmp_dir, dvc): + tmp_dir.gen({"dir": {"bar": "bar"}}) + + (tmp_dir / "dir" / "foo").symlink_to(os.path.join(".", "bar")) + + dvc.add(os.path.join("dir", "foo")) + + assert not (tmp_dir / "dir" / "foo").is_symlink() + assert not (tmp_dir / "dir" / "bar").is_symlink() + assert (tmp_dir / "dir" / "foo").read_text() == "bar" + assert (tmp_dir / "dir" / "bar").read_text() == "bar" + + assert (tmp_dir / ".dvc" / "cache").read_text() == { + "37": {"b51d194a7513e45b56f6524f2d51f2": "bar"} + } + assert not ( + tmp_dir / ".dvc" / "cache" / "37" / "b51d194a7513e45b56f6524f2d51f2" + ).is_symlink()