From 44b78b81b99bac06bf4549487656a5d20005f5b6 Mon Sep 17 00:00:00 2001 From: Matt Seddon Date: Tue, 6 Feb 2024 12:01:33 +1100 Subject: [PATCH] repo: add get_subrepo_relpath helper for studio live experiments monorepo support --- dvc/repo/__init__.py | 11 +++++++++ tests/unit/repo/test_repo.py | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index c10965f432..36d0f56752 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -13,6 +13,7 @@ ) from dvc.ignore import DvcIgnoreFilter from dvc.log import logger +from dvc.utils import as_posix from dvc.utils.objects import cached_property if TYPE_CHECKING: @@ -350,6 +351,16 @@ def fs(self, fs: "FileSystem"): # fs. self._reset() + @property + def subrepo_relpath(self) -> str: + from dvc.fs import GitFileSystem + + scm_root_dir = "/" if isinstance(self.fs, GitFileSystem) else self.scm.root_dir + + relpath = as_posix(self.fs.relpath(self.root_dir, scm_root_dir)) + + return "" if relpath == "." else relpath + @property def data_index(self) -> "DataIndex": from dvc_data.index import DataIndex diff --git a/tests/unit/repo/test_repo.py b/tests/unit/repo/test_repo.py index 897a4c3b39..c3ea4cd713 100644 --- a/tests/unit/repo/test_repo.py +++ b/tests/unit/repo/test_repo.py @@ -135,3 +135,51 @@ def test_dynamic_cache_initialization(tmp_dir, scm): dvc.close() Repo(str(tmp_dir)).close() + + +def test_monorepo_relpath(tmp_dir, scm): + from dvc.repo.destroy import destroy + + tmp_dir.gen({"project_a": {}, "subdir/project_b": {}}) + + non_monorepo = Repo.init(tmp_dir) + assert non_monorepo.subrepo_relpath == "" + + destroy(non_monorepo) + + monorepo_project_a = Repo.init(tmp_dir / "project_a", subdir=True) + + assert monorepo_project_a.subrepo_relpath == "project_a" + + monorepo_project_b = Repo.init(tmp_dir / "subdir" / "project_b", subdir=True) + + assert monorepo_project_b.subrepo_relpath == "subdir/project_b" + + +def test_virtual_monorepo_relpath(tmp_dir, scm): + from dvc.fs.git import GitFileSystem + from dvc.repo.destroy import destroy + + tmp_dir.gen({"project_a": {}, "subdir/project_b": {}}) + scm.commit("initial commit") + gfs = GitFileSystem(scm=scm, rev="master") + + non_monorepo = Repo.init(tmp_dir) + non_monorepo.fs = gfs + non_monorepo.root_dir = "/" + + assert non_monorepo.subrepo_relpath == "" + + destroy(non_monorepo) + + monorepo_project_a = Repo.init(tmp_dir / "project_a", subdir=True) + monorepo_project_a.fs = gfs + monorepo_project_a.root_dir = "/project_a" + + assert monorepo_project_a.subrepo_relpath == "project_a" + + monorepo_project_b = Repo.init(tmp_dir / "subdir" / "project_b", subdir=True) + monorepo_project_b.fs = gfs + monorepo_project_b.root_dir = "/subdir/project_b" + + assert monorepo_project_b.subrepo_relpath == "subdir/project_b"