refactor(repo): all config writes must go through repo
Brian Tiger Chow committed
Jan 12, 2015 at 15:23 UTC
1b700864f914e1d1f33a7490f308a532f12111eb
8 files changed
+132
-55
cmd/ipfs/init.go
+21
-14
@@ -78,16 +78,16 @@ IPFS and are now interfacing with the ipfs merkledag!
78
For a short demo of what you can do, enter 'ipfs tour'
79
`
80
81
-func initWithDefaults(configRoot string) error {
82
- _, err := doInit(configRoot, false, nBitsForKeypairDefault)
81
+func initWithDefaults(repoRoot string) error {
82
+ _, err := doInit(repoRoot, false, nBitsForKeypairDefault)
83
return debugerror.Wrap(err)
84
}
85
86
-func doInit(configRoot string, force bool, nBitsForKeypair int) (interface{}, error) {
86
+func doInit(repoRoot string, force bool, nBitsForKeypair int) (interface{}, error) {
87
88
- u.POut("initializing ipfs node at %s\n", configRoot)
88
+ u.POut("initializing ipfs node at %s\n", repoRoot)
89
90
- if fsrepo.ConfigIsInitialized(configRoot) && !force {
90
+ if fsrepo.IsInitialized(repoRoot) && !force {
91
return nil, errCannotInitConfigExists
92
}
93
@@ -96,16 +96,23 @@ func doInit(configRoot string, force bool, nBitsForKeypair int) (interface{}, er
96
return nil, err
97
}
98
99
- r := fsrepo.At(configRoot)
100
- if err := r.Open(); err != nil {
101
- return nil, err
102
- }
103
- if err := r.SetConfig(conf); err != nil {
104
- return nil, err
105
- }
106
- if err := r.Close(); err != nil {
107
- return nil, err
99
+ if !fsrepo.IsInitialized(repoRoot) {
100
+ if err := fsrepo.Init(repoRoot, conf); err != nil {
101
+ return nil, err
102
+ }
103
+ } else {
104
+ r := fsrepo.At(repoRoot)
105
+ if err := r.Open(); err != nil {
106
+ return nil, err
107
+ }
108
+ if err := r.SetConfig(conf); err != nil {
109
+ return nil, err
110
+ }
111
+ if err := r.Close(); err != nil {
112
+ return nil, err
113
+ }
114
}
115
+
116
if err := repo.ConfigureEventLogger(conf.Logs); err != nil {
117
return nil, err
118
}
cmd/ipfs/tour.go
+5
-4
@@ -9,8 +9,8 @@ import (
9
10
cmds "github.com/jbenet/go-ipfs/commands"
11
config "github.com/jbenet/go-ipfs/repo/config"
12
- tour "github.com/jbenet/go-ipfs/tour"
12
fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
13
+ tour "github.com/jbenet/go-ipfs/tour"
14
)
15
16
var tourCmd = &cmds.Command{
@@ -188,9 +188,10 @@ func tourGet(id tour.ID) (*tour.Topic, error) {
188
189
// TODO share func
190
func writeConfig(path string, cfg *config.Config) error {
191
- filename, err := config.Filename(path)
192
- if err != nil {
191
+ r := fsrepo.At(path)
192
+ if err := r.Open(); err != nil {
193
return err
194
}
195
- return fsrepo.WriteConfigFile(filename, cfg)
195
+ defer r.Close()
196
+ return r.SetConfig(cfg)
197
}
core/commands/bootstrap.go
+18
-26
@@ -5,6 +5,7 @@ import (
5
"io"
6
7
cmds "github.com/jbenet/go-ipfs/commands"
8
+ repo "github.com/jbenet/go-ipfs/repo"
9
config "github.com/jbenet/go-ipfs/repo/config"
10
"github.com/jbenet/go-ipfs/repo/fsrepo"
11
u "github.com/jbenet/go-ipfs/util"
@@ -77,15 +78,12 @@ in the bootstrap list).
78
return nil, err
79
}
80
80
- filename, err := config.Filename(req.Context().ConfigRoot)
81
- if err != nil {
82
- return nil, err
83
- }
84
-
85
- cfg, err := req.Context().GetConfig()
86
- if err != nil {
81
+ r := fsrepo.At(req.Context().ConfigRoot)
82
+ if err := r.Open(); err != nil {
83
return nil, err
84
}
85
+ defer r.Close()
86
+ cfg := r.Config()
87
88
deflt, _, err := req.Option("default").Bool()
89
if err != nil {
@@ -102,7 +100,7 @@ in the bootstrap list).
100
inputPeers = append(inputPeers, defltPeers...)
101
}
102
105
- added, err := bootstrapAdd(filename, cfg, inputPeers)
103
+ added, err := bootstrapAdd(r, cfg, inputPeers)
104
if err != nil {
105
return nil, err
106
}
@@ -147,15 +145,12 @@ var bootstrapRemoveCmd = &cmds.Command{
145
return nil, err
146
}
147
150
- filename, err := config.Filename(req.Context().ConfigRoot)
151
- if err != nil {
152
- return nil, err
153
- }
154
-
155
- cfg, err := req.Context().GetConfig()
156
- if err != nil {
148
+ r := fsrepo.At(req.Context().ConfigRoot)
149
+ if err := r.Open(); err != nil {
150
return nil, err
151
}
152
+ defer r.Close()
153
+ cfg := r.Config()
154
155
all, _, err := req.Option("all").Bool()
156
if err != nil {
@@ -164,9 +159,9 @@ var bootstrapRemoveCmd = &cmds.Command{
159
160
var removed []config.BootstrapPeer
161
if all {
167
- removed, err = bootstrapRemoveAll(filename, cfg)
162
+ removed, err = bootstrapRemoveAll(r, cfg)
163
} else {
169
- removed, err = bootstrapRemove(filename, cfg, input)
164
+ removed, err = bootstrapRemove(r, cfg, input)
165
}
166
if err != nil {
167
return nil, err
@@ -233,7 +228,7 @@ func bootstrapWritePeers(w io.Writer, prefix string, peers []config.BootstrapPee
228
return nil
229
}
230
236
-func bootstrapAdd(filename string, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
231
+func bootstrapAdd(r repo.Interface, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
232
added := make([]config.BootstrapPeer, 0, len(peers))
233
234
for _, peer := range peers {
@@ -251,15 +246,14 @@ func bootstrapAdd(filename string, cfg *config.Config, peers []config.BootstrapP
246
}
247
}
248
254
- err := fsrepo.WriteConfigFile(filename, cfg)
255
- if err != nil {
249
+ if err := r.SetConfig(cfg); err != nil {
250
return nil, err
251
}
252
253
return added, nil
254
}
255
262
-func bootstrapRemove(filename string, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
256
+func bootstrapRemove(r repo.Interface, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
257
removed := make([]config.BootstrapPeer, 0, len(toRemove))
258
keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap))
259
@@ -279,21 +273,19 @@ func bootstrapRemove(filename string, cfg *config.Config, toRemove []config.Boot
273
}
274
cfg.Bootstrap = keep
275
282
- err := fsrepo.WriteConfigFile(filename, cfg)
283
- if err != nil {
276
+ if err := r.SetConfig(cfg); err != nil {
277
return nil, err
278
}
279
280
return removed, nil
281
}
282
290
-func bootstrapRemoveAll(filename string, cfg *config.Config) ([]config.BootstrapPeer, error) {
283
+func bootstrapRemoveAll(r repo.Interface, cfg *config.Config) ([]config.BootstrapPeer, error) {
284
removed := make([]config.BootstrapPeer, len(cfg.Bootstrap))
285
copy(removed, cfg.Bootstrap)
286
287
cfg.Bootstrap = nil
295
- err := fsrepo.WriteConfigFile(filename, cfg)
296
- if err != nil {
288
+ if err := r.SetConfig(cfg); err != nil {
289
return nil, err
290
}
291
repo/fsrepo/fsrepo.go
+54
-6
@@ -1,6 +1,7 @@
1
package fsrepo
2
3
import (
4
+ "fmt"
5
"io"
6
"os"
7
"path/filepath"
@@ -11,17 +12,40 @@ import (
12
)
13
14
type FSRepo struct {
15
+ state state
16
path string
15
- config config.Config
17
+ config *config.Config
18
}
19
20
func At(path string) *FSRepo {
21
return &FSRepo{
20
- path: path,
22
+ path: path,
23
+ state: unopened, // explicitly set for clarity
24
}
25
}
26
27
+func Init(path string, conf *config.Config) error {
28
+ if IsInitialized(path) {
29
+ return nil
30
+ }
31
+ configFilename, err := config.Filename(path)
32
+ if err != nil {
33
+ return err
34
+ }
35
+ if err := writeConfigFile(configFilename, conf); err != nil {
36
+ return err
37
+ }
38
+ return nil
39
+}
40
+
41
+// Open returns an error if the repo is not initialized.
42
func (r *FSRepo) Open() error {
43
+ if r.state != unopened {
44
+ return debugerror.Errorf("repo is %s", r.state)
45
+ }
46
+ if !IsInitialized(r.path) {
47
+ return debugerror.New("repo is not initialized")
48
+ }
49
// check repo path, then check all constituent parts.
50
// TODO acquire repo lock
51
// TODO if err := initCheckDir(logpath); err != nil { // }
@@ -29,6 +53,16 @@ func (r *FSRepo) Open() error {
53
return err
54
}
55
56
+ configFilename, err := config.Filename(r.path)
57
+ if err != nil {
58
+ return err
59
+ }
60
+ conf, err := Load(configFilename)
61
+ if err != nil {
62
+ return err
63
+ }
64
+ r.config = conf
65
+
66
// datastore
67
dspath, err := config.DataStorePath("")
68
if err != nil {
@@ -46,29 +80,43 @@ func (r *FSRepo) Open() error {
80
return debugerror.Errorf("logs: %s", err)
81
}
82
83
+ r.state = opened
84
return nil
85
}
86
87
+func (r *FSRepo) Config() *config.Config {
88
+ if r.state != opened {
89
+ panic(fmt.Sprintln("repo is", r.state))
90
+ }
91
+ return r.config
92
+}
93
+
94
func (r *FSRepo) SetConfig(conf *config.Config) error {
95
+ if r.state != opened {
96
+ panic(fmt.Sprintln("repo is", r.state))
97
+ }
98
configFilename, err := config.Filename(r.path)
99
if err != nil {
100
return err
101
}
57
- if err := WriteConfigFile(configFilename, conf); err != nil {
102
+ if err := writeConfigFile(configFilename, conf); err != nil {
103
return err
104
}
60
- r.config = *conf // copy so caller cannot modify the private config
105
+ *r.config = *conf // copy so caller cannot modify the private config
106
return nil
107
}
108
109
func (r *FSRepo) Close() error {
110
+ if r.state != opened {
111
+ return debugerror.Errorf("repo is %s", r.state)
112
+ }
113
return nil // TODO release repo lock
114
}
115
116
var _ io.Closer = &FSRepo{}
117
70
-// ConfigIsInitialized returns true if the config exists in provided |path|.
71
-func ConfigIsInitialized(path string) bool {
118
+// IsInitialized returns true if the repo is initialized at provided |path|.
119
+func IsInitialized(path string) bool {
120
configFilename, err := config.Filename(path)
121
if err != nil {
122
return false
repo/fsrepo/serialize.go
+3
-3
@@ -30,7 +30,7 @@ func ReadConfigFile(filename string, cfg interface{}) error {
30
}
31
32
// WriteConfigFile writes the config from `cfg` into `filename`.
33
-func WriteConfigFile(filename string, cfg interface{}) error {
33
+func writeConfigFile(filename string, cfg interface{}) error {
34
err := os.MkdirAll(filepath.Dir(filename), 0775)
35
if err != nil {
36
return err
@@ -125,7 +125,7 @@ func WriteConfigKey(filename, key string, value interface{}) error {
125
}
126
}
127
128
- return WriteConfigFile(filename, cfg)
128
+ return writeConfigFile(filename, cfg)
129
}
130
131
// Load reads given file and returns the read config, or error.
@@ -165,5 +165,5 @@ func RecordUpdateCheck(cfg *config.Config, filename string) {
165
log.Error("config.Version.CheckPeriod not set. config broken?")
166
}
167
168
- WriteConfigFile(filename, cfg)
168
+ writeConfigFile(filename, cfg)
169
}
repo/fsrepo/serialize_test.go
+1
-1
@@ -11,7 +11,7 @@ func TestConfig(t *testing.T) {
11
const dsPath = "/path/to/datastore"
12
cfgWritten := new(config.Config)
13
cfgWritten.Datastore.Path = dsPath
14
- err := WriteConfigFile(filename, cfgWritten)
14
+ err := writeConfigFile(filename, cfgWritten)
15
if err != nil {
16
t.Error(err)
17
}
repo/fsrepo/state.go
new
+22
@@ -0,0 +1,22 @@
1
+package fsrepo
2
+
3
+type state int
4
+
5
+const (
6
+ unopened = iota
7
+ opened
8
+ closed
9
+)
10
+
11
+func (s state) String() string {
12
+ switch s {
13
+ case unopened:
14
+ return "unopened"
15
+ case opened:
16
+ return "opened"
17
+ case closed:
18
+ return "closed"
19
+ default:
20
+ return "invalid"
21
+ }
22
+}
repo/repo.go
+8
-1
@@ -1,6 +1,13 @@
1
package repo
2
3
-import util "github.com/jbenet/go-ipfs/util"
3
+import (
4
+ config "github.com/jbenet/go-ipfs/repo/config"
5
+ util "github.com/jbenet/go-ipfs/util"
6
+)
7
+
8
+type Interface interface {
9
+ SetConfig(*config.Config) error
10
+}
11
12
// IsInitialized returns true if the path is home to an initialized IPFS
13
// repository.