Repository: iterative/dvc

Issue:
import: same command creates .dvc file in different locations
## DVC Version

```console
~/example-get-started$ dvc version
DVC version: 1.0.1
Python version: 3.7.1
Platform: Linux-4.15.0-88-generic-x86_64-with-debian-buster-sid
Binary: True
Package: deb
Supported remotes: azure, gdrive, gs, hdfs, http, https, s3, ssh, oss
Cache: reflink - not supported, hardlink - supported, symlink - supported
Filesystem type (cache directory): ('ext4', '/dev/mapper/host01--vg-root')
Repo: dvc, git
Filesystem type (workspace): ('ext4', '/dev/mapper/host01--vg-root')
```

## Reproduce

Run the same command:

`dvc import https://github.com/iterative/dataset-registry get-started/data.xml -o data/data.xml`

when `data` directory exists and when it does not.

In the first case we get:

```console
Importing 'get-started/data.xml (https://github.com/iterative/dataset-registry)' -> 'data/data.xml'

To track the changes with git, run:

        git add data/data.xml.dvc
```

In the second case:

```console
Importing 'get-started/data.xml (https://github.com/iterative/dataset-registry)' -> 'data/data.xml'

To track the changes with git, run:

        git add data.xml.dvc data/.gitignore
```

**There are two bugs:**

- [ ] It creates `data.xml.dvc` in different locations (`data/data.xml.dvc` vs `data.xml.dvc`)
- [x] It doesn't mention `.gitignore` in the first case in the `git add` hint.




Discussion:
> It creates data.xml.dvc in different locations (data/data.xml.dvc vs data.xml.dvc)

Good catch!

>  It doesn't mention .gitignore in the first case in the git add hint.

Works for me, I suppose you just had gitignore entry before that (probably from the previous run).


> Works for me, I suppose you just had gitignore entry before that (probably from the previous run).

yep, confirmed.

Resolving patch:
diff --git a/dvc/utils/__init__.py b/dvc/utils/__init__.py
--- a/dvc/utils/__init__.py
+++ b/dvc/utils/__init__.py
@@ -363,19 +363,22 @@ def resolve_output(inp, out):
 
 
 def resolve_paths(repo, out):
+    from urllib.parse import urlparse
     from ..dvcfile import DVC_FILE_SUFFIX
     from ..path_info import PathInfo
     from .fs import contains_symlink_up_to
 
-    abspath = os.path.abspath(out)
+    abspath = PathInfo(os.path.abspath(out))
     dirname = os.path.dirname(abspath)
     base = os.path.basename(os.path.normpath(out))
 
-    # NOTE: `out` might not exist yet, so using `dirname`(aka `wdir`) to check
-    # if it is a local path.
+    scheme = urlparse(out).scheme
+    if os.name == "nt" and scheme == abspath.drive[0].lower():
+        # urlparse interprets windows drive letters as URL scheme
+        scheme = ""
     if (
-        os.path.exists(dirname)  # out might not exist yet, so
-        and PathInfo(abspath).isin_or_eq(repo.root_dir)
+        not scheme
+        and abspath.isin_or_eq(repo.root_dir)
         and not contains_symlink_up_to(abspath, repo.root_dir)
     ):
         wdir = dirname


Test patch:
diff --git a/tests/func/test_import.py b/tests/func/test_import.py
--- a/tests/func/test_import.py
+++ b/tests/func/test_import.py
@@ -9,6 +9,7 @@
 from dvc.config import NoRemoteError
 from dvc.dvcfile import Dvcfile
 from dvc.exceptions import DownloadError, PathMissingError
+from dvc.stage.exceptions import StagePathNotFoundError
 from dvc.system import System
 from dvc.utils.fs import makedirs, remove
 
@@ -132,6 +133,28 @@ def test_import_file_from_dir(tmp_dir, scm, dvc, erepo_dir):
     assert (tmp_dir / "X.dvc").exists()
 
 
+def test_import_file_from_dir_to_dir(tmp_dir, scm, dvc, erepo_dir):
+    with erepo_dir.chdir():
+        erepo_dir.dvc_gen({"dir": {"foo": "foo"}}, commit="create dir")
+
+    with pytest.raises(StagePathNotFoundError):
+        dvc.imp(
+            os.fspath(erepo_dir),
+            os.path.join("dir", "foo"),
+            out=os.path.join("dir", "foo"),
+        )
+
+    tmp_dir.gen({"dir": {}})
+    dvc.imp(
+        os.fspath(erepo_dir),
+        os.path.join("dir", "foo"),
+        out=os.path.join("dir", "foo"),
+    )
+    assert not (tmp_dir / "foo.dvc").exists()
+    assert (tmp_dir / "dir" / "foo").read_text() == "foo"
+    assert (tmp_dir / "dir" / "foo.dvc").exists()
+
+
 def test_import_non_cached(erepo_dir, tmp_dir, dvc, scm):
     src = "non_cached_output"
     dst = src + "_imported"