Repository: iterative/dvc

Issue:
api: does not work with git only local repository
```sh
➜ cd "$(mktemp -d)" 
➜ git init
Initialized empty Git repository in /tmp/tmp.TGV6SVXYsz/.git/

➜ echo "foo" > foo
➜ git add foo
➜ git -c commit.gpgsign=false commit -m "first"
[master (root-commit) 136fd94] first
 1 file changed, 1 insertion(+)
 create mode 100644 foo

➜ python -c '
➜ import dvc.api
➜ with dvc.api.open(path="foo", repo=".") as fd:
➜     print(fd.read())
➜ '
Traceback (most recent call last):
  File "<string>", line 3, in <module>
  File "/home/saugat/.pyenv/versions/3.6.6/lib/python3.6/contextlib.py", line 81, in __enter__
    return next(self.gen)
  File "/home/saugat/repos/iterative/dvc/dvc/api.py", line 95, in _open
    with _make_repo(repo, rev=rev) as _repo:
  File "/home/saugat/.pyenv/versions/3.6.6/lib/python3.6/contextlib.py", line 81, in __enter__
    return next(self.gen)
  File "/home/saugat/repos/iterative/dvc/dvc/api.py", line 113, in _make_repo
    yield Repo(repo_url)
  File "/home/saugat/repos/iterative/dvc/dvc/repo/__init__.py", line 76, in __init__
    root_dir = self.find_root(root_dir)
  File "/home/saugat/repos/iterative/dvc/dvc/repo/__init__.py", line 144, in find_root
    raise NotDvcRepoError(root)
dvc.exceptions.NotDvcRepoError: you are not inside of a dvc repository (checked up to mount point '/tmp')
```

This is because of the recent changes in `_make_repo` that instead of falling back to external repo on error, it assumes the local path to be a DVC repository.
https://github.com/iterative/dvc/blob/e9caa44b554daf7f0f21dc2bb9bb0df028369fb1/dvc/api.py#L112-L113


Discussion:

Resolving patch:
diff --git a/dvc/api.py b/dvc/api.py
--- a/dvc/api.py
+++ b/dvc/api.py
@@ -10,7 +10,7 @@
 from voluptuous import Schema, Required, Invalid
 
 from dvc.repo import Repo
-from dvc.exceptions import DvcException
+from dvc.exceptions import DvcException, NotDvcRepoError
 from dvc.external_repo import external_repo
 
 
@@ -108,12 +108,16 @@ def read(path, repo=None, rev=None, remote=None, mode="r", encoding=None):
 
 
 @contextmanager
-def _make_repo(repo_url, rev=None):
-    if rev is None and (not repo_url or os.path.exists(repo_url)):
-        yield Repo(repo_url)
-    else:
-        with external_repo(url=repo_url, rev=rev) as repo:
-            yield repo
+def _make_repo(repo_url=None, rev=None):
+    repo_url = repo_url or os.getcwd()
+    if rev is None and os.path.exists(repo_url):
+        try:
+            yield Repo(repo_url)
+            return
+        except NotDvcRepoError:
+            pass  # fallthrough to external_repo
+    with external_repo(url=repo_url, rev=rev) as repo:
+        yield repo
 
 
 def summon(name, repo=None, rev=None, summon_file="dvcsummon.yaml", args=None):
diff --git a/dvc/external_repo.py b/dvc/external_repo.py
--- a/dvc/external_repo.py
+++ b/dvc/external_repo.py
@@ -128,10 +128,10 @@ def pull_to(self, path, to_info):
             raise PathMissingError(path, self.url)
 
     @contextmanager
-    def open_by_relpath(self, path, mode="r", encoding=None):
+    def open_by_relpath(self, path, mode="r", encoding=None, **kwargs):
         try:
             abs_path = os.path.join(self.root_dir, path)
-            with open(abs_path, mode, encoding) as fd:
+            with open(abs_path, mode, encoding=encoding) as fd:
                 yield fd
         except FileNotFoundError:
             raise PathMissingError(path, self.url)


Test patch:
diff --git a/tests/func/test_api.py b/tests/func/test_api.py
--- a/tests/func/test_api.py
+++ b/tests/func/test_api.py
@@ -8,7 +8,7 @@
 from dvc import api
 from dvc.api import SummonError, UrlNotDvcRepoError
 from dvc.compat import fspath
-from dvc.exceptions import FileMissingError, NotDvcRepoError
+from dvc.exceptions import FileMissingError
 from dvc.main import main
 from dvc.path_info import URLInfo
 from dvc.remote.config import RemoteConfig
@@ -54,7 +54,7 @@ def test_get_url_external(erepo_dir, remote_url):
 def test_get_url_requires_dvc(tmp_dir, scm):
     tmp_dir.scm_gen({"foo": "foo"}, commit="initial")
 
-    with pytest.raises(NotDvcRepoError, match="not inside of a DVC repo"):
+    with pytest.raises(UrlNotDvcRepoError, match="not a DVC repository"):
         api.get_url("foo", repo=fspath(tmp_dir))
 
     with pytest.raises(UrlNotDvcRepoError):