erepo: include exp refs in clones

- add test for dvc get --rev=<exp>
This commit is contained in:
Peter Rowlands
2022-04-09 10:27:06 +09:00
committed by Peter Rowlands (변기호)
parent 7dd0cffd49
commit 69acbe33c9
4 changed files with 54 additions and 8 deletions
+18 -7
View File
@@ -3,7 +3,7 @@ import os
import tempfile
import threading
from contextlib import contextmanager
from typing import Dict
from typing import TYPE_CHECKING, Dict
from funcy import retry, wrap_with
@@ -19,6 +19,9 @@ from dvc.repo import Repo
from dvc.scm import CloneError, map_scm_exception
from dvc.utils import relpath
if TYPE_CHECKING:
from scmrepo import Git
logger = logging.getLogger(__name__)
@@ -201,14 +204,12 @@ def _clone_default_branch(url, rev, for_write=False):
# given repo URL it is easier/safer for us to work with
# full clones in this case.
logger.debug("erepo: unshallowing clone for '%s'", url)
git.fetch(unshallow=True)
_merge_upstream(git)
_pull(git, unshallow=True)
shallow = False
CLONES[url] = (clone_path, shallow)
else:
logger.debug("erepo: git pull '%s'", url)
git.fetch()
_merge_upstream(git)
_pull(git)
else:
from dvc.scm import clone
@@ -227,7 +228,9 @@ def _clone_default_branch(url, rev, for_write=False):
"erepo: using shallow clone for branch '%s'", rev
)
except CloneError:
pass
git_dir = os.path.join(clone_path, ".git")
if os.path.exists(git_dir):
_remove(git_dir)
if not git:
git = clone(url, clone_path)
shallow = False
@@ -239,7 +242,15 @@ def _clone_default_branch(url, rev, for_write=False):
return clone_path, shallow
def _merge_upstream(git):
def _pull(git: "Git", unshallow: bool = False):
from dvc.repo.experiments.utils import fetch_all_exps
git.fetch(unshallow=unshallow)
_merge_upstream(git)
fetch_all_exps(git, "origin")
def _merge_upstream(git: "Git"):
from scmrepo.exceptions import SCMError
try:
+13
View File
@@ -191,3 +191,16 @@ def check_ref_format(scm: "Git", ref: ExpRefInfo):
f"Invalid exp name {ref.name}, the exp name must follow rules in "
"https://git-scm.com/docs/git-check-ref-format"
)
def fetch_all_exps(scm: "Git", url: str, progress: Optional[Callable] = None):
refspecs = [
f"{ref}:{ref}"
for ref in iter_remote_refs(scm, url, base=EXPS_NAMESPACE)
if not (ref.startswith(EXEC_NAMESPACE) or ref == EXPS_STASH)
]
scm.fetch_refspecs(
url,
refspecs,
progress=progress,
)
+6 -1
View File
@@ -101,9 +101,14 @@ class TqdmGit(Tqdm):
def clone(url: str, to_path: str, **kwargs):
from scmrepo.exceptions import CloneError as InternalCloneError
from dvc.repo.experiments.utils import fetch_all_exps
with TqdmGit(desc="Cloning") as pbar:
try:
return Git.clone(url, to_path, progress=pbar.update_git, **kwargs)
git = Git.clone(url, to_path, progress=pbar.update_git, **kwargs)
if "shallow_branch" not in kwargs:
fetch_all_exps(git, "origin", progress=pbar.update_git)
return git
except InternalCloneError as exc:
raise CloneError(str(exc))
+17
View File
@@ -374,3 +374,20 @@ def test_auth_error_push(tmp_dir, scm, dvc, exp_stage, http_auth_patch):
match=f"HTTP Git authentication is not supported: '{http_auth_patch}'",
):
dvc.experiments.push(http_auth_patch, [ref_info.name])
@pytest.mark.parametrize("use_ref", [True, False])
def test_get(tmp_dir, scm, dvc, exp_stage, erepo_dir, use_ref):
from dvc.repo import Repo
results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
exp_rev = first(results)
exp_ref = first(exp_refs_by_rev(scm, exp_rev))
with erepo_dir.chdir():
Repo.get(
str(tmp_dir),
"params.yaml",
rev=exp_ref.name if use_ref else exp_rev,
)
assert (erepo_dir / "params.yaml").read_text().strip() == "foo: 2"