format hook

This commit is contained in:
Roy Olav Purser 2021-03-26 17:17:52 +01:00
parent 002ab7d205
commit 46207396ef
No known key found for this signature in database
GPG Key ID: 0BA77797F072BC52
5 changed files with 258 additions and 245 deletions

3
.hooks/pre-commit Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
go fmt *.go
git add *.go

View File

@ -1,37 +1,41 @@
package envconf package envconf
import ("time")
import (
"time"
)
type DataType int type DataType int
const ( const (
TypeNone DataType = iota TypeNone DataType = iota
TypeInt DataType = iota TypeInt DataType = iota
TypeMetric DataType = iota TypeMetric DataType = iota
TypeDuration DataType = iota TypeDuration DataType = iota
TypeString DataType = iota TypeString DataType = iota
TypeDirectory DataType = iota TypeDirectory DataType = iota
TypeBool DataType = iota TypeBool DataType = iota
) )
type cValue struct { type cValue struct {
dtype DataType dtype DataType
intval int64 intval int64
durval time.Duration durval time.Duration
boolval bool boolval bool
strval string strval string
err error err error
} }
func (dtype DataType) parse(key string, str string)(ret cValue) { func (dtype DataType) parse(key string, str string) (ret cValue) {
info, ok := tInfo[dtype] info, ok := tInfo[dtype]
if ok { if ok {
return info.parser(key, str) return info.parser(key, str)
} }
return return
} }
func (dtype DataType) String()(string) { func (dtype DataType) String() string {
info, ok := tInfo[dtype] info, ok := tInfo[dtype]
if ok { if ok {
return info.name return info.name
} }
return "invalid" return "invalid"
} }

View File

