in newt/syscfg/syscfg.go [445:572]
func readSetting(name string, lpkg *pkg.LocalPackage,
vals map[interface{}]interface{}) (CfgEntry, error) {
entry := CfgEntry{}
entry.Name = name
entry.PackageDef = lpkg
entry.Description = stringValue(vals["description"])
if boolValue(vals["defunct"]) {
entry.State = CFG_SETTING_STATE_DEFUNCT
} else if boolValue(vals["deprecated"]) {
entry.State = CFG_SETTING_STATE_DEPRECATED
} else if boolValue(vals["experimental"]) {
entry.State = CFG_SETTING_STATE_EXPERIMENTAL
} else {
entry.State = CFG_SETTING_STATE_GOOD
}
stateVal, stateExist := vals["state"]
if stateExist {
if entry.State != CFG_SETTING_STATE_GOOD {
util.OneTimeWarning("Setting %s has duplicated state definition, using \"state\".", name)
}
switch stringValue(stateVal) {
case "defunct":
entry.State = CFG_SETTING_STATE_DEFUNCT
case "deprecated":
entry.State = CFG_SETTING_STATE_DEPRECATED
case "experimental":
entry.State = CFG_SETTING_STATE_EXPERIMENTAL
default:
util.OneTimeWarning("Invalid \"state\" for setting %s, assuming regular state.", name)
}
}
// The value field for setting definition is required.
valueVal, valueExist := vals["value"]
if valueExist {
entry.Value = stringValue(valueVal)
} else if entry.State == CFG_SETTING_STATE_DEFUNCT {
// defunct settings do not need default value, we only care if
// value was set anywhere and emit an error then
entry.Value = ""
} else {
return entry, util.FmtNewtError(
"setting %s does not have required value field", name)
}
if vals["type"] == nil {
entry.SettingType = CFG_SETTING_TYPE_RAW
} else {
var ok bool
typename := stringValue(vals["type"])
entry.SettingType, ok = cfgSettingNameTypeMap[typename]
if !ok {
return entry, util.FmtNewtError(
"setting %s specifies invalid type: %s", name, typename)
}
}
entry.appendValue(lpkg, entry.Value)
entry.Restrictions = []CfgRestriction{}
restrictionStrings := cast.ToStringSlice(vals["restrictions"])
for _, rstring := range restrictionStrings {
r, err := readRestriction(name, rstring)
if err != nil {
return entry,
util.PreNewtError(err, "error parsing setting %s", name)
}
entry.Restrictions = append(entry.Restrictions, r)
}
if vals["choices"] != nil && vals["range"] != nil {
return entry, util.FmtNewtError(
"setting %s uses both choice and range restrictions", name)
}
if vals["choices"] != nil {
var choices []string
switch vals["choices"].(type) {
default:
choices = cast.ToStringSlice(vals["choices"])
case string:
choices = strings.Split(vals["choices"].(string), ",")
}
entry.ValidChoices = choices
sort.Slice(choices, func(a, b int) bool {
return strings.ToLower(choices[a]) < strings.ToLower(choices[b])
})
for i, choice := range choices {
if !cfgChoiceValRe.MatchString(choice) {
return entry, util.FmtNewtError(
"setting %s has invalid choice defined (%s) - "+
"only letters, numbers and underscore are allowed", name, choice)
}
if i > 0 && strings.ToLower(choices[i-1]) == strings.ToLower(choice) {
return entry, util.FmtNewtError(
"setting %s has duplicated choice defined ('%s' and '%s')",
name, choice, choices[i-1])
}
}
r := CfgRestriction{
BaseSetting: name,
Code: CFG_RESTRICTION_CODE_CHOICE,
}
entry.Restrictions = append(entry.Restrictions, r)
}
if vals["range"] != nil {
r, err := createRangeRestriction(name, stringValue(vals["range"]))
if err != nil {
return entry,
util.PreNewtError(err, "error parsing setting %s", name)
}
entry.Restrictions = append(entry.Restrictions, r)
}
return entry, nil
}