From 2a04263f021db190641ee2ca077b70563c74cdea Mon Sep 17 00:00:00 2001 From: David de la Iglesia Castro Date: Thu, 27 Apr 2023 10:24:07 +0200 Subject: [PATCH] api: Add `scm` module with `all_{X}` methods for listing revs. --- dvc/api/__init__.py | 4 +++ dvc/api/scm.py | 54 ++++++++++++++++++++++++++++++++++++++ tests/func/api/test_scm.py | 30 +++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 dvc/api/scm.py create mode 100644 tests/func/api/test_scm.py diff --git a/dvc/api/__init__.py b/dvc/api/__init__.py index 6675f3635..dc34f5c46 100644 --- a/dvc/api/__init__.py +++ b/dvc/api/__init__.py @@ -3,9 +3,13 @@ from dvc.fs.dvc import _DVCFileSystem as DVCFileSystem from .data import open # pylint: disable=redefined-builtin from .data import get_url, read from .experiments import exp_save, exp_show, make_checkpoint +from .scm import all_branches, all_commits, all_tags from .show import metrics_show, params_show __all__ = [ + "all_branches", + "all_commits", + "all_tags", "exp_save", "exp_show", "get_url", diff --git a/dvc/api/scm.py b/dvc/api/scm.py new file mode 100644 index 000000000..b3656bd7c --- /dev/null +++ b/dvc/api/scm.py @@ -0,0 +1,54 @@ +from typing import List, Optional + +from dvc.repo import Repo + + +def all_branches(repo: Optional[str] = None) -> List[str]: + """Get all Git branches in a DVC repository. + + Args: + repo (str, optional): location of the DVC repository. + Defaults to the current project (found by walking up from the + current working directory tree). + It can be a URL or a file system path. + Both HTTP and SSH protocols are supported for online Git repos + (e.g. [user@]server:project.git). + Returns: + List[str]: Names of the Git branches. + """ + with Repo.open(repo) as _repo: + return _repo.scm.list_branches() + + +def all_commits(repo: Optional[str] = None) -> List[str]: + """Get all Git commits in a DVC repository. + + Args: + repo (str, optional): location of the DVC repository. + Defaults to the current project (found by walking up from the + current working directory tree). + It can be a URL or a file system path. + Both HTTP and SSH protocols are supported for online Git repos + (e.g. [user@]server:project.git). + Returns: + List[str]: SHAs of the Git commits. + """ + with Repo.open(repo) as _repo: + return _repo.scm.list_all_commits() + + +def all_tags(repo: Optional[str] = None) -> List[str]: + """Get all Git tags in a DVC repository. + + Args: + repo (str, optional): location of the DVC repository. + Defaults to the current project (found by walking up from the + current working directory tree). + It can be a URL or a file system path. + Both HTTP and SSH protocols are supported for online Git repos + (e.g. [user@]server:project.git). + Returns: + List[str]: Names of the Git tags. + """ + with Repo.open(repo) as _repo: + return _repo.scm.list_tags() diff --git a/tests/func/api/test_scm.py b/tests/func/api/test_scm.py new file mode 100644 index 000000000..bd13d5cec --- /dev/null +++ b/tests/func/api/test_scm.py @@ -0,0 +1,30 @@ +from dvc.api.scm import all_branches, all_commits, all_tags + + +def test_all_branches(tmp_dir, scm, dvc): + assert all_branches() == ["master"] + + with tmp_dir.branch("branch", new=True): + tmp_dir.scm_gen("branch", "branch", "commit") + + assert all_branches() == ["branch", "master"] + + +def test_all_commits(tmp_dir, scm, dvc): + first = scm.get_rev() + assert all_commits() == [first] + + tmp_dir.scm_gen("foo", "foo", "commit") + second = scm.get_rev() + + assert set(all_commits()) == {first, second} + + +def test_all_tags(tmp_dir, scm, dvc): + scm.tag("v1") + assert all_tags() == ["v1"] + + tmp_dir.scm_gen("foo", "foo", "commit") + scm.tag("v2") + + assert set(all_tags()) == {"v1", "v2"}