diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index a7c3d4d7ca..e878590342 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -388,8 +388,12 @@ def get_data_index_entry( workspace: str = "repo", ) -> tuple["DataIndex", "DataIndexEntry"]: if self.subrepos: - fs_path = self.dvcfs.from_os_path(path) fs = self.dvcfs.fs + fs_path = self.dvcfs.from_os_path(path) + # `path` is relative to the repo root, so anchor it there instead of + # letting it resolve against the current working directory (#11029). + if not fs_path.startswith(fs.root_marker): + fs_path = fs.join(fs.root_marker, fs_path) key = fs._get_key_from_relative(fs_path) subrepo, _, key = fs._get_subrepo_info(key) index = subrepo.index.data[workspace] diff --git a/tests/func/api/test_data.py b/tests/func/api/test_data.py index 48d4e98eed..2c948ae00c 100644 --- a/tests/func/api/test_data.py +++ b/tests/func/api/test_data.py @@ -32,6 +32,18 @@ def test_get_url_requires_dvc(tmp_dir, scm): api.get_url("foo", repo=f"file://{tmp_dir.as_posix()}") +def test_get_url_from_subdir(tmp_dir, dvc, local_remote): + # `path` is documented as relative to the repo root, so the result must not + # depend on the current working directory (see #11029). + tmp_dir.dvc_gen("foo", "foo") + subdir = tmp_dir / "subdir" + subdir.mkdir() + + expected = api.get_url("foo", repo=os.fspath(tmp_dir)) + with subdir.chdir(): + assert api.get_url("foo", repo=os.fspath(tmp_dir)) == expected + + def test_get_url_from_remote(tmp_dir, erepo_dir, cloud, local_cloud): erepo_dir.add_remote(config=cloud.config, name="other") erepo_dir.add_remote(config=local_cloud.config, default=True)