From 14114018eac32b2a6501f8c76defa86fdcb76aa1 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 24 Oct 2014 19:03:27 +0800 Subject: [PATCH] config ini support include --- config.go | 16 ++++++++++------ config/ini.go | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/config.go b/config.go index 6fd35d8c..84f8cf39 100644 --- a/config.go +++ b/config.go @@ -88,13 +88,13 @@ type beegoAppConfig struct { innerConfig config.ConfigContainer } -func newAppConfig(AppConfigProvider, AppConfigPath string) *beegoAppConfig { +func newAppConfig(AppConfigProvider, AppConfigPath string) (*beegoAppConfig, error) { ac, err := config.NewConfig(AppConfigProvider, AppConfigPath) if err != nil { - ac = config.NewFakeConfig() + return nil, err } rac := &beegoAppConfig{ac} - return rac + return rac, nil } func (b *beegoAppConfig) Set(key, val string) error { @@ -281,15 +281,19 @@ func init() { err = ParseConfig() if err != nil && !os.IsNotExist(err) { // for init if doesn't have app.conf will not panic - Info(err) + ac := config.NewFakeConfig() + AppConfig = &beegoAppConfig{ac} + Warning(err) } } // ParseConfig parsed default config file. // now only support ini, next will support json. func ParseConfig() (err error) { - AppConfig = newAppConfig(AppConfigProvider, AppConfigPath) - + AppConfig, err = newAppConfig(AppConfigProvider, AppConfigPath) + if err != nil { + return err + } envRunMode := os.Getenv("BEEGO_RUNMODE") // set the runmode first if envRunMode != "" { diff --git a/config/ini.go b/config/ini.go index e8afecb6..837c9ffe 100644 --- a/config/ini.go +++ b/config/ini.go @@ -48,6 +48,10 @@ type IniConfig struct { // ParseFile creates a new Config and parses the file configuration from the named file. func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { + return ini.parseFile(name) +} + +func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) { file, err := os.Open(name) if err != nil { return nil, err @@ -66,6 +70,7 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { var comment bytes.Buffer buf := bufio.NewReader(file) + // check the BOM head, err := buf.Peek(3) if err == nil && head[0] == 239 && head[1] == 187 && head[2] == 191 { for i := 1; i <= 3; i++ { @@ -114,13 +119,48 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { cfg.data[section] = make(map[string]string) } keyValue := bytes.SplitN(line, bEqual, 2) + + key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive + key = strings.ToLower(key) + + // handle include "other.conf" + if len(keyValue) == 1 && strings.HasPrefix(key, "include") { + includefiles := strings.Fields(key) + if includefiles[0] == "include" && len(includefiles) == 2 { + otherfile := strings.Trim(includefiles[1], "\"") + if !path.IsAbs(otherfile) { + otherfile = path.Join(path.Dir(name), otherfile) + } + i, err := ini.parseFile(otherfile) + if err != nil { + return nil, err + } + for sec, dt := range i.data { + if _, ok := cfg.data[sec]; !ok { + cfg.data[sec] = make(map[string]string) + } + for k, v := range dt { + cfg.data[sec][k] = v + } + } + for sec, comm := range i.sectionComment { + cfg.sectionComment[sec] = comm + } + for k, comm := range i.keyComment { + cfg.keyComment[k] = comm + } + continue + } + } + + if len(keyValue) != 2 { + return nil, errors.New("read the content error: \"" + string(line) + "\", should key = val") + } val := bytes.TrimSpace(keyValue[1]) if bytes.HasPrefix(val, bDQuote) { val = bytes.Trim(val, `"`) } - key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive - key = strings.ToLower(key) cfg.data[section][key] = string(val) if comment.Len() > 0 { cfg.keyComment[section+"."+key] = comment.String()