Repository: iterative/dvc

Issue:
import: does not work from bare git repo
Here's a repro:
```sh
#!/usr/bin/env bash
set -ex
temp=$(mktemp -d)
cd "$temp"
mkdir {repo1,repo2,upstream,dataregistry}

# create artifacts on repo1 and commit
cd repo1
git init && dvc init 
dvc run  -f output.dvc -o 1 "echo 1 >> 1"
dvc remote add -d local ../dataregistry 
dvc push 
git add -A
git -c commit.gpgsign=false commit -m "initial"

# setup upstream and push source code for collaboration
cd ../upstream
git init --bare
cd ../repo1
git remote add origin ../upstream
git push -u origin --all

# import from upstream
cd ../repo2
git init && dvc init
dvc import -v ../upstream 1 

# change artifacts on repo1
cd ../repo1
dvc run  -f output.dvc --overwrite-dvcfile -o 1 "echo 2 >> 1"
dvc push 
git add -A
git -c commit.gpgsign=false commit -m "second"
git push

# try to update modified artifacts
cd ../repo2
dvc update -v 1.dvc
cat 1
```
```sh
+ dvc import -v /tmp/tmp.aQ6WqOY6Rl/upstream 1
2020-03-06 10:32:08,699 DEBUG: Trying to spawn '['/home/saugat/repos/iterative/dvc/.env/py36/bin/python', '/home/saugat/repos/iterative/dvc/.env/py36/bin/dvc', 'daemon', '-q', 'updater']'
2020-03-06 10:32:08,701 DEBUG: Spawned '['/home/saugat/repos/iterative/dvc/.env/py36/bin/python', '/home/saugat/repos/iterative/dvc/.env/py36/bin/dvc', 'daemon', '-q', 'updater']'
2020-03-06 10:32:08,705 DEBUG: CREATE TABLE IF NOT EXISTS state (inode INTEGER PRIMARY KEY, mtime TEXT NOT NULL, size TEXT NOT NULL, md5 TEXT NOT NULL, timestamp TEXT NOT NULL)
2020-03-06 10:32:08,707 DEBUG: CREATE TABLE IF NOT EXISTS state_info (count INTEGER)
2020-03-06 10:32:08,709 DEBUG: CREATE TABLE IF NOT EXISTS link_state (path TEXT PRIMARY KEY, inode INTEGER NOT NULL, mtime TEXT NOT NULL)
2020-03-06 10:32:08,711 DEBUG: INSERT OR IGNORE INTO state_info (count) SELECT 0 WHERE NOT EXISTS (SELECT * FROM state_info)
2020-03-06 10:32:08,712 DEBUG: PRAGMA user_version = 3;
2020-03-06 10:32:09,015 DEBUG: Removing output '1' of '1.dvc'.
Importing '1 (/tmp/tmp.aQ6WqOY6Rl/upstream)' -> '1'
2020-03-06 10:32:09,017 DEBUG: Computed stage '1.dvc' md5: '9b8ffff91e5c3b7cd3be65868ae81f3b'
2020-03-06 10:32:09,017 DEBUG: Creating external repo /tmp/tmp.aQ6WqOY6Rl/upstream@None
2020-03-06 10:32:09,017 DEBUG: erepo: git clone /tmp/tmp.aQ6WqOY6Rl/upstream to a temporary dir
2020-03-06 10:32:09,046 DEBUG: erepo: making a copy of /tmp/tmp.aQ6WqOY6Rl/upstream clone
2020-03-06 10:32:09,115 DEBUG: SELECT count from state_info WHERE rowid=?
2020-03-06 10:32:09,115 DEBUG: fetched: [(0,)]
2020-03-06 10:32:09,115 DEBUG: UPDATE state_info SET count = ? WHERE rowid = ?
2020-03-06 10:32:09,116 ERROR: failed to import '1' from '/tmp/tmp.aQ6WqOY6Rl/upstream'. - The path '1' does not exist in the target repository '/tmp/tmp.aQ6WqOY6Rl/upstream' neither as an output nor a git-handled file.
------------------------------------------------------------
Traceback (most recent call last):
  File "/home/saugat/repos/iterative/dvc/dvc/external_repo.py", line 179, in pull_to
    fs_copy(os.path.join(self.root_dir, path), fspath(to_info))
  File "/home/saugat/repos/iterative/dvc/dvc/utils/fs.py", line 27, in fs_copy
    shutil.copy2(src, dst)
  File "/home/saugat/.pyenv/versions/3.6.6/lib/python3.6/shutil.py", line 257, in copy2
    copyfile(src, dst, follow_symlinks=follow_symlinks)
  File "/home/saugat/.pyenv/versions/3.6.6/lib/python3.6/shutil.py", line 120, in copyfile
    with open(src, 'rb') as fsrc:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpn3my58ffdvc-erepo/1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/saugat/repos/iterative/dvc/dvc/command/imp.py", line 19, in run
    rev=self.args.rev,
  File "/home/saugat/repos/iterative/dvc/dvc/repo/imp.py", line 6, in imp
    return self.imp_url(path, out=out, erepo=erepo, locked=True)
  File "/home/saugat/repos/iterative/dvc/dvc/repo/__init__.py", line 28, in wrapper
    ret = f(repo, *args, **kwargs)
  File "/home/saugat/repos/iterative/dvc/dvc/repo/scm_context.py", line 4, in run
    result = method(repo, *args, **kw)
  File "/home/saugat/repos/iterative/dvc/dvc/repo/imp_url.py", line 28, in imp_url
    stage.run()
  File "/home/saugat/repos/iterative/dvc/.env/py36/lib/python3.6/site-packages/funcy/decorators.py", line 39, in wrapper
    return deco(call, *dargs, **dkwargs)
  File "/home/saugat/repos/iterative/dvc/dvc/stage.py", line 161, in rwlocked
    return call()
  File "/home/saugat/repos/iterative/dvc/.env/py36/lib/python3.6/site-packages/funcy/decorators.py", line 60, in __call__
    return self._func(*self._args, **self._kwargs)
  File "/home/saugat/repos/iterative/dvc/dvc/stage.py", line 941, in run
    self.deps[0].download(self.outs[0])
  File "/home/saugat/repos/iterative/dvc/dvc/dependency/repo.py", line 81, in download
    repo.pull_to(self.def_path, to.path_info)
  File "/home/saugat/repos/iterative/dvc/dvc/external_repo.py", line 181, in pull_to
    raise PathMissingError(path, self.url)
dvc.exceptions.PathMissingError: The path '1' does not exist in the target repository '/tmp/tmp.aQ6WqOY6Rl/upstream' neither as an output nor a git-handled file.
------------------------------------------------------------

Having any troubles? Hit us up at https://dvc.org/support, we are always happy to help!
```

