14114018 by astaxie

config ini support include

1 parent 8ac2b9bf
...@@ -88,13 +88,13 @@ type beegoAppConfig struct { ...@@ -88,13 +88,13 @@ type beegoAppConfig struct {
88 innerConfig config.ConfigContainer 88 innerConfig config.ConfigContainer
89 } 89 }
90 90
91 func newAppConfig(AppConfigProvider, AppConfigPath string) *beegoAppConfig { 91 func newAppConfig(AppConfigProvider, AppConfigPath string) (*beegoAppConfig, error) {
92 ac, err := config.NewConfig(AppConfigProvider, AppConfigPath) 92 ac, err := config.NewConfig(AppConfigProvider, AppConfigPath)
93 if err != nil { 93 if err != nil {
94 ac = config.NewFakeConfig() 94 return nil, err
95 } 95 }
96 rac := &beegoAppConfig{ac} 96 rac := &beegoAppConfig{ac}
97 return rac 97 return rac, nil
98 } 98 }
99 99
100 func (b *beegoAppConfig) Set(key, val string) error { 100 func (b *beegoAppConfig) Set(key, val string) error {
...@@ -281,15 +281,19 @@ func init() { ...@@ -281,15 +281,19 @@ func init() {
281 err = ParseConfig() 281 err = ParseConfig()
282 if err != nil && !os.IsNotExist(err) { 282 if err != nil && !os.IsNotExist(err) {
283 // for init if doesn't have app.conf will not panic 283 // for init if doesn't have app.conf will not panic
284 Info(err) 284 ac := config.NewFakeConfig()
285 AppConfig = &beegoAppConfig{ac}
286 Warning(err)
285 } 287 }
286 } 288 }
287 289
288 // ParseConfig parsed default config file. 290 // ParseConfig parsed default config file.
289 // now only support ini, next will support json. 291 // now only support ini, next will support json.
290 func ParseConfig() (err error) { 292 func ParseConfig() (err error) {
291 AppConfig = newAppConfig(AppConfigProvider, AppConfigPath) 293 AppConfig, err = newAppConfig(AppConfigProvider, AppConfigPath)
292 294 if err != nil {
295 return err
296 }
293 envRunMode := os.Getenv("BEEGO_RUNMODE") 297 envRunMode := os.Getenv("BEEGO_RUNMODE")
294 // set the runmode first 298 // set the runmode first
295 if envRunMode != "" { 299 if envRunMode != "" {
......
...@@ -48,6 +48,10 @@ type IniConfig struct { ...@@ -48,6 +48,10 @@ type IniConfig struct {
48 48
49 // ParseFile creates a new Config and parses the file configuration from the named file. 49 // ParseFile creates a new Config and parses the file configuration from the named file.
50 func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { 50 func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
51 return ini.parseFile(name)
52 }
53
54 func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
51 file, err := os.Open(name) 55 file, err := os.Open(name)
52 if err != nil { 56 if err != nil {
53 return nil, err 57 return nil, err
...@@ -66,6 +70,7 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { ...@@ -66,6 +70,7 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
66 70
67 var comment bytes.Buffer 71 var comment bytes.Buffer
68 buf := bufio.NewReader(file) 72 buf := bufio.NewReader(file)
73 // check the BOM
69 head, err := buf.Peek(3) 74 head, err := buf.Peek(3)
70 if err == nil && head[0] == 239 && head[1] == 187 && head[2] == 191 { 75 if err == nil && head[0] == 239 && head[1] == 187 && head[2] == 191 {
71 for i := 1; i <= 3; i++ { 76 for i := 1; i <= 3; i++ {
...@@ -114,13 +119,48 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { ...@@ -114,13 +119,48 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
114 cfg.data[section] = make(map[string]string) 119 cfg.data[section] = make(map[string]string)
115 } 120 }
116 keyValue := bytes.SplitN(line, bEqual, 2) 121 keyValue := bytes.SplitN(line, bEqual, 2)
122
123 key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive
124 key = strings.ToLower(key)
125
126 // handle include "other.conf"
127 if len(keyValue) == 1 && strings.HasPrefix(key, "include") {
128 includefiles := strings.Fields(key)
129 if includefiles[0] == "include" && len(includefiles) == 2 {
130 otherfile := strings.Trim(includefiles[1], "\"")
131 if !path.IsAbs(otherfile) {
132 otherfile = path.Join(path.Dir(name), otherfile)
133 }
134 i, err := ini.parseFile(otherfile)
135 if err != nil {
136 return nil, err
137 }
138 for sec, dt := range i.data {
139 if _, ok := cfg.data[sec]; !ok {
140 cfg.data[sec] = make(map[string]string)
141 }
142 for k, v := range dt {
143 cfg.data[sec][k] = v
144 }
145 }
146 for sec, comm := range i.sectionComment {
147 cfg.sectionComment[sec] = comm
148 }
149 for k, comm := range i.keyComment {
150 cfg.keyComment[k] = comm
151 }
152 continue
153 }
154 }
155
156 if len(keyValue) != 2 {
157 return nil, errors.New("read the content error: \"" + string(line) + "\", should key = val")
158 }
117 val := bytes.TrimSpace(keyValue[1]) 159 val := bytes.TrimSpace(keyValue[1])
118 if bytes.HasPrefix(val, bDQuote) { 160 if bytes.HasPrefix(val, bDQuote) {
119 val = bytes.Trim(val, `"`) 161 val = bytes.Trim(val, `"`)
120 } 162 }
121 163
122 key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive
123 key = strings.ToLower(key)
124 cfg.data[section][key] = string(val) 164 cfg.data[section][key] = string(val)
125 if comment.Len() > 0 { 165 if comment.Len() > 0 {
126 cfg.keyComment[section+"."+key] = comment.String() 166 cfg.keyComment[section+"."+key] = comment.String()
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!