diff --git a/dvc/dependency/repo.py b/dvc/dependency/repo.py index 20439c024e..68cd044a1d 100644 --- a/dvc/dependency/repo.py +++ b/dvc/dependency/repo.py @@ -49,10 +49,10 @@ def _make_repo(self, **overrides): def status(self): with self._make_repo() as repo: - current = repo.find_out_by_relpath(self.def_path).info + current = repo.find_out_by_path(self.def_path).info with self._make_repo(rev_lock=None) as repo: - updated = repo.find_out_by_relpath(self.def_path).info + updated = repo.find_out_by_path(self.def_path).info if current != updated: return {str(self): "update available"} @@ -71,7 +71,7 @@ def fetch(self): ) as repo: self.def_repo[self.PARAM_REV_LOCK] = repo.scm.get_rev() - out = repo.find_out_by_relpath(self.def_path) + out = repo.find_out_by_path(self.def_path) with repo.state: repo.cloud.pull(out.get_used_cache()) diff --git a/dvc/exceptions.py b/dvc/exceptions.py index 3c85f3dae0..369b33ac7f 100644 --- a/dvc/exceptions.py +++ b/dvc/exceptions.py @@ -59,10 +59,12 @@ class OutputNotFoundError(DvcException): output (unicode): path to the file/directory. """ - def __init__(self, output): + def __init__(self, output, repo=None): + self.repo = repo + self.failed_output = output super(OutputNotFoundError, self).__init__( "unable to find DVC-file with output '{path}'".format( - path=relpath(output) + path=relpath(self.failed_output) ) ) diff --git a/dvc/external_repo.py b/dvc/external_repo.py index 46657fc4d7..d528af6a55 100644 --- a/dvc/external_repo.py +++ b/dvc/external_repo.py @@ -9,6 +9,8 @@ from dvc.config import NoRemoteError from dvc.exceptions import RemoteNotSpecifiedInExternalRepoError +from dvc.exceptions import NoOutputInExternalRepoError +from dvc.exceptions import OutputNotFoundError from dvc.utils.fs import remove @@ -25,6 +27,10 @@ def external_repo(url=None, rev=None, rev_lock=None, cache_dir=None): yield repo except NoRemoteError as exc: raise RemoteNotSpecifiedInExternalRepoError(url, cause=exc) + except OutputNotFoundError as exc: + if exc.repo is repo: + raise NoOutputInExternalRepoError(url, exc.failed_output) + raise repo.close() diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index e0003b8087..86d6a343c7 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -418,10 +418,13 @@ def stages(self): return get_stages(self.graph) def find_outs_by_path(self, path, outs=None, recursive=False): + abs_path = ( + path if os.path.isabs(path) else os.path.join(self.root_dir, path) + ) + if not outs: outs = [out for stage in self.stages for out in stage.outs] - abs_path = os.path.abspath(path) is_dir = self.tree.isdir(abs_path) def func(out): @@ -435,12 +438,15 @@ def func(out): matched = list(filter(func, outs)) if not matched: - raise OutputNotFoundError(path) + if abs_path.startswith(self.root_dir): + failed_output = relpath(abs_path) + else: + failed_output = path + raise OutputNotFoundError(failed_output, self) return matched - def find_out_by_relpath(self, relpath): - path = os.path.join(self.root_dir, relpath) + def find_out_by_path(self, path): out, = self.find_outs_by_path(path) return out diff --git a/dvc/repo/fetch.py b/dvc/repo/fetch.py index 531fd4d535..0440dddaea 100644 --- a/dvc/repo/fetch.py +++ b/dvc/repo/fetch.py @@ -81,7 +81,7 @@ def _fetch_external(self, repo_url, repo_rev, files): cache = NamedCache() for name in files: try: - out = repo.find_out_by_relpath(name) + out = repo.find_out_by_path(name) except OutputNotFoundError: failed += 1 logger.exception( diff --git a/dvc/repo/get.py b/dvc/repo/get.py index 21d01ed7e7..64ca5eaf07 100644 --- a/dvc/repo/get.py +++ b/dvc/repo/get.py @@ -49,7 +49,7 @@ def get(url, path, out=None, rev=None): # the same cache file might be used a few times in a directory. repo.cache.local.cache_types = ["reflink", "hardlink", "copy"] - o = repo.find_out_by_relpath(path) + o = repo.find_out_by_path(path) with repo.state: repo.cloud.pull(o.get_used_cache()) o.path_info = PathInfo(os.path.abspath(out)) diff --git a/dvc/repo/imp.py b/dvc/repo/imp.py index 869039266a..68ead389b6 100644 --- a/dvc/repo/imp.py +++ b/dvc/repo/imp.py @@ -1,13 +1,6 @@ -from dvc.exceptions import NoOutputInExternalRepoError -from dvc.exceptions import OutputNotFoundError - - def imp(self, url, path, out=None, rev=None): erepo = {"url": url} if rev is not None: erepo["rev"] = rev - try: - return self.imp_url(path, out=out, erepo=erepo, locked=True) - except OutputNotFoundError: - raise NoOutputInExternalRepoError(url, path) + return self.imp_url(path, out=out, erepo=erepo, locked=True)