package main import ( "errors" "fmt" "github.com/yuin/gopher-lua" ) // Server holds information about a Gitea server. type Server struct { servername string url string username string token string primary bool } // Servers holds all of the server structures. type Servers map[string]*Server // getPrimary gets the primary server contained in this map. Returns an error if no primary server is defined. func (servers *Servers) getPrimary() (*Server, error) { for _, s := range *servers { if s.primary { return s, nil } } return &Server{}, errors.New("No primary server found.") } // Configuration holds data retrieved from a Lua script. type Configuration struct { servers Servers } // getStringFromTable parses a text value from the configuration file. func getStringFromTable(L *lua.LState, lobj lua.LValue, key string, out *string) error { lv := L.GetTable(lobj, lua.LString(key)) if text, ok := lv.(lua.LString); ok { *out = string(text) } else { return errors.New("Text is not a string!") } return nil } // getBoolFromTable parses a boolean value from the configuration file. func getBoolFromTable(L *lua.LState, lobj lua.LValue, key string, out *bool) error { lv := L.GetTable(lobj, lua.LString(key)) if val, ok := lv.(lua.LBool); ok { *out = bool(val) } else { return errors.New(fmt.Sprintf("Failed to get configuration value '%s'", key)) } return nil } // parseServerFromTable parses a Lua table into a Server structure. func parseServerFromTable(L *lua.LState, table lua.LValue) (Server, error) { server := Server{} if err := getStringFromTable(L, table, "servername", &server.servername); err != nil { return server, err } if err := getStringFromTable(L, table, "username", &server.username); err != nil { return server, err } if err := getStringFromTable(L, table, "token", &server.token); err != nil { return server, err } if err := getStringFromTable(L, table, "url", &server.url); err != nil { return server, err } lv := L.GetTable(table, lua.LString("primary")) if val, ok := lv.(lua.LBool); ok { server.primary = bool(val) } else if _, ok := lv.(*lua.LNilType); !ok { panic("Config error : " + server.servername + " : Primary is neither nil nor boolean") } return server, nil } // Configuration.Parse parses a Lua configuration file into a Configuration struct. func (config *Configuration) Parse(fname string) error { config.servers = make(map[string]*Server) L := lua.NewState() defer L.Close() L.DoFile(fname) table := L.Get(-1) found_primary := false for i := 1; i <= L.ObjLen(table); i++ { lserver := L.GetTable(table, lua.LNumber(i)) if server, err := parseServerFromTable(L, lserver); err == nil { if !found_primary && server.primary { found_primary = true } else if server.primary { panic("Config error : " + server.servername + " : Cannot have multiple primary servers!") } config.servers[server.servername] = &server } else { return err } } return nil }