@ -1,186 +1,188 @@
package envconf package envconf
import ("strings" import (
"unicode" "errors"
"errors" "fmt"
"time" "os"
"fmt" "strings"
"os") "time"
"unicode"
)
type cEntry struct { type cEntry struct {
value string value string
parsed cValue parsed cValue
dtype DataType dtype DataType
unset bool unset bool
empty bool empty bool
} }
type Config struct { type Config struct {
parsed bool parsed bool
env map[string]cEntry env map[string]cEntry
} }
// NewConfig returns an envconf.Config that is used to read configuration from environment variables. // NewConfig returns an envconf.Config that is used to read configuration from environment variables.
// The environment variables are stored in envconf.Config, so changes to the environment after NewConfig has been called // The environment variables are stored in envconf.Config, so changes to the environment after NewConfig has been called
// will not be taken into account. // will not be taken into account.
func NewConfig()(*Config) { func NewConfig() *Config {
config := new(Config) config := new(Config)
config.parsed = false config.parsed = false
config.env = make(map[string]cEntry) config.env = make(map[string]cEntry)
for _,v := range os.Environ() { for _, v := range os.Environ() {
splitted := strings.SplitN(v, "=", 2) splitted := strings.SplitN(v, "=", 2)
if len(splitted) == 2 { if len(splitted) == 2 {
key := strings.TrimSpace(strings.ToUpper(splitted[0])) key := strings.TrimSpace(strings.ToUpper(splitted[0]))
if unicode.IsLetter(getFirstRune(key)) { if unicode.IsLetter(getFirstRune(key)) {
var entry cEntry var entry cEntry
entry.value = splitted[1] entry.value = splitted[1]
entry.dtype = TypeNone entry.dtype = TypeNone
entry.unset = false entry.unset = false
entry.empty = false entry.empty = false
config.env[key] = entry config.env[key] = entry
} }
} }
} }
return config return config
} }
// Define defines the type of an environment variable. // Define defines the type of an environment variable.
// Variables without a defined type will be ignored by Parse. // Variables without a defined type will be ignored by Parse.
func (c *Config) Define(key string, dtype DataType) { func (c *Config) Define(key string, dtype DataType) {
upper := strings.ToUpper(key) upper := strings.ToUpper(key)
entry, ok := c.env[upper] entry, ok := c.env[upper]
if ok { if ok {
entry.dtype = dtype entry.dtype = dtype
c.env[upper] = entry c.env[upper] = entry
} else { } else {
var entry cEntry var entry cEntry
entry.dtype = dtype entry.dtype = dtype
entry.unset = true entry.unset = true
entry.empty = true entry.empty = true
c.env[upper] = entry c.env[upper] = entry
} }
} }
// DefineDefault defines the type and default value of an environment variable. // DefineDefault defines the type and default value of an environment variable.
// Variables without a defined type will be ignored by Parse. // Variables without a defined type will be ignored by Parse.
func (c *Config) DefineDefault(key string, val string, dtype DataType) { func (c *Config) DefineDefault(key string, val string, dtype DataType) {
upper := strings.ToUpper(key) upper := strings.ToUpper(key)
entry, ok := c.env[upper] entry, ok := c.env[upper]
if ok { if ok {
if entry.unset { if entry.unset {
entry.value = val entry.value = val
} }
entry.dtype = dtype entry.dtype = dtype
entry.empty = false entry.empty = false
c.env[upper] = entry c.env[upper] = entry
} else { } else {
var entry cEntry var entry cEntry
entry.dtype = dtype entry.dtype = dtype
entry.unset = true entry.unset = true
entry.empty = false entry.empty = false
entry.value = val entry.value = val
c.env[upper] = entry c.env[upper] = entry
} }
} }
// Parse parses the environment variables previously defined by Define and DefineDefault. // Parse parses the environment variables previously defined by Define and DefineDefault.
// Parse should only be called once for a given envconf.Config. // Parse should only be called once for a given envconf.Config.
func (c *Config) Parse() { func (c *Config) Parse() {
if c.parsed { if c.parsed {
return return
} }
c.parsed = true c.parsed = true
for k,v := range c.env { for k, v := range c.env {
if v.empty { if v.empty {
if v.unset { if v.unset {
v.parsed.err = errors.New(fmt.Sprintf(`Environment variable "%s" not found. It should have been of type %s.`, k, v.dtype)) v.parsed.err = errors.New(fmt.Sprintf(`Environment variable "%s" not found. It should have been of type %s.`, k, v.dtype))
c.env[k] = v c.env[k] = v
} }
} else { } else {
v.parsed = v.dtype.parse(k, v.value) v.parsed = v.dtype.parse(k, v.value)
c.env[k] = v c.env[k] = v
} }
} }
} }
// Status prints out failures that occured while parsing the environment to os.Stderr. // Status prints out failures that occured while parsing the environment to os.Stderr.
// Variables that have been defined without a default value and are // Variables that have been defined without a default value and are
// missing from the environment will be considered a failure. // missing from the environment will be considered a failure.
// If parsing of any of the variables has failed Status will return false. // If parsing of any of the variables has failed Status will return false.
func (c *Config) Status()(ok bool) { func (c *Config) Status() (ok bool) {
ok = c.parsed ok = c.parsed
if ok { if ok {
for _,v := range c.env { for _, v := range c.env {
err := v.parsed.err err := v.parsed.err
if err != nil { if err != nil {
ok = false ok = false
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
} }
} }
} }
return return
} }
func (c *Config) getRaw(key string, dtype DataType)(val cValue) { func (c *Config) getRaw(key string, dtype DataType) (val cValue) {
val.dtype = TypeNone val.dtype = TypeNone
if c.parsed { if c.parsed {
upper := strings.ToUpper(key) upper := strings.ToUpper(key)
entry, ok := c.env[upper] entry, ok := c.env[upper]
if ok && (entry.dtype == dtype) { if ok && (entry.dtype == dtype) {
return entry.parsed return entry.parsed
} }
} }
return return
} }
// GetInt returns the value of an environment variable. // GetInt returns the value of an environment variable.
// If the variable is not defined as envconf.TypeInt the function will return 0. // If the variable is not defined as envconf.TypeInt the function will return 0.
func (c *Config) GetInt(key string)(int64) { func (c *Config) GetInt(key string) int64 {
val := c.getRaw(key, TypeInt) val := c.getRaw(key, TypeInt)
return val.intval return val.intval
} }
// GetMetric returns the value of an environment variable. // GetMetric returns the value of an environment variable.
// If the variable is not defined as envconf.TypeMetric the function will return 0. // If the variable is not defined as envconf.TypeMetric the function will return 0.
func (c *Config) GetMetric(key string)(int64) { func (c *Config) GetMetric(key string) int64 {
val := c.getRaw(key, TypeMetric) val := c.getRaw(key, TypeMetric)
return val.intval return val.intval
} }
// GetDirectory returns the value of an environment variable. // GetDirectory returns the value of an environment variable.
// If the variable is not defined as envconf.TypeDirectory the // If the variable is not defined as envconf.TypeDirectory the
// function will return the empty string. // function will return the empty string.
func (c *Config) GetDirectory(key string)(string) { func (c *Config) GetDirectory(key string) string {
val := c.getRaw(key, TypeDirectory) val := c.getRaw(key, TypeDirectory)
return val.strval return val.strval
} }
// GetString returns the value of an environment variable. // GetString returns the value of an environment variable.
// If the variable is not defined as envconf.TypeString the // If the variable is not defined as envconf.TypeString the
// function will return the empty string. // function will return the empty string.
func (c *Config) GetString(key string)(string) { func (c *Config) GetString(key string) string {
val := c.getRaw(key, TypeString) val := c.getRaw(key, TypeString)
return val.strval return val.strval
} }
// GetDuration returns the value of an environment variable. // GetDuration returns the value of an environment variable.
// If the variable is not defined as envconf.TypeDuration the // If the variable is not defined as envconf.TypeDuration the
// function will return time.Duration(0). // function will return time.Duration(0).
func (c *Config) GetDuration(key string)(time.Duration) { func (c *Config) GetDuration(key string) time.Duration {
val := c.getRaw(key, TypeDuration) val := c.getRaw(key, TypeDuration)
return val.durval return val.durval
} }
// GetBool returns the value of an environment variable. // GetBool returns the value of an environment variable.
// If the variable is not defined as envconf.TypeBool the // If the variable is not defined as envconf.TypeBool the
// function will return false. // function will return false.
func (c *Config) GetBool(key string)(bool) { func (c *Config) GetBool(key string) bool {
val := c.getRaw(key, TypeBool) val := c.getRaw(key, TypeBool)
return val.boolval return val.boolval
} }
func getFirstRune(str string)(rune) { func getFirstRune(str string) rune {
for _,v := range str { for _, v := range str {
return v return v
} }
return rune(0) return rune(0)
} }

