Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions dvc/repo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
48 changes: 48 additions & 0 deletions tests/unit/repo/test_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"