github.com/theliebeskind/genfig@v0.1.5-alpha/writers/config.go (about) 1 package writers 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "strings" 8 9 "github.com/imdario/mergo" 10 11 "github.com/theliebeskind/genfig/models" 12 13 "github.com/theliebeskind/genfig/util" 14 u "github.com/theliebeskind/genfig/util" 15 ) 16 17 //WriteConfig writes 18 func WriteConfig(w io.Writer, s models.SchemaMap, config map[string]interface{}, def map[string]interface{}, env string) (err error) { 19 defer func() { 20 if r := recover(); r != nil { 21 err = u.RecoverError(r) 22 return 23 } 24 }() 25 26 // first write into buffer, so that no gobbledygook is written 27 // into some files, when someting panics 28 buf := bytes.NewBuffer([]byte{}) 29 30 // assigns this config to the according child of the global 'Envs' var 31 // via an init function 32 buf.Write(u.B("func init() {" + nl + indent + "Envs." + strings.Title(env) + " = ")) 33 34 // write actual config 35 WriteConfigValue(buf, defaultSchemaRootName, def, config, s, 1) 36 37 merged := def 38 if err := mergo.Merge(&merged, config, mergo.WithOverride); err != nil { 39 panic(err) 40 } 41 buf.Write(u.B(nl + indent + "Envs." + strings.Title(env) + "._map = " + fmt.Sprintf("%#v", merged))) 42 43 // closing bracket of init func 44 buf.Write(u.B(nl + "}" + nl)) 45 46 // now write buffer to writer 47 w.Write(buf.Bytes()) 48 49 return 50 } 51 52 //WriteConfigLine writes 53 func WriteConfigLine(w io.Writer, p string, k string, v interface{}, o interface{}, s models.SchemaMap, l int) { 54 if l > maxLevel { 55 panic(fmt.Errorf("Maximum of %d levels exceeded", maxLevel)) 56 } 57 58 n := strings.Title(k) 59 60 if _, ex := s[p+n]; !ex { 61 panic(fmt.Errorf("Config property '%s' is not defined in the default config", p+n)) 62 } 63 64 w.Write(u.B(indents[:l*len(indent)])) 65 w.Write(u.B(n + ": ")) 66 67 WriteConfigValue(w, p+n, v, o, s, l) 68 69 w.Write(u.B("," + nl)) 70 } 71 72 //WriteConfigValue writes 73 func WriteConfigValue(w io.Writer, p string, v interface{}, o interface{}, s models.SchemaMap, l int) { 74 switch v.(type) { 75 case map[string]interface{}: 76 w.Write(u.B(p + "{" + nl)) 77 for _k, _v := range v.(map[string]interface{}) { 78 _o := getOverwriteEntry(o, _k) 79 WriteConfigLine(w, p, _k, _v, _o, s, l+1) 80 } 81 w.Write(u.B(indents[:l*len(indent)])) 82 w.Write(u.B("}")) 83 case map[interface{}]interface{}: 84 w.Write(u.B(p + "{" + nl)) 85 for _k, _v := range v.(map[interface{}]interface{}) { 86 _o := getOverwriteEntry(o, _k) 87 WriteConfigLine(w, p, fmt.Sprintf("%v", _k), _v, _o, s, l+1) 88 } 89 w.Write(u.B(indents[:l*len(indent)])) 90 w.Write(u.B("}")) 91 case []interface{}: 92 t := &v 93 if o != nil { 94 t = &o 95 } 96 typ := util.DetectSliceTypeString((*t).([]interface{})) 97 w.Write(u.B(strings.Replace(fmt.Sprintf("%#v", *t), "[]interface {}", typ, 1))) 98 default: 99 t := &v 100 if o != nil { 101 t = &o 102 } 103 fmt.Fprintf(w, `%#v`, *t) 104 } 105 } 106 107 func getOverwriteEntry(o interface{}, k interface{}) (r interface{}) { 108 if o == nil { 109 return 110 } 111 switch o.(type) { 112 case map[string]interface{}: 113 r = o.(map[string]interface{})[fmt.Sprintf("%v", k)] 114 case map[interface{}]interface{}: 115 r = o.(map[interface{}]interface{})[k] 116 } 117 return 118 }