// setConfigUnsynced is for private use. func (r *FSRepo) setConfigUnsynced(updated *config.Config) error { configFilename, err := config.Filename(r.path) if err != nil { return err } // 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 := serialize.ReadConfigFile(configFilename, &mapconf); err != nil { return err } m, err := config.ToMap(updated) if err != nil { return err } for k, v := range m { mapconf[k] = v } if err := serialize.WriteConfigFile(configFilename, mapconf); err != nil { return err } *r.config = *updated // copy so caller cannot modify this private config return nil }
// GetConfigKey retrieves only the value of a particular key. func (r *FSRepo) GetConfigKey(key string) (interface{}, error) { packageLock.Lock() defer packageLock.Unlock() if r.closed { return nil, errors.New("repo is closed") } filename, err := config.Filename(r.path) if err != nil { return nil, err } var cfg map[string]interface{} if err := serialize.ReadConfigFile(filename, &cfg); err != nil { return nil, err } return common.MapGetKV(cfg, key) }
// SetConfigKey writes the value of a particular key. func (r *FSRepo) SetConfigKey(key string, value interface{}) error { packageLock.Lock() defer packageLock.Unlock() if r.closed { return errors.New("repo is closed") } filename, err := config.Filename(r.path) if err != nil { return err } var mapconf map[string]interface{} if err := serialize.ReadConfigFile(filename, &mapconf); err != nil { return err } // Get the type of the value associated with the key oldValue, err := common.MapGetKV(mapconf, key) ok := true if err != nil { // key-value does not exist yet switch v := value.(type) { case string: value, err = strconv.ParseBool(v) if err != nil { value, err = strconv.Atoi(v) if err != nil { value, err = strconv.ParseFloat(v, 32) if err != nil { value = v } } } default: } } else { switch oldValue.(type) { case bool: value, ok = value.(bool) case int: value, ok = value.(int) case float32: value, ok = value.(float32) case string: value, ok = value.(string) default: value = value } if !ok { return fmt.Errorf("Wrong config type, expected %T", oldValue) } } if err := common.MapSetKV(mapconf, key, value); err != nil { return err } // This step doubles as to validate the map against the struct // before serialization conf, err := config.FromMap(mapconf) if err != nil { return err } if err := serialize.WriteConfigFile(filename, mapconf); err != nil { return err } return r.setConfigUnsynced(conf) // TODO roll this into this method }