I also tried with a `file:///` based urls and still it didn't work.

#### Discord (there's too much noise, so just picking the conversations on this issue): 

https://discordapp.com/channels/485586884165107732/485596304961962003/684611313162518555
https://discordapp.com/channels/485586884165107732/485596304961962003/684778738553979002
https://discordapp.com/channels/485586884165107732/485596304961962003/685120959912607748
https://discordapp.com/channels/485586884165107732/485596304961962003/685266189609467914



Discussion:

Patch:
diff --git a/README.rst b/README.rst
index de442da1d..bf975c648 100644
--- a/README.rst
+++ b/README.rst
@@ -307,6 +307,6 @@ Iterative, *DVC: Data Version Control - Git for Data & Models* (2020)
    :target: https://doi.org/10.5281/zenodo.3677553
    :alt: DOI
 
-.. |Flowchart| image:: https://dvc.org/static/img/flow.gif
+.. |Flowchart| image:: https://dvc.org/img/flow.gif
    :target: https://dvc.org/img/flow.gif
    :alt: how_dvc_works
diff --git a/dvc/external_repo.py b/dvc/external_repo.py
index 068335ae3..ec48a43f8 100644
--- a/dvc/external_repo.py
+++ b/dvc/external_repo.py
@@ -127,9 +127,17 @@ class ExternalRepo(Repo):
         if not os.path.isdir(self.url):
             return
 
-        remote_name = self.config["core"].get("remote")
-        src_repo = Repo(self.url)
         try:
+            src_repo = Repo(self.url)
+        except NotDvcRepoError:
+            # If ExternalRepo does not throw NotDvcRepoError and Repo does,
+            # the self.url might be a bare git repo.
+            # NOTE: This will fail to resolve remote with relative path,
+            # same as if it was a remote DVC repo.
+            return
+
+        try:
+            remote_name = self.config["core"].get("remote")
             if remote_name:
                 self._fix_local_remote(src_repo, remote_name)
             else:


Test patch:
diff --git a/tests/func/test_import.py b/tests/func/test_import.py
index c4fa1dc17..65ca99b56 100644
--- a/tests/func/test_import.py
+++ b/tests/func/test_import.py
@@ -305,3 +305,20 @@ def test_pull_no_rev_lock(erepo_dir, tmp_dir, dvc):
 
     assert (tmp_dir / "foo_imported").is_file()
     assert (tmp_dir / "foo_imported").read_text() == "contents"
+
+
+def test_import_from_bare_git_repo(tmp_dir, make_tmp_dir, erepo_dir):
+    import git
+
+    git.Repo.init(fspath(tmp_dir), bare=True)
+
+    with erepo_dir.chdir():
+        erepo_dir.dvc_gen({"foo": "foo"}, commit="initial")
+        erepo_dir.dvc.push()
+
+        erepo_dir.scm.repo.create_remote("origin", fspath(tmp_dir))
+        erepo_dir.scm.repo.remote("origin").push("master")
+
+    dvc_repo = make_tmp_dir("dvc-repo", scm=True, dvc=True)
+    with dvc_repo.chdir():
+        dvc_repo.dvc.imp(fspath(tmp_dir), "foo")