// 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 }
// 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 } switch v := value.(type) { case string: if i, err := strconv.Atoi(v); err == nil { value = i } } var mapconf map[string]interface{} if err := serialize.ReadConfigFile(filename, &mapconf); err != nil { return err } if err := common.MapSetKV(mapconf, key, value); err != nil { return err } 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 }
// configIsInitialized returns true if the repo is initialized at // provided |path|. func configIsInitialized(path string) bool { configFilename, err := config.Filename(path) if err != nil { return false } if !util.FileExists(configFilename) { return false } return true }
// openConfig returns an error if the config file is not present. func (r *FSRepo) openConfig() error { configFilename, err := config.Filename(r.path) if err != nil { return err } conf, err := serialize.Load(configFilename) if err != nil { return err } r.config = conf return nil }
// ConfigAt returns an error if the FSRepo at the given path is not // initialized. This function allows callers to read the config file even when // another process is running and holding the lock. func ConfigAt(repoPath string) (*config.Config, error) { // packageLock must be held to ensure that the Read is atomic. packageLock.Lock() defer packageLock.Unlock() configFilename, err := config.Filename(repoPath) if err != nil { return nil, err } return serialize.Load(configFilename) }
func initConfig(path string, conf *config.Config) error { if configIsInitialized(path) { return nil } configFilename, err := config.Filename(path) if err != nil { return err } // initialization is the one time when it's okay to write to the config // without reading the config from disk and merging any user-provided keys // that may exist. if err := serialize.WriteConfigFile(configFilename, conf); err != nil { return err } 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) }
"edit": configEditCmd, "replace": configReplaceCmd, }, } var configShowCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Outputs the content of the config file.", ShortDescription: ` WARNING: Your private key is stored in the config file, and it will be included in the output of this command. `, }, Run: func(req cmds.Request, res cmds.Response) { filename, err := config.Filename(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return } output, err := showConfig(filename) if err != nil { res.SetError(err, cmds.ErrNormal) return } res.SetOutput(output) }, } var configEditCmd = &cmds.Command{
// 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 }