mirror of
https://github.com/spf13/viper
synced 2025-05-06 20:27:17 +00:00
Merge aa295b144a
into 7538d73b4e
This commit is contained in:
commit
d41277840c
2 changed files with 129 additions and 2 deletions
53
util.go
53
util.go
|
@ -21,12 +21,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
"github.com/magiconair/properties"
|
"github.com/magiconair/properties"
|
||||||
toml "github.com/pelletier/go-toml"
|
toml "github.com/pelletier/go-toml"
|
||||||
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigParseError denotes failing to parse configuration file.
|
// ConfigParseError denotes failing to parse configuration file.
|
||||||
|
@ -39,6 +41,16 @@ func (pe ConfigParseError) Error() string {
|
||||||
return fmt.Sprintf("While parsing config: %s", pe.err.Error())
|
return fmt.Sprintf("While parsing config: %s", pe.err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfigMarshalError happens when failing to marshal the configuration.
|
||||||
|
type ConfigMarshalError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns the formatted configuration error.
|
||||||
|
func (e ConfigMarshalError) Error() string {
|
||||||
|
return fmt.Sprintf("While marshaling config: %s", e.err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
// toCaseInsensitiveValue checks if the value is a map;
|
// toCaseInsensitiveValue checks if the value is a map;
|
||||||
// if so, create a copy and lower-case the keys recursively.
|
// if so, create a copy and lower-case the keys recursively.
|
||||||
func toCaseInsensitiveValue(value interface{}) interface{} {
|
func toCaseInsensitiveValue(value interface{}) interface{} {
|
||||||
|
@ -152,6 +164,45 @@ func userHomeDir() string {
|
||||||
return os.Getenv("HOME")
|
return os.Getenv("HOME")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func marshalConfigWriter(f afero.File, c map[string]interface{}, configType string) error {
|
||||||
|
switch configType {
|
||||||
|
case "json":
|
||||||
|
b, err := json.MarshalIndent(v.AllSettings(), "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return ConfigMarshalError{err}
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(string(b))
|
||||||
|
if err != nil {
|
||||||
|
return ConfigMarshalError{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "hcl":
|
||||||
|
// TODO: How to convert map to hcl???
|
||||||
|
|
||||||
|
case "prop", "props", "properties":
|
||||||
|
|
||||||
|
case "toml":
|
||||||
|
t := toml.TreeFromMap(v.AllSettings())
|
||||||
|
s := t.String()
|
||||||
|
_, err := f.WriteString(s)
|
||||||
|
if err != nil {
|
||||||
|
return ConfigMarshalError{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "yaml", "yml":
|
||||||
|
b, err := yaml.Marshal(v.AllSettings())
|
||||||
|
if err != nil {
|
||||||
|
return ConfigMarshalError{err}
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(string(b))
|
||||||
|
if err != nil {
|
||||||
|
return ConfigMarshalError{err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType string) error {
|
func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType string) error {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
buf.ReadFrom(in)
|
buf.ReadFrom(in)
|
||||||
|
|
78
viper.go
78
viper.go
|
@ -30,12 +30,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
"gopkg.in/fsnotify.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var v *Viper
|
var v *Viper
|
||||||
|
@ -1147,6 +1147,73 @@ func (v *Viper) MergeConfig(in io.Reader) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeConfig(filename string, force bool) error { return v.writeConfig(filename, force) }
|
||||||
|
func (v *Viper) writeConfig(filename string, force bool) error {
|
||||||
|
jww.INFO.Println("Attempting to write configuration to file.")
|
||||||
|
ext := filepath.Ext(filename)
|
||||||
|
if len(ext) <= 1 {
|
||||||
|
return fmt.Errorf("Filename: %s requires valid extension.", filename)
|
||||||
|
}
|
||||||
|
configType := ext[1:]
|
||||||
|
if !stringInSlice(configType, SupportedExts) {
|
||||||
|
return UnsupportedConfigError(configType)
|
||||||
|
}
|
||||||
|
if v.config == nil {
|
||||||
|
v.config = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
var flags int
|
||||||
|
if force == true {
|
||||||
|
flags = os.O_CREATE | os.O_WRONLY
|
||||||
|
} else {
|
||||||
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
|
flags = os.O_WRONLY
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("File: %s exists. Use WriteConfig to overwrite.", filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f, err := v.fs.OpenFile(filename, flags, os.FileMode(0644))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return v.marshalWriter(f, v.config, configType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteConfig writes the current configuration to a file.
|
||||||
|
func WriteConfig() error { return v.WriteConfig() }
|
||||||
|
func (v *Viper) WriteConfig() error {
|
||||||
|
filename, err := v.getConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return v.writeConfig(filename, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeWriteConfig writes current configuration to file only if the file does not exist.
|
||||||
|
func SafeWriteConfig() error { return v.SafeWriteConfig() }
|
||||||
|
func (v *Viper) SafeWriteConfig() error {
|
||||||
|
filename, err := v.getConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return v.writeConfig(filename, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteConfigAs writes current configuration to a given filename.
|
||||||
|
func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) }
|
||||||
|
func (v *Viper) WriteConfigAs(filename string) error {
|
||||||
|
return v.writeConfig(filename, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeWriteConfigAs writes current configuration to a given filename is it does not exist.
|
||||||
|
func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
|
||||||
|
func (v *Viper) SafeWriteConfigAs(filename string) error {
|
||||||
|
return v.writeConfig(filename, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteConfigKey writes given key and value to file.
|
||||||
|
|
||||||
|
// WriteConfigKeyAs writes given key and value to a given filename.
|
||||||
|
|
||||||
func keyExists(k string, m map[string]interface{}) string {
|
func keyExists(k string, m map[string]interface{}) string {
|
||||||
lk := strings.ToLower(k)
|
lk := strings.ToLower(k)
|
||||||
for mk := range m {
|
for mk := range m {
|
||||||
|
@ -1265,6 +1332,15 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
||||||
return unmarshallConfigReader(in, c, v.getConfigType())
|
return unmarshallConfigReader(in, c, v.getConfigType())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshal a map into Writer.
|
||||||
|
func marshalWriter(out afero.File, c map[string]interface{}, configType string) error {
|
||||||
|
return v.marshalWriter(out, c, configType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Viper) marshalWriter(out afero.File, c map[string]interface{}, configType string) error {
|
||||||
|
return marshalConfigWriter(out, c, configType)
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Viper) insensitiviseMaps() {
|
func (v *Viper) insensitiviseMaps() {
|
||||||
insensitiviseMap(v.config)
|
insensitiviseMap(v.config)
|
||||||
insensitiviseMap(v.defaults)
|
insensitiviseMap(v.defaults)
|
||||||
|
|
Loading…
Add table
Reference in a new issue