diff --git a/dvc/external_repo.py b/dvc/external_repo.py index 88ec1e1ec..37f02cc40 100644 --- a/dvc/external_repo.py +++ b/dvc/external_repo.py @@ -198,6 +198,8 @@ def _clone_default_branch(url, rev, for_write=False): logger.debug("erepo: git pull '%s'", url) git.pull() else: + from dvc.scm import clone + logger.debug("erepo: git clone '%s' to a temporary dir", url) clone_path = tempfile.mkdtemp("dvc-clone") if not for_write and rev and not Git.is_sha(rev): @@ -205,7 +207,7 @@ def _clone_default_branch(url, rev, for_write=False): from dvc.scm.base import CloneError try: - git = Git.clone(url, clone_path, shallow_branch=rev) + git = clone(url, clone_path, shallow_branch=rev) shallow = True logger.debug( "erepo: using shallow clone for branch '%s'", rev @@ -213,7 +215,7 @@ def _clone_default_branch(url, rev, for_write=False): except CloneError: pass if not git: - git = Git.clone(url, clone_path) + git = clone(url, clone_path) shallow = False CLONES[url] = (clone_path, shallow) finally: diff --git a/dvc/scm/__init__.py b/dvc/scm/__init__.py index 9a0b0f4a0..3dccfb298 100644 --- a/dvc/scm/__init__.py +++ b/dvc/scm/__init__.py @@ -31,3 +31,13 @@ def SCM( return NoSCM(root_dir) return Git(root_dir, search_parent_directories=search_parent_directories) + + +def clone(url: str, to_path: str, **kwargs): + from .exceptions import CloneError as InternalCloneError + from .base import CloneError + + try: + return Git.clone(url, to_path, **kwargs) + except InternalCloneError as exc: + raise CloneError(str(exc)) diff --git a/dvc/scm/base.py b/dvc/scm/base.py index cfcc51d4e..cabb59871 100644 --- a/dvc/scm/base.py +++ b/dvc/scm/base.py @@ -10,8 +10,7 @@ class SCMError(DvcException): class CloneError(SCMError): - def __init__(self, url, path): - super().__init__(f"Failed to clone repo '{url}' to '{path}'") + pass class RevError(SCMError): diff --git a/dvc/scm/exceptions.py b/dvc/scm/exceptions.py index 2ff9e0f82..cb549e065 100644 --- a/dvc/scm/exceptions.py +++ b/dvc/scm/exceptions.py @@ -28,3 +28,10 @@ class AuthError(SCMError): def __init__(self, url: str) -> None: self.url = url super().__init__(f"HTTP Git authentication is not supported: '{url}'") + + +class CloneError(SCMError): + def __init__(self, url: str, path: str) -> None: + self.url = url + self.path = path + super().__init__(f"Failed to clone repo '{url}' to '{path}'") \ No newline at end of file diff --git a/dvc/scm/git/backend/gitpython.py b/dvc/scm/git/backend/gitpython.py index 61715a3a8..658896db8 100644 --- a/dvc/scm/git/backend/gitpython.py +++ b/dvc/scm/git/backend/gitpython.py @@ -17,8 +17,8 @@ from typing import ( from funcy import ignore from dvc.progress import Tqdm -from dvc.scm.base import CloneError, RevError, SCMError -from dvc.scm.exceptions import MergeConflictError +from dvc.scm.base import RevError, SCMError +from dvc.scm.exceptions import MergeConflictError, CloneError from dvc.utils import fix_env, is_binary, relpath from ..objects import GitCommit, GitObject