git: move branch iteration functionality from experiments into scm.git (#4810)

* git: move branch iteration functionality from experiments into scm.git

* add branch_revs unit test
This commit is contained in:
Peter Rowlands (변기호)
2020-10-30 19:06:35 +09:00
committed by GitHub
parent f827d641d5
commit 3d58f4b8ce
3 changed files with 40 additions and 29 deletions
+2 -28
View File
@@ -1,9 +1,6 @@
import logging
from collections import OrderedDict, defaultdict
from datetime import datetime
from typing import Optional
from funcy import first
from dvc.repo import locked
from dvc.repo.metrics.show import _collect_metrics, _read_metrics
@@ -20,7 +17,7 @@ def _collect_experiment(repo, rev, stash=False, sha_only=True):
if rev == "workspace":
res["timestamp"] = None
else:
commit = _resolve_commit(repo, rev)
commit = repo.scm.resolve_commit(rev)
res["timestamp"] = datetime.fromtimestamp(commit.committed_date)
configs = _collect_configs(repo, rev=rev)
@@ -47,38 +44,15 @@ def _collect_experiment(repo, rev, stash=False, sha_only=True):
return res
def _resolve_commit(repo, rev):
from git.objects.tag import TagObject
commit = repo.scm.repo.rev_parse(rev)
if isinstance(commit, TagObject):
commit = commit.object
return commit
def _collect_checkpoint_experiment(repo, branch, baseline, **kwargs):
res = OrderedDict()
exp_rev = repo.scm.resolve_rev(branch)
for rev in _branch_revs(repo, exp_rev, baseline):
for rev in repo.scm.branch_revs(exp_rev, baseline):
res[rev] = _collect_experiment(repo, rev, **kwargs)
res[rev]["checkpoint_tip"] = exp_rev
return res
def _branch_revs(repo, branch_tip, baseline: Optional[str] = None):
"""Iterate over revisions in a given branch (from newest to oldest).
If baseline is set, iterator will stop when the specified revision is
reached.
"""
commit = _resolve_commit(repo, branch_tip)
while commit is not None:
yield commit.hexsha
commit = first(commit.parents)
if commit and commit.hexsha == baseline:
return
@locked
def show(
repo,
+24 -1
View File
@@ -4,8 +4,9 @@ import logging
import os
import shlex
from functools import partial
from typing import Optional
from funcy import cached_property
from funcy import cached_property, first
from pathspec.patterns import GitWildMatchPattern
from dvc.exceptions import GitHookAlreadyExistsError
@@ -468,3 +469,25 @@ class Git(Base):
@property
def no_commits(self):
return not self.list_all_commits()
def branch_revs(self, branch: str, end_rev: Optional[str] = None):
"""Iterate over revisions in a given branch (from newest to oldest).
If end_rev is set, iterator will stop when the specified revision is
reached.
"""
commit = self.resolve_commit(branch)
while commit is not None:
yield commit.hexsha
commit = first(commit.parents)
if commit and commit.hexsha == end_rev:
return
def resolve_commit(self, rev):
"""Return Commit object for the specified revision."""
from git.objects.tag import TagObject
commit = self.repo.rev_parse(rev)
if isinstance(commit, TagObject):
commit = commit.object
return commit
+14
View File
@@ -109,3 +109,17 @@ def test_no_commits(tmp_dir):
Git().commit("foo")
assert not Git().no_commits
def test_branch_revs(tmp_dir, scm):
tmp_dir.scm_gen({"file": "0"}, commit="init")
init_rev = scm.get_rev()
expected = []
for i in range(1, 5):
tmp_dir.scm_gen({"file": f"{i}"}, commit=f"{i}")
expected.append(scm.get_rev())
for rev in scm.branch_revs("master", init_rev):
assert rev == expected.pop()
assert len(expected) == 0