Repository: iterative/dvc
Pull request: metrics diff error message in --no-scm projects
* [x] ❗ I have followed the [Contributing to DVC](https://dvc.org/doc/user-guide/contributing/core) checklist.

* [x] 📖 If this PR requires [documentation](https://dvc.org/doc) updates, I have created a separate PR (or issue, at least) in [dvc.org](https://github.com/iterative/dvc.org) and linked it here. If the CLI API is changed, I have updated [tab completion scripts](https://github.com/iterative/dvc/tree/master/scripts/completion).

* [x] ❌ I will check DeepSource, CodeClimate, and other sanity checks below. (We consider them recommendatory and don't expect everything to be addressed. Please fix things that actually improve code or fix bugs.)

Thank you for the contribution - we'll try to review it as soon as possible. 🙏


I am not sure if there is any other scm tools besides git going to be supported. 
If so, the error message"only supported for Git repositories" is not proper one,
 

fix #3605

Problem statement:
metrics diff: cryptic error in --no-scm projects [qa]
```console
λ dvc version
DVC version: 0.92.0
Python version: 3.7.5
Platform: Windows-10-10.0.18362-SP0
Binary: True
Package: exe

λ dvc metrics diff
ERROR: unexpected error - 'NoSCM' object has no attribute 'resolve_rev'
```

Run in a --no-scm DVC project. Compare to `dvc diff`:

```console
λ dvc diff
ERROR: failed to get diff - only supported for Git repositories
```

Hints from issue discussion:

Commit message: Updated error msg

Patch to review:
diff --git a/dvc/repo/brancher.py b/dvc/repo/brancher.py
index 67a3b19b36..702ed9dc97 100644
--- a/dvc/repo/brancher.py
+++ b/dvc/repo/brancher.py
@@ -1,6 +1,7 @@
 from funcy import group_by
 
 from dvc.scm.tree import WorkingTree
+from dvc.scm.base import NOSCMError
 
 
 def brancher(  # noqa: E302
@@ -46,5 +47,7 @@ def brancher(  # noqa: E302
             for sha, names in group_by(scm.resolve_rev, revs).items():
                 self.tree = scm.get_tree(sha)
                 yield ", ".join(names)
+    except AttributeError:
+        raise NOSCMError()
     finally:
         self.tree = saved_tree
diff --git a/dvc/repo/diff.py b/dvc/repo/diff.py
index d18389e05c..d6e59ffb4e 100644
--- a/dvc/repo/diff.py
+++ b/dvc/repo/diff.py
@@ -1,9 +1,9 @@
 import os
 
-from dvc.exceptions import DvcException
 from dvc.repo import locked
 from dvc.scm.git import Git
 from dvc.scm.tree import is_working_tree
+from dvc.scm.base import NOSCMError
 
 
 @locked
@@ -16,7 +16,7 @@ def diff(self, a_rev="HEAD", b_rev=None):
     `dvc diff` would be the same as `dvc diff HEAD`.
     """
     if type(self.scm) is not Git:
-        raise DvcException("only supported for Git repositories")
+        raise NOSCMError
 
     def _paths_checksums():
         """
diff --git a/dvc/scm/base.py b/dvc/scm/base.py
index 017263de12..8d74222cd5 100644
--- a/dvc/scm/base.py
+++ b/dvc/scm/base.py
@@ -24,6 +24,16 @@ class RevError(SCMError):
     pass
 
 
+class NOSCMError(SCMError):
+    def __init__(self):
+        msg = (
+            "only supported for Git repositories. If you had\n already "
+            "initialized a git repo, this may be caused by dvc configuration. "
+            "Use\n `dvc config core.no_scm False` to update it."
+        )
+        super().__init__(msg)
+
+
 class Base(object):
     """Base class for source control management driver implementations."""
 
diff --git a/tests/func/test_metrics.py b/tests/func/test_metrics.py
index fab19c86d6..872c2250e7 100644
--- a/tests/func/test_metrics.py
+++ b/tests/func/test_metrics.py
@@ -1005,3 +1005,13 @@ def test_metrics_diff_deleted_metric(tmp_dir, scm, dvc):
             "a.b.e": {"old": "3", "new": None},
         }
     }
+
+
+def test_metrics_without_scm(tmp_dir, dvc):
+    metrics = {"acc": 0.97, "recall": 0.95}
+    metrics_name = "metrics.json"
+    tmp_dir.gen({metrics_name: json.dumps(metrics)})
+    dvc.add(metrics_name)
+    dvc.metrics.add(metrics_name)
+    with pytest.raises(DvcException, match=r"only supported for Git repos"):
+        dvc.metrics.diff()


Code review comments:
diff_hunk: @@ -24,6 +24,16 @@ class RevError(SCMError):
     pass
 
 
+class NOSCMError(SCMError):
+    def __init__(self):
+        msg = (
+            "only supported for Git repositories. If you had\n already "
+            "initialized a git repo, this may be caused by dvc configuration. "
+            "Use\n `dvc config core.no_scm False` to update it."
path: dvc/scm/base.py
text: @user1:
Shouldn't this begin with capital O? Depends if it's printed by itself (in that case yes) or if it's a continuation of a previously printed message (in that case no). Other capitalizations:
```suggestion
            "only supported for Git repositories. If you had\n already "
            "initialized a Git repo, this may be caused by DVC configuration. "
            "Use\n `dvc config core.no_scm False` to update it."
```

@user1:
> If you had already initialized a Git repo, this may be caused by DVC configuration...

I'm not sure I understand this explanation though. I think we mean something like ``If you're seeing this error in a Git repo, try updating the DVC configuration with `dvc config core.no_scm False`.`` ?

@author:
I think so, my pool english representation.

> > If you had already initialized a Git repo, this may be caused by DVC configuration...
> 
> I'm not sure I understand this explanation though. I think we mean something like `` If you're seeing this error in a Git repo, try updating the DVC configuration with `dvc config core.no_scm False`. `` ?



@user1:
Ah sorry I didn't realize you were an outside contributor! Don't worry about it we can polish it 🙂 this is a great change. Thanks a lot!

@author:
Thank you too.