From e84fc5df22e3225459590fdaa4ab7844cedc2a06 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Mon, 12 Jan 2015 18:31:42 -0800 Subject: [PATCH] fix(config): avoid clobbering user-provided key value pairs let me know if this looks off @whyrusleeping @jbenet --- repo/config/config.go | 12 ++++++++++++ repo/fsrepo/fsrepo.go | 20 +++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/repo/config/config.go b/repo/config/config.go index a0a79eeba..1230cd29b 100644 --- a/repo/config/config.go +++ b/repo/config/config.go @@ -219,3 +219,15 @@ func FromMap(v map[string]interface{}) (*Config, error) { } return &conf, nil } + +func ToMap(conf *Config) (map[string]interface{}, error) { + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(conf); err != nil { + return nil, err + } + var m map[string]interface{} + if err := json.NewDecoder(&buf).Decode(&m); err != nil { + return nil, fmt.Errorf("Failure to decode config: %s", err) + } + return m, nil +} diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 53e38745a..588eaa15f 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -99,7 +99,7 @@ func (r *FSRepo) Config() *config.Config { } // SetConfig updates the FSRepo's config. -func (r *FSRepo) SetConfig(conf *config.Config) error { +func (r *FSRepo) SetConfig(updated *config.Config) error { if r.state != opened { panic(fmt.Sprintln("repo is", r.state)) } @@ -107,10 +107,24 @@ func (r *FSRepo) SetConfig(conf *config.Config) error { if err != nil { return err } - if err := writeConfigFile(configFilename, conf); err != nil { + // to avoid clobbering user-provided keys, must read the config from disk + // as a map, write the updated struct values to the map and write the map + // to disk. + var mapconf map[string]interface{} + if err := readConfigFile(configFilename, &mapconf); err != nil { return err } - *r.config = *conf // copy so caller cannot modify the private config + m, err := config.ToMap(updated) + if err != nil { + return err + } + for k, v := range m { + mapconf[k] = v + } + if err := writeConfigFile(configFilename, mapconf); err != nil { + return err + } + *r.config = *updated // copy so caller cannot modify this private config return nil }