From 4bf6f65377cc512f384939b501759c41e87a41a1 Mon Sep 17 00:00:00 2001 From: eschao Date: Tue, 12 Dec 2017 16:00:34 +0800 Subject: [PATCH] add comments --- cli/cli.go | 45 +++++++++++++++++++++++++++++++++++++++++---- cli/cli_test.go | 15 +++++++++++++++ config.go | 39 +++++++++++++++++++++++++++++++++++++++ config_test.go | 15 +++++++++++++++ env/env.go | 33 +++++++++++++++++++++++++++++++++ env/env_test.go | 15 +++++++++++++++ test/data.go | 15 +++++++++++++++ utils/utils.go | 15 +++++++++++++++ utils/utils_test.go | 15 +++++++++++++++ 9 files changed, 203 insertions(+), 4 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index 62d88cf..1f6dcab 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package cli import ( @@ -11,10 +26,13 @@ import ( "github.com/eschao/config/utils" ) +// anyValue wraps a reflect.Value object and implements flag.Value interface +// the reflect.Value could be Bool, String, Int, Uint and Float type anyValue struct { any reflect.Value } +// newAnyValue creates an anyValue object func newAnyValue(v reflect.Value) *anyValue { return &anyValue{any: v} } @@ -78,6 +96,8 @@ func (this *anyValue) Set(v string) error { return nil } +// sliceValue wraps a reflect.Value object and implements flag.Value interface +// the reflect.Value could only be a sliceable type type sliceValue struct { value reflect.Value separator string @@ -99,19 +119,26 @@ func (this *sliceValue) Set(v string) error { return utils.SetValueWithSlice(this.value, v, sp) } +// errorHanling is a global flag.ErrorHandling var errorHandling = flag.ExitOnError +// UsageFunc defines a callback function for printing command usage type UsageFunc func(*Command) func() +// usageHandler is a global UsageFunc callback, default is nil which means it +// will use default flag.Usage function var usageHandler UsageFunc = nil +// Command defines a command line structure type Command struct { - Name string - FlagSet *flag.FlagSet - Usage string - SubCommands map[string]*Command + Name string // command name + FlagSet *flag.FlagSet // command arguments + Usage string // command usage description + SubCommands map[string]*Command // sub-commands } +// New creates a command with given name, the command will use default +// ErrorHandling: flag.ExitOnError and default usage function: flag.Usage func New(name string) *Command { cmd := Command{ Name: name, @@ -122,6 +149,8 @@ func New(name string) *Command { return &cmd } +// NewWith creates a command with given name, error handling and customized +// usage function func NewWith(name string, errHandling flag.ErrorHandling, usageHandling UsageFunc) *Command { errorHandling = errHandling @@ -139,6 +168,9 @@ func NewWith(name string, errHandling flag.ErrorHandling, return &cmd } +// Init analyzes the given structure interface, extracts cli definitions from +// its tag and installs command flagset by flag APIs. The interface must be a +// structure pointer, otherwise will return an error func (this *Command) Init(i interface{}) error { ptrRef := reflect.ValueOf(i) @@ -156,6 +188,7 @@ func (this *Command) Init(i interface{}) error { return this.parseValue(valueOfStruct) } +// parseValue parses a reflect.Value object and extracts cli definitions func (this *Command) parseValue(v reflect.Value) error { typeOfStruct := v.Type() var err error @@ -181,6 +214,7 @@ func (this *Command) parseValue(v reflect.Value) error { return err } +// addFlag installs a command flag variable by flag API func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error { cmdTag, ok := f.Tag.Lookup("cli") if !ok || cmdTag == "" { @@ -226,6 +260,7 @@ func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error { return nil } +// createSubCommand creates sub-commands func (this *Command) createSubCommand(tag reflect.StructTag) *Command { cmdTag, ok := tag.Lookup("cli") if !ok || cmdTag == "" { @@ -253,6 +288,8 @@ func (this *Command) createSubCommand(tag reflect.StructTag) *Command { return &cmd } +// Parse parses values from command line and save values into given structure. +// The Init(interface{}) function must be called before parsing func (this *Command) Parse(args []string) error { if err := this.FlagSet.Parse(args); err != nil { return err diff --git a/cli/cli_test.go b/cli/cli_test.go index 81a0f0d..a240b6c 100644 --- a/cli/cli_test.go +++ b/cli/cli_test.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package cli import ( diff --git a/config.go b/config.go index d58af1a..865ea24 100644 --- a/config.go +++ b/config.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package config import ( @@ -15,6 +30,7 @@ import ( "gopkg.in/yaml.v2" ) +// Default configuration file const ( DefaultJSONConfig = "config.json" DefaultYamlConfig = "config.yaml" @@ -27,6 +43,10 @@ const ( PropConfigType = "properties" ) +// ParseDefault parses the given structure, extract default value from its tag +// and set structure with these values. +// Normally, ParseDefault should be called before any other parsing functions +// to set default values for structure. func ParseDefault(i interface{}) error { ptrRef := reflect.ValueOf(i) @@ -108,10 +128,13 @@ func parseValue(v reflect.Value) error { return err } +// ParseEnv parses given structure interface and set it with corresponding +// environment values func ParseEnv(i interface{}) error { return env.ParseWith(i, "") } +// ParseCli parses given structure interface and set it with command line input func ParseCli(i interface{}) error { cli := cli.New(os.Args[0]) if err := cli.Init(i); err != nil { @@ -123,11 +146,19 @@ func ParseCli(i interface{}) error { return nil } +// ParseConfig parses given structure interface and set it with default +// configuration file. +// configFlag is a command line flag to tell where to locate configure file. +// If the config file doesn't exist, the default config fill will be searched +// under the same folder with the fixed order: config.json, config.yaml and +// config.properties func ParseConfig(i interface{}, configFlag string) error { configFile := flag.String(configFlag, "", "Specifiy configuration file") return ParseConfigFile(i, *configFile) } +// ParseConfigFile parses given structure interface and set its value with +// the specified configuration file func ParseConfigFile(i interface{}, configFile string) error { var err error if configFile == "" { @@ -156,6 +187,7 @@ func ParseConfigFile(i interface{}, configFile string) error { return nil } +// parseJSON parses JSON file and set structure with its value func parseJSON(i interface{}, jsonFile string) error { raw, err := ioutil.ReadFile(jsonFile) if err != nil { @@ -165,6 +197,7 @@ func parseJSON(i interface{}, jsonFile string) error { return json.Unmarshal(raw, i) } +// parseYaml parses Yaml file and set structure with its value func parseYaml(i interface{}, yamlFile string) error { raw, err := ioutil.ReadFile(yamlFile) if err != nil { @@ -174,10 +207,14 @@ func parseYaml(i interface{}, yamlFile string) error { return yaml.Unmarshal(raw, i) } +// parseProp parses Properties file and set structure with its value func parseProp(i interface{}, propFile string) error { return fmt.Errorf("Properties config has not implemented!") } +// getDefaultConfigFile returns a existing default config file. The checking +// order is fixed with beginning from: config.json to config.yaml and +// config.properties func getDefaultConfigFile() (string, error) { exe, err := os.Executable() if err != nil { @@ -207,6 +244,8 @@ func getDefaultConfigFile() (string, error) { return "", fmt.Errorf("No default config file found in path: %s", path) } +// getConfigFileType analyzes config file extension name and return +// corresponding type: json, yaml or properties func getConfigFileType(configFile string) (string, error) { ext := filepath.Ext(configFile) if ext == ".json" { diff --git a/config_test.go b/config_test.go index 9e3df9d..67ddd07 100644 --- a/config_test.go +++ b/config_test.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package config import ( diff --git a/env/env.go b/env/env.go index cc5bf0f..98245b0 100644 --- a/env/env.go +++ b/env/env.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package env import ( @@ -8,10 +23,25 @@ import ( "github.com/eschao/config/utils" ) +// Parse parses given structure interface, extracts environment definitions +// from its tag and sets structure with defined environement variables func Parse(i interface{}) error { return ParseWith(i, "") } +// ParseWith parses with given structure interface and environment name prefix +// It is normally used in nested structure. +// For example: we have such structure +// type Database struct { +// Host string `env:"HOST"` +// } + +// type Server struct { +// Server string `env:"SERVER"` +// DB Database `env:"DB_"` +// } +// The Server.DB.Host will be mapped to environment variable: DB_HOST which is +// concatenated from DB tag in Server struct and Host tag in Database struct func ParseWith(i interface{}, prefix string) error { ptrRef := reflect.ValueOf(i) @@ -29,6 +59,7 @@ func ParseWith(i interface{}, prefix string) error { return parseValue(valueOfStruct, prefix) } +// parseValue parses a reflect.Value object func parseValue(v reflect.Value, prefix string) error { typeOfStruct := v.Type() var err error @@ -55,6 +86,7 @@ func parseValue(v reflect.Value, prefix string) error { return err } +// getEnvValue get environment value func getEnvValue(envName string, f reflect.StructField) (string, bool) { //fmt.Printf("Lookup ENV: %s\n", envName) envValue, ok := os.LookupEnv(envName) @@ -65,6 +97,7 @@ func getEnvValue(envName string, f reflect.StructField) (string, bool) { return envValue, ok } +// setFieldValue sets a reflect.Value with environment value func setFieldValue(v reflect.Value, f reflect.StructField, prefix string) error { envName := f.Tag.Get("env") if envName == "" { diff --git a/env/env_test.go b/env/env_test.go index 634a068..88ee4a9 100644 --- a/env/env_test.go +++ b/env/env_test.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package env import ( diff --git a/test/data.go b/test/data.go index f6f8288..d429e91 100644 --- a/test/data.go +++ b/test/data.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package test type DBConfig struct { diff --git a/utils/utils.go b/utils/utils.go index e83cb7c..bb6c490 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package utils import ( diff --git a/utils/utils_test.go b/utils/utils_test.go index d157478..c9d711c 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 eschao + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package utils import (