Skip to content

Commit 1cc803d

Browse files
committed
exp: output troubleshooting link on shallow merge failure
1 parent 2b6aa01 commit 1cc803d

File tree

4 files changed

+42
-8
lines changed

4 files changed

+42
-8
lines changed

dvc/repo/experiments/apply.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def apply(repo, rev, force=True, **kwargs):
2222
from scmrepo.exceptions import MergeConflictError
2323

2424
from dvc.repo.checkout import checkout as dvc_checkout
25-
from dvc.scm import RevError, SCMError, resolve_rev
25+
from dvc.scm import GitMergeError, RevError, resolve_rev
2626

2727
exps = repo.experiments
2828

@@ -51,7 +51,7 @@ def apply(repo, rev, force=True, **kwargs):
5151
try:
5252
repo.scm.merge(exp_rev, commit=False, squash=True)
5353
except _SCMError as exc:
54-
raise SCMError(str(exc))
54+
raise GitMergeError(str(exc), scm=repo.scm)
5555

5656
if workspace:
5757
try:

dvc/repo/experiments/executor/local.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
from typing import TYPE_CHECKING, Optional
66

77
from funcy import cached_property
8+
from scmrepo.exceptions import SCMError as _SCMError
89

9-
from dvc.scm import SCM
10+
from dvc.scm import SCM, GitMergeError
1011
from dvc.utils.fs import remove
1112

1213
from ..base import (
@@ -88,7 +89,10 @@ def init_git(self, scm: "Git", branch: Optional[str] = None):
8889
head = EXEC_BRANCH if branch else EXEC_HEAD
8990
self.scm.checkout(head, detach=True)
9091
merge_rev = self.scm.get_ref(EXEC_MERGE)
91-
self.scm.merge(merge_rev, squash=True, commit=False)
92+
try:
93+
self.scm.merge(merge_rev, squash=True, commit=False)
94+
except _SCMError as exc:
95+
raise GitMergeError(str(exc), scm=self.scm)
9296

9397
def _config(self, cache_dir):
9498
local_config = os.path.join(
@@ -155,7 +159,10 @@ def init_git(self, scm: "Git", branch: Optional[str] = None):
155159
)
156160
)
157161
merge_rev = self.scm.get_ref(EXEC_MERGE)
158-
self.scm.merge(merge_rev, squash=True, commit=False)
162+
try:
163+
self.scm.merge(merge_rev, squash=True, commit=False)
164+
except _SCMError as exc:
165+
raise GitMergeError(str(exc), scm=self.scm)
159166
if branch:
160167
self.scm.set_ref(EXEC_BRANCH, branch, symbolic=True)
161168
elif scm.get_ref(EXEC_BRANCH):

dvc/scm.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Manages source control systems (e.g. Git)."""
2+
import os
23
from contextlib import contextmanager
34
from functools import partial
45
from typing import TYPE_CHECKING, Iterator, List, Mapping, Optional
@@ -10,6 +11,7 @@
1011

1112
from dvc.exceptions import DvcException
1213
from dvc.progress import Tqdm
14+
from dvc.utils import format_link
1315

1416
if TYPE_CHECKING:
1517
from scmrepo.progress import GitProgressEvent
@@ -47,6 +49,25 @@ def __init__(self, reason: str) -> None:
4749
super().__init__(f"{reason}\n{doc}")
4850

4951

52+
class GitMergeError(SCMError):
53+
def __init__(self, msg: str, scm: Optional["Git"] = None) -> None:
54+
if scm and self._is_shallow(scm):
55+
url = format_link(
56+
"https://dvc.org/doc/user-guide/troubleshooting#git-shallow"
57+
)
58+
msg = (
59+
f"{msg}: `dvc exp` does not work in shallow Git repos. "
60+
f"See {url} for more information."
61+
)
62+
super().__init__(msg)
63+
64+
@staticmethod
65+
def _is_shallow(scm: "Git") -> bool:
66+
if os.path.exists(os.path.join(scm.root_dir, Git.GIT_DIR, "shallow")):
67+
return True
68+
return False
69+
70+
5071
@contextmanager
5172
def map_scm_exception(with_cause: bool = False) -> Iterator[None]:
5273
from scmrepo.exceptions import SCMError as InternalSCMError
@@ -115,8 +136,6 @@ def update_git(self, event: "GitProgressEvent") -> None:
115136

116137

117138
def clone(url: str, to_path: str, **kwargs):
118-
import os
119-
120139
from scmrepo.exceptions import CloneError as InternalCloneError
121140

122141
from dvc.repo.experiments.utils import fetch_all_exps

tests/unit/scm/test_scm.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dvc.repo.experiments import ExpRefInfo
2-
from dvc.scm import iter_revs
2+
from dvc.scm import GitMergeError, iter_revs
33

44

55
def test_iter_revs(
@@ -61,3 +61,11 @@ def test_iter_revs(
6161
rev_old: [rev_old],
6262
rev_root: [rev_root],
6363
}
64+
65+
66+
def test_merge_error(tmp_dir, scm):
67+
exc = GitMergeError("Merge failed")
68+
assert "shallow" not in str(exc)
69+
tmp_dir.gen({".git": {"shallow": ""}})
70+
exc = GitMergeError("Merge failed", scm=scm)
71+
assert "shallow" in str(exc)

0 commit comments

Comments
 (0)