From 5e18924f8e9c29da811696bae5658754ce2cb2e7 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Thu, 25 Jan 2024 18:34:06 +0200 Subject: [PATCH] fetch: handle missing/modified imports (#10220) tests: pull after imp-url no-download Co-authored-by: dberenbaum --- dvc/fs/dvc.py | 9 +++++++++ dvc/repo/index.py | 4 +++- pyproject.toml | 2 +- tests/func/test_data_cloud.py | 22 ++++++++++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/dvc/fs/dvc.py b/dvc/fs/dvc.py index 89ca26eaee9..c75a86cec2a 100644 --- a/dvc/fs/dvc.py +++ b/dvc/fs/dvc.py @@ -532,6 +532,15 @@ def _prepare_credentials(self, **config) -> Dict[str, Any]: def fs(self) -> "_DVCFileSystem": return _DVCFileSystem(**self.fs_args) + @property + def immutable(self): + from dvc.scm import NoSCM + + if isinstance(self.fs.repo.scm, NoSCM): + return False + + return self.fs._repo_kwargs.get("rev") == self.fs.repo.get_rev() + def getcwd(self): return self.fs.getcwd() diff --git a/dvc/repo/index.py b/dvc/repo/index.py index 35eea98f2c7..fe9d29ca8d7 100644 --- a/dvc/repo/index.py +++ b/dvc/repo/index.py @@ -205,7 +205,9 @@ def _load_storage_from_import(storage_map, key, out): return dep = out.stage.deps[0] - if not out.hash_info: + if not out.hash_info and ( + not dep.hash_info or dep.hash_info.name != storage_map[key].cache.odb.hash_name + ): # partial import fs_cache = out.repo.cache.fs_cache storage_map.add_cache( diff --git a/pyproject.toml b/pyproject.toml index dc01a34e719..3687107ca37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ dependencies = [ "configobj>=5.0.6", "distro>=1.3", "dpath<3,>=2.1.0", - "dvc-data>=3.8,<3.9", + "dvc-data>=3.9,<3.10", "dvc-http>=2.29.0", "dvc-render>=1.0.1,<2", "dvc-studio-client>=0.17.1,<1", diff --git a/tests/func/test_data_cloud.py b/tests/func/test_data_cloud.py index 5e58edf53a5..01845ea3adf 100644 --- a/tests/func/test_data_cloud.py +++ b/tests/func/test_data_cloud.py @@ -277,6 +277,28 @@ def test_pull_partial_import(tmp_dir, dvc, local_workspace): assert stage.outs[0].get_hash().value == "d10b4c3ff123b26dc068d43a8bef2d23" +def test_pull_partial_import_missing(tmp_dir, dvc, local_workspace): + local_workspace.gen("file", "file content") + dst = tmp_dir / "file" + dvc.imp_url("remote://workspace/file", os.fspath(dst), no_download=True) + + (local_workspace / "file").unlink() + with pytest.raises(CheckoutError): + dvc.pull("file") + assert not dst.exists() + + +def test_pull_partial_import_modified(tmp_dir, dvc, local_workspace): + local_workspace.gen("file", "file content") + dst = tmp_dir / "file" + dvc.imp_url("remote://workspace/file", os.fspath(dst), no_download=True) + + local_workspace.gen("file", "updated file content") + with pytest.raises(CheckoutError): + dvc.pull("file") + assert not dst.exists() + + def test_pull_external_dvc_imports_mixed(tmp_dir, dvc, scm, erepo_dir, local_remote): with erepo_dir.chdir(): erepo_dir.dvc_gen("foo", "foo", commit="first")