Repository: iterative/dvc

Issue:
Bug: dvc remote remove leads to Initialization error / config file error.
**Setup**

- dvc version 0.18.9, installed with pip, python Anaconda 3.6.4, Ubuntu 16.04

**Repro**

```bash
set -e
set -x
rm -rf foo
mkdir -p foo && cd foo
git init && dvc init
echo bar > bar.txt
dvc remote add -d dummy s3://dummy
dvc remote remove dummy
dvc add bar.txt
```

```bash
+ rm -rf foo
+ mkdir -p foo
+ cd foo
+ git init
Initialized empty Git repository in /home/tmain/foo/.git/
+ dvc init
Adding '.dvc/state' to '.dvc/.gitignore'.
Adding '.dvc/state.lock' to '.dvc/.gitignore'.
Adding '.dvc/link.state' to '.dvc/.gitignore'.
Adding '.dvc/link.state.lock' to '.dvc/.gitignore'.
Adding '.dvc/lock' to '.dvc/.gitignore'.
Adding '.dvc/config.local' to '.dvc/.gitignore'.
Adding '.dvc/updater' to '.dvc/.gitignore'.
Adding '.dvc/cache' to '.dvc/.gitignore'.
Checking for updates...
+ echo bar
+ dvc remote add -d dummy s3://dummy
Setting 'dummy' as a default remote.
+ dvc remote remove dummy
+ dvc add bar.txt
Error: Initialization error: Config file error: Can't find remote section 'remote "dummy"' in config

```


Discussion:
Hi @tdeboissiere, this is definitely a bug. I think this is happening because the remote you removed is assigned as a default one in the `core` config section:

```
['remote "myremote"']
url = /tmp/dvc-storage
[core]
remote = myremote
```

We'll fix this asap, meanwhile, I would try

```
dvc config -u core.remote
```

as a temporary workaround.

Thank you, for the report!

Resolving patch:
diff --git a/dvc/command/remote.py b/dvc/command/remote.py
--- a/dvc/command/remote.py
+++ b/dvc/command/remote.py
@@ -1,4 +1,6 @@
+import os
 import re
+import configobj
 
 from dvc.config import Config
 from dvc.command.config import CmdConfig
@@ -23,9 +25,35 @@ def run(self):
 
 
 class CmdRemoteRemove(CmdConfig):
+    def _remove_default(self, config_file, remote):
+        path = os.path.join(os.path.dirname(self.config_file),
+                            config_file)
+        config = configobj.ConfigObj(path)
+
+        core = config.get(Config.SECTION_CORE, None)
+        if core is None:
+            return
+
+        default = core.get(Config.SECTION_CORE_REMOTE, None)
+        if default is None:
+            return
+
+        if default == remote:
+            del config[Config.SECTION_CORE][Config.SECTION_CORE_REMOTE]
+            if len(config[Config.SECTION_CORE]) == 0:
+                del config[Config.SECTION_CORE]
+
+        config.write()
+
     def run(self):
         section = Config.SECTION_REMOTE_FMT.format(self.args.name)
-        return self.unset(section, Config.SECTION_REMOTE_URL)
+        ret = self.unset(section)
+        if ret != 0:
+            return ret
+
+        self._remove_default(Config.CONFIG, self.args.name)
+        self._remove_default(Config.CONFIG_LOCAL, self.args.name)
+        return 0
 
 
 class CmdRemoteModify(CmdConfig):


Test patch:
diff --git a/tests/test_remote.py b/tests/test_remote.py
--- a/tests/test_remote.py
+++ b/tests/test_remote.py
@@ -1,4 +1,8 @@
+import os
+import configobj
+
 from dvc.main import main
+from dvc.project import Project
 from dvc.command.remote import CmdRemoteAdd
 from dvc.exceptions import UnsupportedRemoteError
 from dvc.remote import Remote
@@ -41,3 +45,30 @@ class A(object):
     def test_unsupported(self):
         with self.assertRaises(UnsupportedRemoteError):
             Remote(self.dvc, {Config.SECTION_REMOTE_URL: 'unsupported://url'})
+
+
+class TestRemoteRemoveDefault(TestDvc):
+    def test(self):
+        remote = 'mys3'
+        self.assertEqual(main(['remote', 'add', '--default', remote, 's3://bucket/name']), 0)
+        self.assertEqual(main(['remote', 'modify', remote, 'profile', 'default']), 0)
+        self.assertEqual(main(['config', '--local', 'core.remote', remote]), 0)
+
+        config = configobj.ConfigObj(os.path.join(self.dvc.dvc_dir, Config.CONFIG))
+        local_config = configobj.ConfigObj(os.path.join(self.dvc.dvc_dir, Config.CONFIG_LOCAL))
+        self.assertEqual(config[Config.SECTION_CORE][Config.SECTION_CORE_REMOTE], remote)
+        self.assertEqual(local_config[Config.SECTION_CORE][Config.SECTION_CORE_REMOTE], remote)
+
+        self.assertEqual(main(['remote', 'remove', remote]), 0)
+        config = configobj.ConfigObj(os.path.join(self.dvc.dvc_dir, Config.CONFIG))
+        local_config = configobj.ConfigObj(os.path.join(self.dvc.dvc_dir, Config.CONFIG_LOCAL))
+        section = Config.SECTION_REMOTE_FMT.format(remote)
+        self.assertTrue(section not in config.keys())
+
+        core = config.get(Config.SECTION_CORE, None)
+        if core is not None:
+            self.assertTrue(Config.SECTION_CORE_REMOTE not in core.keys())
+
+        core = local_config.get(Config.SECTION_CORE, None)
+        if core is not None:
+            self.assertTrue(Config.SECTION_CORE_REMOTE not in core.keys())