diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index 52f7478bd9..c6a3e0bec9 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -4,6 +4,7 @@ from functools import wraps from funcy import cached_property, cat, first +from git import InvalidGitRepositoryError from dvc.config import Config from dvc.dvcfile import PIPELINE_FILE, Dvcfile, is_valid_filename @@ -15,6 +16,8 @@ OutputNotFoundError, ) from dvc.path_info import PathInfo +from dvc.scm import Base +from dvc.scm.base import SCMError from dvc.tree.repo import RepoTree from dvc.utils.fs import path_isin @@ -80,6 +83,37 @@ class Repo: from dvc.repo.status import status from dvc.repo.update import update + def _get_repo_dirs( + self, + root_dir: str = None, + scm: Base = None, + rev: str = None, + uninitialized: bool = False, + ): + assert bool(scm) == bool(rev) + + from dvc.scm import SCM + from dvc.utils.fs import makedirs + + try: + tree = scm.get_tree(rev) if rev else None + root_dir = self.find_root(root_dir, tree) + dvc_dir = os.path.join(root_dir, self.DVC_DIR) + tmp_dir = os.path.join(dvc_dir, "tmp") + makedirs(tmp_dir, exist_ok=True) + + except NotDvcRepoError: + if not uninitialized: + raise + try: + root_dir = SCM(root_dir or os.curdir).root_dir + except (SCMError, InvalidGitRepositoryError): + root_dir = SCM(os.curdir, no_scm=True).root_dir + + dvc_dir = None + tmp_dir = None + return root_dir, dvc_dir, tmp_dir + def __init__( self, root_dir=None, @@ -95,24 +129,13 @@ def __init__( from dvc.repo.metrics import Metrics from dvc.repo.params import Params from dvc.repo.plots import Plots - from dvc.scm import SCM from dvc.stage.cache import StageCache from dvc.state import State, StateNoop from dvc.tree.local import LocalTree - from dvc.utils.fs import makedirs - try: - tree = scm.get_tree(rev) if rev else None - self.root_dir = self.find_root(root_dir, tree) - self.dvc_dir = os.path.join(self.root_dir, self.DVC_DIR) - self.tmp_dir = os.path.join(self.dvc_dir, "tmp") - makedirs(self.tmp_dir, exist_ok=True) - except NotDvcRepoError: - if not uninitialized: - raise - self.root_dir = SCM(root_dir or os.curdir).root_dir - self.dvc_dir = None - self.tmp_dir = None + self.root_dir, self.dvc_dir, self.tmp_dir = self._get_repo_dirs( + root_dir=root_dir, scm=scm, rev=rev, uninitialized=uninitialized + ) tree_kwargs = {"use_dvcignore": True, "dvcignore_root": self.root_dir} if scm: diff --git a/dvc/repo/metrics/show.py b/dvc/repo/metrics/show.py index 9d3d2c9562..aff2a5d1f9 100644 --- a/dvc/repo/metrics/show.py +++ b/dvc/repo/metrics/show.py @@ -3,6 +3,7 @@ from dvc.exceptions import NoMetricsError from dvc.repo import locked from dvc.repo.collect import collect +from dvc.scm.base import SCMError from dvc.tree.repo import RepoTree from dvc.utils.serialize import YAMLFileCorruptedError, load_yaml @@ -113,8 +114,10 @@ def show( # Hide workspace metrics if they are the same as in the active branch try: active_branch = repo.scm.active_branch() - except TypeError: - pass # Detached head + except (TypeError, SCMError): + # TypeError - detached head + # SCMError - no repo case + pass else: if res.get("workspace") == res.get(active_branch): res.pop("workspace", None) diff --git a/tests/func/metrics/test_show.py b/tests/func/metrics/test_show.py index 818be806de..f346b35caf 100644 --- a/tests/func/metrics/test_show.py +++ b/tests/func/metrics/test_show.py @@ -173,3 +173,11 @@ def test_show_falsey(tmp_dir, dvc): assert dvc.metrics.show(targets=["metrics.json"]) == { "": {"metrics.json": {"foo": 0, "bar": 0.0}} } + + +def test_show_no_repo(tmp_dir): + tmp_dir.gen("metrics.json", '{"foo": 0, "bar": 0.0, "baz": {}}') + + dvc = Repo(uninitialized=True) + + dvc.metrics.show(targets=["metrics.json"]) diff --git a/tests/func/plots/test_plots.py b/tests/func/plots/test_plots.py index 0d5f22f567..6ea8d68b3f 100644 --- a/tests/func/plots/test_plots.py +++ b/tests/func/plots/test_plots.py @@ -663,3 +663,15 @@ def test_show_non_plot_and_plot_with_params( plot_content.pop("title") plot2_content.pop("title") assert plot_content == plot2_content + + +def test_show_no_repo(tmp_dir): + metric = [ + {"first_val": 100, "val": 2}, + {"first_val": 200, "val": 3}, + ] + _write_json(tmp_dir, metric, "metric.json") + + dvc = Repo(uninitialized=True) + + dvc.plots.show(["metric.json"])