def _unprotect_file(path): if System.is_symlink(path) or System.is_hardlink(path): logger.debug("Unprotecting '{}'".format(path)) tmp = os.path.join(os.path.dirname(path), "." + uuid()) # The operations order is important here - if some application # would access the file during the process of copyfile then it # would get only the part of file. So, at first, the file should be # copied with the temporary name, and then original file should be # replaced by new. copyfile(path, tmp, name="Unprotecting '{}'".format(relpath(path))) remove(path) os.rename(tmp, path) else: logger.debug("Skipping copying for '{}', since it is not " "a symlink or a hardlink.".format(path)) os.chmod(path, os.stat(path).st_mode | stat.S_IWRITE)
def _unprotect_file(self, path): import stat import uuid from dvc.system import System from dvc.utils import copyfile, move, remove if System.is_symlink(path) or System.is_hardlink(path): logger.debug("Unprotecting '{}'".format(path)) tmp = os.path.join(os.path.dirname(path), "." + str(uuid.uuid4())) move(path, tmp) copyfile(tmp, path) remove(tmp) else: logger.debug("Skipping copying for '{}', since it is not " "a symlink or a hardlink.".format(path)) os.chmod(path, os.stat(path).st_mode | stat.S_IWRITE)
def test_hardlink_optimization(tmp_dir, dvc, ssh): from dvc.fs import get_cloud_fs cls, config, path_info = get_cloud_fs(dvc, **ssh.config) fs = cls(**config) assert isinstance(fs, SSHFileSystem) from_info = path_info / "empty" to_info = path_info / "link" with fs.open(from_info, "wb"): pass if os.name == "nt": link_path = "c:" + to_info.path.replace("/", "\\") else: link_path = to_info.path fs.hardlink(from_info, to_info) assert not System.is_hardlink(link_path)
def iscopy(self, path_info): return not (System.is_symlink(path_info) or System.is_hardlink(path_info))
def is_hardlink(path_info): return System.is_hardlink(path_info)
tmp_dir.dvc_gen({"foo": "foo", "bar": "bar"}) shutil.copy("bar", "foo") copy_spy = mocker.spy(dvc.cache.local.tree, "copy") dvc.add("foo") assert copy_spy.mock.call_count == 0 @pytest.mark.parametrize( "link,new_link,link_test_func", [ ("hardlink", "copy", lambda path: not System.is_hardlink(path)), ("symlink", "copy", lambda path: not System.is_symlink(path)), ("copy", "hardlink", System.is_hardlink), ("copy", "symlink", System.is_symlink), ], ) def test_should_relink_on_repeated_add(link, new_link, link_test_func, tmp_dir, dvc): from dvc.path_info import PathInfo dvc.config["cache"]["type"] = link tmp_dir.dvc_gen({"foo": "foo", "bar": "bar"}) os.remove("foo") getattr(dvc.cache.local.tree, link)(PathInfo("bar"), PathInfo("foo"))
def is_hardlink(path): return System.is_hardlink(path)
def test_reflink(repo_dir, ssh): ssh.reflink("foo", "link") assert filecmp.cmp("foo", "link") assert not System.is_symlink("link") assert not System.is_hardlink("link")
def test_hardlink(repo_dir, ssh): ssh.hardlink("foo", "link") assert System.is_hardlink("link")
def test_reflink(tmp_dir, ssh): tmp_dir.gen("foo", "foo content") ssh.reflink("foo", "link") assert filecmp.cmp("foo", "link") assert not System.is_symlink("link") assert not System.is_hardlink("link")
def test_hardlink(tmp_dir, ssh): tmp_dir.gen("foo", "foo content") ssh.hardlink("foo", "link") assert System.is_hardlink("link")