When setting config keys, the program doesn't know whether the
key-to-be-modified exists on the Config struct. (Perhaps, with
reflection, it is possible to find the field). To allow callers to write
non-existent keys, the program would...
Before:
1) converts the in-memory *Config to a map
2) sets the key on the map, and
3) writes this map to disk.
4) Then, it converts this map back into an in-memory struct.
This commit swaps 3 and 4 so the map can be validated against the struct
before being written to disk. This prevents the bug identified in #740.
⚠️ this commit makes your current configs unusable, as the
default bootstrap peers. You may need to edit your config.
Go from:
```js
Bootstrap: [
{
"Address": "/ip4/104.131.131.82/tcp/4001",
"PeerID": "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
}
]
```
To:
```js
Bootstrap: [
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
]
```
@whyrusleeping @jbenet newly initialized datastores were being dumped
into ./go-ipfs. Eeek. An oversight during the FSRepo refactor. Not sure
how this bug survived this long.
doh! I forgot to make sure leveldb is only opened once. thanks for catching this @mappum
* You may be wondering why we don't just share pointers to FSRepos. We
want to manage the lifecycle of the FSRepo by tracking its `state`.
Thus each FSRepo/goroutine requires private instance variables. For
this reason, each `fsrepo.At(p)` caller must get its own goroutine.
* There's a test in `fsrepo` because callers desire the ability to Open
from multiple goroutines. There's a test in `component` because this
is where the actual work needs to go in order to provide the desired
contract. If the `component` package moves, the assurances need to
move along with it.
cc @whyrusleeping @jbenet
side note: there are a couple packages in FSRepo that it might be
worthwhile to extract once the dust settles on this feature-set.