View File

@ -1,84 +1,85 @@
package envconf package envconf
import ("strconv"
"strings"
"fmt"
"errors"
"os"
"path"
"time")
func parseInt(key string, str string)(ret cValue) { import (
val, err := strconv.ParseInt(str, 10, 64) "errors"
if err == nil { "fmt"
ret.intval = val "os"
} else { "path"
ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type int.`, key)) "strconv"
} "strings"
return "time"
)
func parseInt(key string, str string) (ret cValue) {
val, err := strconv.ParseInt(str, 10, 64)
if err == nil {
ret.intval = val
} else {
ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type int.`, key))
}
return
} }
func parseMetric(key string, str string)(ret cValue) { func parseMetric(key string, str string) (ret cValue) {
mod := int64(1) mod := int64(1)
str = strings.ToUpper(str) str = strings.ToUpper(str)
if strings.HasSuffix(str, "K") { if strings.HasSuffix(str, "K") {
mod = 1024 mod = 1024
str = strings.TrimSuffix(str, "K") str = strings.TrimSuffix(str, "K")
} else if strings.HasSuffix(str, "M") { } else if strings.HasSuffix(str, "M") {
mod = 1024 * 1024 mod = 1024 * 1024
str = strings.TrimSuffix(str, "M") str = strings.TrimSuffix(str, "M")
} else if strings.HasSuffix(str, "G") { } else if strings.HasSuffix(str, "G") {
mod = 1024 * 1024 * 1024 mod = 1024 * 1024 * 1024
str = strings.TrimSuffix(str, "G") str = strings.TrimSuffix(str, "G")
} else if strings.HasSuffix(str, "T") { } else if strings.HasSuffix(str, "T") {
mod = 1024 * 1024 * 1024 * 1024 mod = 1024 * 1024 * 1024 * 1024
str = strings.TrimSuffix(str, "T") str = strings.TrimSuffix(str, "T")
} }
val, err := strconv.ParseInt(str, 10, 64) val, err := strconv.ParseInt(str, 10, 64)
if err == nil { if err == nil {
ret.intval = mod * val ret.intval = mod * val
} else { } else {
ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type int.`, key)) ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type int.`, key))
} }
return return
} }
func parseDuration(key string, str string)(ret cValue) { func parseDuration(key string, str string) (ret cValue) {
val, err := time.ParseDuration(str) val, err := time.ParseDuration(str)
if err == nil { if err == nil {
ret.durval = val ret.durval = val
} else { } else {
ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type duration.`, key)) ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type duration.`, key))
} }
return return
} }
func parseBool(key string, str string)(ret cValue) { func parseBool(key string, str string) (ret cValue) {
val, err := strconv.ParseBool(str) val, err := strconv.ParseBool(str)
if err == nil { if err == nil {
ret.boolval = val ret.boolval = val
} else { } else {
ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type bool.`, key)) ret.err = errors.New(fmt.Sprintf(`Environment variable "%s" is not of type bool.`, key))
} }
return return
} }
func parseDirectory(_ string, str string)(ret cValue) { func parseDirectory(_ string, str string) (ret cValue) {
wd, err := os.Getwd() wd, err := os.Getwd()
if err == nil { if err == nil {
if path.IsAbs(str) { if path.IsAbs(str) {
ret.strval = path.Clean(str) ret.strval = path.Clean(str)
} else { } else {
ret.strval = path.Join(wd, str) ret.strval = path.Join(wd, str)
} }
} else { } else {
ret.strval = path.Clean(str) ret.strval = path.Clean(str)
} }
return return
} }
func parseString(_ string, str string) (ret cValue) {
func parseString(_ string, str string)(ret cValue) { ret.strval = str
ret.strval = str return
return
} }

View File

@ -1,36 +1,39 @@
package envconf package envconf
type dataTypeInfo struct { type dataTypeInfo struct {
parser func(string,string)(cValue) parser func(string, string) cValue
name string name string
} }
var tInfo map[DataType]dataTypeInfo var tInfo map[DataType]dataTypeInfo
func init() { func init() {
tInfo = make(map[DataType]dataTypeInfo) tInfo = make(map[DataType]dataTypeInfo)
var intInfo dataTypeInfo var intInfo dataTypeInfo
var metricInfo dataTypeInfo var metricInfo dataTypeInfo
var durInfo dataTypeInfo var durInfo dataTypeInfo
var strInfo dataTypeInfo var strInfo dataTypeInfo
var dirInfo dataTypeInfo var dirInfo dataTypeInfo
var boolInfo dataTypeInfo var boolInfo dataTypeInfo
intInfo.name = "int" intInfo.name = "int"
metricInfo.name = "metric" metricInfo.name = "metric"
durInfo.name = "duration" durInfo.name = "duration"
dirInfo.name = "directory" dirInfo.name = "directory"
strInfo.name = "string" strInfo.name = "string"
boolInfo.name = "bool" boolInfo.name = "bool"
intInfo.parser = parseInt intInfo.parser = parseInt
metricInfo.parser = parseMetric metricInfo.parser = parseMetric
durInfo.parser = parseDuration durInfo.parser = parseDuration
dirInfo.parser = parseDirectory dirInfo.parser = parseDirectory
strInfo.parser = parseString strInfo.parser = parseString
boolInfo.parser = parseBool boolInfo.parser = parseBool
tInfo[TypeInt] = intInfo tInfo[TypeInt] = intInfo
tInfo[TypeMetric] = metricInfo tInfo[TypeMetric] = metricInfo
tInfo[TypeDuration] = durInfo tInfo[TypeDuration] = durInfo
tInfo[TypeString] = strInfo tInfo[TypeString] = strInfo
tInfo[TypeDirectory] = dirInfo tInfo[TypeDirectory] = dirInfo
tInfo[TypeBool] = boolInfo tInfo[TypeBool] = boolInfo
} }