gen.go (4915B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package main 19 20 import ( 21 "flag" 22 "fmt" 23 "io" 24 "os" 25 "os/exec" 26 "reflect" 27 "strings" 28 29 "github.com/superseriousbusiness/gotosocial/internal/config" 30 ) 31 32 const license = `// GoToSocial 33 // Copyright (C) GoToSocial Authors admin@gotosocial.org 34 // SPDX-License-Identifier: AGPL-3.0-or-later 35 // 36 // This program is free software: you can redistribute it and/or modify 37 // it under the terms of the GNU Affero General Public License as published by 38 // the Free Software Foundation, either version 3 of the License, or 39 // (at your option) any later version. 40 // 41 // This program is distributed in the hope that it will be useful, 42 // but WITHOUT ANY WARRANTY; without even the implied warranty of 43 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 44 // GNU Affero General Public License for more details. 45 // 46 // You should have received a copy of the GNU Affero General Public License 47 // along with this program. If not, see <http://www.gnu.org/licenses/>. 48 49 ` 50 51 func main() { 52 var out string 53 54 // Load runtime config flags 55 flag.StringVar(&out, "out", "", "Generated file output path") 56 flag.Parse() 57 58 // Open output file path 59 output, err := os.OpenFile(out, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644) 60 if err != nil { 61 panic(err) 62 } 63 64 fmt.Fprint(output, "// THIS IS A GENERATED FILE, DO NOT EDIT BY HAND\n") 65 fmt.Fprint(output, license) 66 fmt.Fprint(output, "package config\n\n") 67 fmt.Fprint(output, "import (\n") 68 fmt.Fprint(output, "\t\"time\"\n\n") 69 fmt.Fprint(output, "\t\"codeberg.org/gruf/go-bytesize\"\n") 70 fmt.Fprint(output, ")\n\n") 71 generateFields(output, nil, reflect.TypeOf(config.Configuration{})) 72 _ = output.Close() 73 _ = exec.Command("gofumports", "-w", out).Run() 74 75 // The plan here is that eventually we might be able 76 // to generate an example configuration from struct tags 77 } 78 79 func generateFields(output io.Writer, prefixes []string, t reflect.Type) { 80 for i := 0; i < t.NumField(); i++ { 81 field := t.Field(i) 82 83 if ft := field.Type; ft.Kind() == reflect.Struct { 84 // This is a struct field containing further nested config vars. 85 generateFields(output, append(prefixes, field.Name), ft) 86 continue 87 } 88 89 // Get prefixed config variable name 90 name := strings.Join(prefixes, "") + field.Name 91 92 // Get period-separated (if nested) config variable "path" 93 fieldPath := strings.Join(append(prefixes, field.Name), ".") 94 95 // Get dash-separated config variable CLI flag "path" 96 flagPath := strings.Join(append(prefixes, field.Tag.Get("name")), "-") 97 flagPath = strings.ToLower(flagPath) 98 99 // ConfigState structure helper methods 100 fmt.Fprintf(output, "// Get%s safely fetches the Configuration value for state's '%s' field\n", name, fieldPath) 101 fmt.Fprintf(output, "func (st *ConfigState) Get%s() (v %s) {\n", name, field.Type.String()) 102 fmt.Fprintf(output, "\tst.mutex.Lock()\n") 103 fmt.Fprintf(output, "\tv = st.config.%s\n", fieldPath) 104 fmt.Fprintf(output, "\tst.mutex.Unlock()\n") 105 fmt.Fprintf(output, "\treturn\n") 106 fmt.Fprintf(output, "}\n\n") 107 fmt.Fprintf(output, "// Set%s safely sets the Configuration value for state's '%s' field\n", name, fieldPath) 108 fmt.Fprintf(output, "func (st *ConfigState) Set%s(v %s) {\n", name, field.Type.String()) 109 fmt.Fprintf(output, "\tst.mutex.Lock()\n") 110 fmt.Fprintf(output, "\tdefer st.mutex.Unlock()\n") 111 fmt.Fprintf(output, "\tst.config.%s = v\n", fieldPath) 112 fmt.Fprintf(output, "\tst.reloadToViper()\n") 113 fmt.Fprintf(output, "}\n\n") 114 115 // Global ConfigState helper methods 116 // TODO: remove when we pass around a ConfigState{} 117 fmt.Fprintf(output, "// %sFlag returns the flag name for the '%s' field\n", name, fieldPath) 118 fmt.Fprintf(output, "func %sFlag() string { return \"%s\" }\n\n", name, flagPath) 119 fmt.Fprintf(output, "// Get%s safely fetches the value for global configuration '%s' field\n", name, fieldPath) 120 fmt.Fprintf(output, "func Get%[1]s() %[2]s { return global.Get%[1]s() }\n\n", name, field.Type.String()) 121 fmt.Fprintf(output, "// Set%s safely sets the value for global configuration '%s' field\n", name, fieldPath) 122 fmt.Fprintf(output, "func Set%[1]s(v %[2]s) { global.Set%[1]s(v) }\n\n", name, field.Type.String()) 123 } 124 }