Fix handling of default values in config (fixes #83)

This commit is contained in:
Jakob Borg 2014-03-04 22:29:43 +01:00
parent 799f55e7ae
commit d6c9afd07f
2 changed files with 34 additions and 16 deletions

View File

@ -46,7 +46,7 @@ type OptionsConfiguration struct {
MaxChangeKbps int `xml:"maxChangeKbps" default:"1000" ini:"max-change-bw"` MaxChangeKbps int `xml:"maxChangeKbps" default:"1000" ini:"max-change-bw"`
} }
func setDefaults(data interface{}, setEmptySlices bool) error { func setDefaults(data interface{}) error {
s := reflect.ValueOf(data).Elem() s := reflect.ValueOf(data).Elem()
t := s.Type() t := s.Type()
@ -56,21 +56,10 @@ func setDefaults(data interface{}, setEmptySlices bool) error {
v := tag.Get("default") v := tag.Get("default")
if len(v) > 0 { if len(v) > 0 {
if f.Kind().String() == "slice" && f.Len() != 0 {
continue
}
switch f.Interface().(type) { switch f.Interface().(type) {
case string: case string:
f.SetString(v) f.SetString(v)
case []string:
if setEmptySlices {
rv := reflect.MakeSlice(reflect.TypeOf([]string{}), 1, 1)
rv.Index(0).SetString(v)
f.Set(rv)
}
case int: case int:
i, err := strconv.ParseInt(v, 10, 64) i, err := strconv.ParseInt(v, 10, 64)
if err != nil { if err != nil {
@ -81,6 +70,11 @@ func setDefaults(data interface{}, setEmptySlices bool) error {
case bool: case bool:
f.SetBool(v == "true") f.SetBool(v == "true")
case []string:
// We don't do anything with string slices here. Any default
// we set will be appended to by the XML decoder, so we fill
// those after decoding.
default: default:
panic(f.Type()) panic(f.Type())
} }
@ -89,6 +83,30 @@ func setDefaults(data interface{}, setEmptySlices bool) error {
return nil return nil
} }
// fillNilSlices sets default value on slices that are still nil.
func fillNilSlices(data interface{}) error {
s := reflect.ValueOf(data).Elem()
t := s.Type()
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
tag := t.Field(i).Tag
v := tag.Get("default")
if len(v) > 0 {
switch f.Interface().(type) {
case []string:
if f.IsNil() {
rv := reflect.MakeSlice(reflect.TypeOf([]string{}), 1, 1)
rv.Index(0).SetString(v)
f.Set(rv)
}
}
}
}
return nil
}
func readConfigINI(m map[string]string, data interface{}) error { func readConfigINI(m map[string]string, data interface{}) error {
s := reflect.ValueOf(data).Elem() s := reflect.ValueOf(data).Elem()
t := s.Type() t := s.Type()
@ -152,15 +170,15 @@ func uniqueStrings(ss []string) []string {
func readConfigXML(rd io.Reader) (Configuration, error) { func readConfigXML(rd io.Reader) (Configuration, error) {
var cfg Configuration var cfg Configuration
setDefaults(&cfg, false) setDefaults(&cfg)
setDefaults(&cfg.Options, false) setDefaults(&cfg.Options)
var err error var err error
if rd != nil { if rd != nil {
err = xml.NewDecoder(rd).Decode(&cfg) err = xml.NewDecoder(rd).Decode(&cfg)
} }
setDefaults(&cfg.Options, true) fillNilSlices(&cfg.Options)
cfg.Options.ListenAddress = uniqueStrings(cfg.Options.ListenAddress) cfg.Options.ListenAddress = uniqueStrings(cfg.Options.ListenAddress)
return cfg, err return cfg, err

View File

@ -92,7 +92,7 @@ func TestOverriddenValues(t *testing.T) {
FollowSymlinks: false, FollowSymlinks: false,
GUIEnabled: false, GUIEnabled: false,
GUIAddress: "125.2.2.2:8080", GUIAddress: "125.2.2.2:8080",
GlobalAnnServer: "announce.nym.se:22025", GlobalAnnServer: "syncthing.nym.se:22025",
GlobalAnnEnabled: false, GlobalAnnEnabled: false,
LocalAnnEnabled: false, LocalAnnEnabled: false,
ParallelRequests: 32, ParallelRequests: 32,