Repository: iterative/dvc

Issue:
`dvc` commands fail on non-DVC repository with an exception
```
$ cd "$(mktemp -d)" && dvc
ERROR: the following arguments are required: COMMAND
usage: dvc [-q | -v] [-h] [-V] COMMAND ...

Data Version Control

optional arguments:
  -q, --quiet    Be quiet.
  -v, --verbose  Be verbose.
  -h, --help     Show this help message and exit.
  -V, --version  Show program's version.

Available Commands:
  COMMAND        Use `dvc COMMAND --help` for command-specific help.
    init         Initialize DVC in the current directory.
    get          Download file or directory tracked by DVC or by Git.
    get-url      Download or copy files from URL.
    destroy      Remove DVC-files, local DVC config and data cache.
    add          Track data files or directories with DVC.
    remove       Remove DVC-file outputs.
    move         Rename or move a DVC controlled data file or a directory.
    unprotect    Unprotect data files or directories.
    run          Generate a stage file from a command and execute the command.
    repro        Check for changes and reproduce stages and dependencies.
    pull         Pull data files from a DVC remote storage.
    push         Push data files to a DVC remote storage.
    fetch        Fetch data files from a DVC remote storage.
    status       Show changed stages, compare local cache and a remote storage.
    gc           Garbage collect unused objects from cache or remote storage.
    import       Download file or directory tracked by DVC or by Git into the workspace, and track it.
    import-url   Download or copy file from URL and take it under DVC control.
    config       Get or set config options.
    checkout     Checkout data files from cache.
    remote       Manage remote storage configuration.
    cache        Manage cache settings.
    metrics      Commands to add, manage, collect and display metrics.
    install      Install DVC git hooks into the repository.
    root         Relative path to the repository's directory.
    list         List files and DVC outputs in the repo.
    lock         Lock DVC-files.
    unlock       Unlock DVC-files.
    pipeline     Manage pipelines.
    commit       Save changed data to cache and update DVC-files.
    diff         Compare two versions of the DVC repository.
                 Shows the list of paths added, modified, or deleted
    version      Show DVC version and system/environment information.
    update       Update data artifacts imported from other DVC repositories.

Having any troubles? Hit us up at https://dvc.org/support, we are always happy to help!
Traceback (most recent call last):
  File "/home/saugat/repos/iterative/dvc/.env/py36/bin/dvc", line 12, in <module>
    sys.exit(main())
  File "/home/saugat/repos/iterative/dvc/dvc/main.py", line 89, in main
    if analytics.is_enabled():
  File "/home/saugat/repos/iterative/dvc/dvc/analytics.py", line 57, in is_enabled
    Config(validate=False).get("core", {}).get("analytics", "true")
  File "/home/saugat/repos/iterative/dvc/dvc/config.py", line 223, in __init__
    self.load(validate=validate)
  File "/home/saugat/repos/iterative/dvc/dvc/config.py", line 282, in load
    self["cache"]["dir"] = os.path.join(self.dvc_dir, "cache")
  File "/home/saugat/.pyenv/versions/3.6.6/lib/python3.6/posixpath.py", line 80, in join
    a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not NoneType
```


Comments:

Patch:
diff --git a/dvc/config.py b/dvc/config.py
--- a/dvc/config.py
+++ b/dvc/config.py
@@ -278,7 +278,7 @@ def load(self, validate=True):
         self.update(conf)
 
         # Add resolved default cache.dir
-        if not self["cache"].get("dir"):
+        if not self["cache"].get("dir") and self.dvc_dir:
             self["cache"]["dir"] = os.path.join(self.dvc_dir, "cache")
 
     def load_one(self, level):


Test patch:
diff --git a/tests/func/test_config.py b/tests/func/test_config.py
--- a/tests/func/test_config.py
+++ b/tests/func/test_config.py
@@ -2,7 +2,7 @@
 import configobj
 
 from dvc.main import main
-from dvc.config import ConfigError
+from dvc.config import Config, ConfigError
 from tests.basic_env import TestDvc
 
 
@@ -101,3 +101,8 @@ def test_merging_two_levels(dvc):
         "url": "ssh://example.com",
         "password": "1",
     }
+
+
+def test_config_loads_without_error_for_non_dvc_repo(tmp_dir):
+    # regression testing for https://github.com/iterative/dvc/issues/3328
+    Config(validate=True)