@cryptotaxi247 / kubo / commits / 20cc7a451

go-ipfs-config: refactor(config, repo): all writes go through FSRepo. next: privatize these

Brian Tiger Chow committed Jan 12, 2015 at 15:00 UTC 20cc7a451b66054dca1e5e17f5ae54ac73b5c298
4 files changed +13 -194
config/config.go
+11 -23
@@ -3,6 +3,7 @@ package config
3
4 import (
5 "encoding/base64"
6 + "encoding/json"
7 "errors"
8 "os"
9 "path/filepath"
@@ -13,7 +14,6 @@ import (
14
15 ic "github.com/jbenet/go-ipfs/p2p/crypto"
16 u "github.com/jbenet/go-ipfs/util"
16 - "github.com/jbenet/go-ipfs/util/debugerror"
17 )
18
19 var log = u.Logger("config")
@@ -191,29 +191,17 @@ func (i *Identity) DecodePrivateKey(passphrase string) (ic.PrivKey, error) {
191 return ic.UnmarshalPrivateKey(pkb)
192 }
193
194 -// Load reads given file and returns the read config, or error.
195 -func Load(filename string) (*Config, error) {
196 - // if nothing is there, fail. User must run 'ipfs init'
197 - if !u.FileExists(filename) {
198 - return nil, debugerror.New("ipfs not initialized, please run 'ipfs init'")
194 +// HumanOutput gets a config value ready for printing
195 +func HumanOutput(value interface{}) ([]byte, error) {
196 + s, ok := value.(string)
197 + if ok {
198 + return []byte(strings.Trim(s, "\n")), nil
199 }
200 -
201 - var cfg Config
202 - err := ReadConfigFile(filename, &cfg)
203 - if err != nil {
204 - return nil, err
205 - }
206 -
207 - // tilde expansion on datastore path
208 - cfg.Datastore.Path, err = u.TildeExpansion(cfg.Datastore.Path)
209 - if err != nil {
210 - return nil, err
211 - }
212 -
213 - return &cfg, err
200 + return Marshal(value)
201 }
202
216 -// Set sets the value of a particular config key
217 -func Set(filename, key, value string) error {
218 - return WriteConfigKey(filename, key, value)
203 +// Marshal configuration with JSON
204 +func Marshal(value interface{}) ([]byte, error) {
205 + // need to prettyprint, hence MarshalIndent, instead of Encoder
206 + return json.MarshalIndent(value, "", " ")
207 }
config/config_test.go deleted
-24
@@ -1,24 +0,0 @@
1 -package config
2 -
3 -import (
4 - "testing"
5 -)
6 -
7 -func TestConfig(t *testing.T) {
8 - const filename = ".ipfsconfig"
9 - const dsPath = "/path/to/datastore"
10 - cfgWritten := new(Config)
11 - cfgWritten.Datastore.Path = dsPath
12 - err := WriteConfigFile(filename, cfgWritten)
13 - if err != nil {
14 - t.Error(err)
15 - }
16 - cfgRead, err := Load(filename)
17 - if err != nil {
18 - t.Error(err)
19 - return
20 - }
21 - if cfgWritten.Datastore.Path != cfgRead.Datastore.Path {
22 - t.Fail()
23 - }
24 -}
config/serialize.go deleted
-144
@@ -1,144 +0,0 @@
1 -package config
2 -
3 -import (
4 - "encoding/json"
5 - "fmt"
6 - "io"
7 - "os"
8 - "path/filepath"
9 - "strings"
10 -)
11 -
12 -// ReadConfigFile reads the config from `filename` into `cfg`.
13 -func ReadConfigFile(filename string, cfg interface{}) error {
14 - f, err := os.Open(filename)
15 - if err != nil {
16 - return err
17 - }
18 - defer f.Close()
19 -
20 - if err := Decode(f, cfg); err != nil {
21 - return fmt.Errorf("Failure to decode config: %s", err)
22 - }
23 - return nil
24 -}
25 -
26 -// WriteConfigFile writes the config from `cfg` into `filename`.
27 -func WriteConfigFile(filename string, cfg interface{}) error {
28 - err := os.MkdirAll(filepath.Dir(filename), 0775)
29 - if err != nil {
30 - return err
31 - }
32 -
33 - f, err := os.Create(filename)
34 - if err != nil {
35 - return err
36 - }
37 - defer f.Close()
38 -
39 - return Encode(f, cfg)
40 -}
41 -
42 -// WriteFile writes the buffer at filename
43 -func WriteFile(filename string, buf []byte) error {
44 - err := os.MkdirAll(filepath.Dir(filename), 0775)
45 - if err != nil {
46 - return err
47 - }
48 -
49 - f, err := os.Create(filename)
50 - if err != nil {
51 - return err
52 - }
53 - defer f.Close()
54 -
55 - _, err = f.Write(buf)
56 - return err
57 -}
58 -
59 -// HumanOutput gets a config value ready for printing
60 -func HumanOutput(value interface{}) ([]byte, error) {
61 - s, ok := value.(string)
62 - if ok {
63 - return []byte(strings.Trim(s, "\n")), nil
64 - }
65 - return Marshal(value)
66 -}
67 -
68 -// Marshal configuration with JSON
69 -func Marshal(value interface{}) ([]byte, error) {
70 - // need to prettyprint, hence MarshalIndent, instead of Encoder
71 - return json.MarshalIndent(value, "", " ")
72 -}
73 -
74 -// Encode configuration with JSON
75 -func Encode(w io.Writer, value interface{}) error {
76 - // need to prettyprint, hence MarshalIndent, instead of Encoder
77 - buf, err := Marshal(value)
78 - if err != nil {
79 - return err
80 - }
81 -
82 - _, err = w.Write(buf)
83 - return err
84 -}
85 -
86 -// Decode configuration with JSON
87 -func Decode(r io.Reader, value interface{}) error {
88 - return json.NewDecoder(r).Decode(value)
89 -}
90 -
91 -// ReadConfigKey retrieves only the value of a particular key
92 -func ReadConfigKey(filename, key string) (interface{}, error) {
93 - var cfg interface{}
94 - if err := ReadConfigFile(filename, &cfg); err != nil {
95 - return nil, err
96 - }
97 -
98 - var ok bool
99 - cursor := cfg
100 - parts := strings.Split(key, ".")
101 - for i, part := range parts {
102 - cursor, ok = cursor.(map[string]interface{})[part]
103 - if !ok {
104 - sofar := strings.Join(parts[:i], ".")
105 - return nil, fmt.Errorf("%s key has no attributes", sofar)
106 - }
107 - }
108 - return cursor, nil
109 -}
110 -
111 -// WriteConfigKey writes the value of a particular key
112 -func WriteConfigKey(filename, key string, value interface{}) error {
113 - var cfg interface{}
114 - if err := ReadConfigFile(filename, &cfg); err != nil {
115 - return err
116 - }
117 -
118 - var ok bool
119 - var mcursor map[string]interface{}
120 - cursor := cfg
121 -
122 - parts := strings.Split(key, ".")
123 - for i, part := range parts {
124 - mcursor, ok = cursor.(map[string]interface{})
125 - if !ok {
126 - sofar := strings.Join(parts[:i], ".")
127 - return fmt.Errorf("%s key is not a map", sofar)
128 - }
129 -
130 - // last part? set here
131 - if i == (len(parts) - 1) {
132 - mcursor[part] = value
133 - break
134 - }
135 -
136 - cursor, ok = mcursor[part]
137 - if !ok { // create map if this is empty
138 - mcursor[part] = map[string]interface{}{}
139 - cursor = mcursor[part]
140 - }
141 - }
142 -
143 - return WriteConfigFile(filename, cfg)
144 -}
config/version_test.go
+2 -3
@@ -1,6 +1,7 @@
1 package config
2
3 import (
4 + "encoding/json"
5 "strings"
6 "testing"
7 )
@@ -23,8 +24,7 @@ func TestAutoUpdateValues(t *testing.T) {
24 }
25
26 for i, tc := range tests {
26 - err := Decode(strings.NewReader(tc.input), &tval)
27 - if err != tc.err {
27 + if err := json.NewDecoder(strings.NewReader(tc.input)).Decode(&tval); err != tc.err {
28 t.Fatalf("%d failed - got err %q wanted %v", i, err, tc.err)
29 }
30
@@ -32,5 +32,4 @@ func TestAutoUpdateValues(t *testing.T) {
32 t.Fatalf("%d failed - got val %q where we wanted %q", i, tval.AutoUpdate, tc.val)
33 }
34 }
35 -
35 }