linters/errcheck: add support for ignore/exclude flags
Add support for the exclude and ignore flags of errcheck. Note that, this commit depends on golangci/errcheck#1. We need to merge it first, update vendors and only then merge this one.
This commit is contained in:
parent
59c3d20303
commit
b81346f9d3
6
Gopkg.lock
generated
6
Gopkg.lock
generated
@ -481,12 +481,12 @@
|
|||||||
revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
|
revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7"
|
branch = "master"
|
||||||
|
digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2"
|
||||||
name = "github.com/spf13/pflag"
|
name = "github.com/spf13/pflag"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
|
revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
|
||||||
version = "v1.0.1"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:59e7dceb53b4a1e57eb1eb0bf9951ff0c25912df7660004a789b62b4e8cdca3b"
|
digest = "1:59e7dceb53b4a1e57eb1eb0bf9951ff0c25912df7660004a789b62b4e8cdca3b"
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
name = "github.com/spf13/viper"
|
name = "github.com/spf13/viper"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/spf13/pflag"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/mitchellh/go-ps"
|
name = "github.com/mitchellh/go-ps"
|
||||||
|
@ -75,16 +75,20 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager) {
|
|||||||
lsc := &cfg.LintersSettings
|
lsc := &cfg.LintersSettings
|
||||||
|
|
||||||
// Hide all linters settings flags: they were initially visible,
|
// Hide all linters settings flags: they were initially visible,
|
||||||
// but when number of linters started to grow it became ovious that
|
// but when number of linters started to grow it became obvious that
|
||||||
// we can't fill 90% of flags by linters settings: common flags became hard to find.
|
// we can't fill 90% of flags by linters settings: common flags became hard to find.
|
||||||
// New linters settings should be done only through config file.
|
// New linters settings should be done only through config file.
|
||||||
fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions",
|
fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions",
|
||||||
false, "Errcheck: check for ignored type assertion results")
|
false, "Errcheck: check for ignored type assertion results")
|
||||||
hideFlag("errcheck.check-type-assertions")
|
hideFlag("errcheck.check-type-assertions")
|
||||||
|
|
||||||
fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false,
|
fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false,
|
||||||
"Errcheck: check for errors assigned to blank identifier: _ = errFunc()")
|
"Errcheck: check for errors assigned to blank identifier: _ = errFunc()")
|
||||||
hideFlag("errcheck.check-blank")
|
hideFlag("errcheck.check-blank")
|
||||||
|
fs.StringVar(&lsc.Errcheck.Exclude, "errcheck.exclude", "", "errcheck.exclude")
|
||||||
|
hideFlag("errcheck.exclude")
|
||||||
|
lsc.Errcheck.Ignore = config.IgnoreFlag{}
|
||||||
|
fs.Var(&lsc.Errcheck.Ignore, "errcheck.ignore", "errcheck.ignore")
|
||||||
|
hideFlag("errcheck.ignore")
|
||||||
|
|
||||||
fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false,
|
fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false,
|
||||||
"Govet: check for shadowed variables")
|
"Govet: check for shadowed variables")
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -115,10 +118,6 @@ type Run struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LintersSettings struct {
|
type LintersSettings struct {
|
||||||
Errcheck struct {
|
|
||||||
CheckTypeAssertions bool `mapstructure:"check-type-assertions"`
|
|
||||||
CheckAssignToBlank bool `mapstructure:"check-blank"`
|
|
||||||
}
|
|
||||||
Govet struct {
|
Govet struct {
|
||||||
CheckShadowing bool `mapstructure:"check-shadowing"`
|
CheckShadowing bool `mapstructure:"check-shadowing"`
|
||||||
UseInstalledPackages bool `mapstructure:"use-installed-packages"`
|
UseInstalledPackages bool `mapstructure:"use-installed-packages"`
|
||||||
@ -164,6 +163,14 @@ type LintersSettings struct {
|
|||||||
Unparam UnparamSettings
|
Unparam UnparamSettings
|
||||||
Nakedret NakedretSettings
|
Nakedret NakedretSettings
|
||||||
Prealloc PreallocSettings
|
Prealloc PreallocSettings
|
||||||
|
Errcheck ErrcheckSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrcheckSettings struct {
|
||||||
|
CheckTypeAssertions bool `mapstructure:"check-type-assertions"`
|
||||||
|
CheckAssignToBlank bool `mapstructure:"check-blank"`
|
||||||
|
Ignore IgnoreFlag `mapstructure:"ignore"`
|
||||||
|
Exclude string `mapstructure:"exclude"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LllSettings struct {
|
type LllSettings struct {
|
||||||
@ -248,3 +255,47 @@ func NewDefault() *Config {
|
|||||||
LintersSettings: defaultLintersSettings,
|
LintersSettings: defaultLintersSettings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IgnoreFlags was taken from errcheck in order to keep the API identical.
|
||||||
|
// https://github.com/kisielk/errcheck/blob/1787c4bee836470bf45018cfbc783650db3c6501/main.go#L25-L60
|
||||||
|
type IgnoreFlag map[string]*regexp.Regexp
|
||||||
|
|
||||||
|
func (f IgnoreFlag) String() string {
|
||||||
|
pairs := make([]string, 0, len(f))
|
||||||
|
for pkg, re := range f {
|
||||||
|
prefix := ""
|
||||||
|
if pkg != "" {
|
||||||
|
prefix = pkg + ":"
|
||||||
|
}
|
||||||
|
pairs = append(pairs, prefix+re.String())
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%q", strings.Join(pairs, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f IgnoreFlag) Set(s string) error {
|
||||||
|
if s == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, pair := range strings.Split(s, ",") {
|
||||||
|
colonIndex := strings.Index(pair, ":")
|
||||||
|
var pkg, re string
|
||||||
|
if colonIndex == -1 {
|
||||||
|
pkg = ""
|
||||||
|
re = pair
|
||||||
|
} else {
|
||||||
|
pkg = pair[:colonIndex]
|
||||||
|
re = pair[colonIndex+1:]
|
||||||
|
}
|
||||||
|
regex, err := regexp.Compile(re)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f[pkg] = regex
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the type of the flag follow the pflag format.
|
||||||
|
func (IgnoreFlag) Type() string {
|
||||||
|
return "stringToRegexp"
|
||||||
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package golinters
|
package golinters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
errcheckAPI "github.com/golangci/errcheck/golangci"
|
errcheckAPI "github.com/golangci/errcheck/golangci"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/config"
|
||||||
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Errcheck struct{}
|
type Errcheck struct{}
|
||||||
@ -21,8 +25,11 @@ func (Errcheck) Desc() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e Errcheck) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
|
func (e Errcheck) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
|
||||||
errCfg := &lintCtx.Settings().Errcheck
|
errCfg, err := genConfig(&lintCtx.Settings().Errcheck)
|
||||||
issues, err := errcheckAPI.Run(lintCtx.Program, errCfg.CheckAssignToBlank, errCfg.CheckTypeAssertions)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
issues, err := errcheckAPI.RunWithConfig(lintCtx.Program, errCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -48,3 +55,36 @@ func (e Errcheck) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Is
|
|||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func genConfig(errCfg *config.ErrcheckSettings) (*errcheckAPI.Config, error) {
|
||||||
|
c := &errcheckAPI.Config{
|
||||||
|
Ignore: errCfg.Ignore,
|
||||||
|
Blank: errCfg.CheckAssignToBlank,
|
||||||
|
Asserts: errCfg.CheckTypeAssertions,
|
||||||
|
}
|
||||||
|
if errCfg.Exclude != "" {
|
||||||
|
exclude, err := readExcludeFile(errCfg.Exclude)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.Exclude = exclude
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readExcludeFile(name string) (map[string]bool, error) {
|
||||||
|
exclude := make(map[string]bool)
|
||||||
|
fh, err := os.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed reading exclude file: %s", name)
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(fh)
|
||||||
|
for scanner.Scan() {
|
||||||
|
name := scanner.Text()
|
||||||
|
exclude[name] = true
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed scanning file: %s", name)
|
||||||
|
}
|
||||||
|
return exclude, nil
|
||||||
|
}
|
||||||
|
104
vendor/github.com/spf13/pflag/bytes.go
generated
vendored
104
vendor/github.com/spf13/pflag/bytes.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package pflag
|
package pflag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
@ -9,10 +10,12 @@ import (
|
|||||||
// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
|
// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
|
||||||
type bytesHexValue []byte
|
type bytesHexValue []byte
|
||||||
|
|
||||||
|
// String implements pflag.Value.String.
|
||||||
func (bytesHex bytesHexValue) String() string {
|
func (bytesHex bytesHexValue) String() string {
|
||||||
return fmt.Sprintf("%X", []byte(bytesHex))
|
return fmt.Sprintf("%X", []byte(bytesHex))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set implements pflag.Value.Set.
|
||||||
func (bytesHex *bytesHexValue) Set(value string) error {
|
func (bytesHex *bytesHexValue) Set(value string) error {
|
||||||
bin, err := hex.DecodeString(strings.TrimSpace(value))
|
bin, err := hex.DecodeString(strings.TrimSpace(value))
|
||||||
|
|
||||||
@ -25,6 +28,7 @@ func (bytesHex *bytesHexValue) Set(value string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type implements pflag.Value.Type.
|
||||||
func (*bytesHexValue) Type() string {
|
func (*bytesHexValue) Type() string {
|
||||||
return "bytesHex"
|
return "bytesHex"
|
||||||
}
|
}
|
||||||
@ -103,3 +107,103 @@ func BytesHex(name string, value []byte, usage string) *[]byte {
|
|||||||
func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
|
func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
return CommandLine.BytesHexP(name, shorthand, value, usage)
|
return CommandLine.BytesHexP(name, shorthand, value, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded
|
||||||
|
type bytesBase64Value []byte
|
||||||
|
|
||||||
|
// String implements pflag.Value.String.
|
||||||
|
func (bytesBase64 bytesBase64Value) String() string {
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(bytesBase64))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set implements pflag.Value.Set.
|
||||||
|
func (bytesBase64 *bytesBase64Value) Set(value string) error {
|
||||||
|
bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytesBase64 = bin
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type implements pflag.Value.Type.
|
||||||
|
func (*bytesBase64Value) Type() string {
|
||||||
|
return "bytesBase64"
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value {
|
||||||
|
*p = val
|
||||||
|
return (*bytesBase64Value)(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bytesBase64ValueConv(sval string) (interface{}, error) {
|
||||||
|
|
||||||
|
bin, err := base64.StdEncoding.DecodeString(sval)
|
||||||
|
if err == nil {
|
||||||
|
return bin, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBytesBase64 return the []byte value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) {
|
||||||
|
val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return val.([]byte), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
|
||||||
|
f.VarP(newBytesBase64Value(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||||
|
f.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||||
|
func BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
|
||||||
|
CommandLine.VarP(newBytesBase64Value(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||||
|
CommandLine.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) BytesBase64(name string, value []byte, usage string) *[]byte {
|
||||||
|
p := new([]byte)
|
||||||
|
f.BytesBase64VarP(p, name, "", value, usage)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
|
p := new([]byte)
|
||||||
|
f.BytesBase64VarP(p, name, shorthand, value, usage)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||||
|
func BytesBase64(name string, value []byte, usage string) *[]byte {
|
||||||
|
return CommandLine.BytesBase64P(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
|
return CommandLine.BytesBase64P(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
|
10
vendor/github.com/spf13/pflag/flag.go
generated
vendored
10
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -925,13 +925,16 @@ func stripUnknownFlagValue(args []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
first := args[0]
|
first := args[0]
|
||||||
if first[0] == '-' {
|
if len(first) > 0 && first[0] == '-' {
|
||||||
//--unknown --next-flag ...
|
//--unknown --next-flag ...
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
//--unknown arg ... (args will be arg ...)
|
//--unknown arg ... (args will be arg ...)
|
||||||
return args[1:]
|
if len(args) > 1 {
|
||||||
|
return args[1:]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
@ -990,11 +993,12 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
||||||
|
outArgs = args
|
||||||
|
|
||||||
if strings.HasPrefix(shorthands, "test.") {
|
if strings.HasPrefix(shorthands, "test.") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outArgs = args
|
|
||||||
outShorts = shorthands[1:]
|
outShorts = shorthands[1:]
|
||||||
c := shorthands[0]
|
c := shorthands[0]
|
||||||
|
|
||||||
|
149
vendor/github.com/spf13/pflag/string_to_int.go
generated
vendored
Normal file
149
vendor/github.com/spf13/pflag/string_to_int.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- stringToInt Value
|
||||||
|
type stringToIntValue struct {
|
||||||
|
value *map[string]int
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue {
|
||||||
|
ssv := new(stringToIntValue)
|
||||||
|
ssv.value = p
|
||||||
|
*ssv.value = val
|
||||||
|
return ssv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format: a=1,b=2
|
||||||
|
func (s *stringToIntValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make(map[string]int, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
out[kv[0]], err = strconv.Atoi(kv[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
for k, v := range out {
|
||||||
|
(*s.value)[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToIntValue) Type() string {
|
||||||
|
return "stringToInt"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToIntValue) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
i := 0
|
||||||
|
for k, v := range *s.value {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteRune(',')
|
||||||
|
}
|
||||||
|
buf.WriteString(k)
|
||||||
|
buf.WriteRune('=')
|
||||||
|
buf.WriteString(strconv.Itoa(v))
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return "[" + buf.String() + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringToIntConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// An empty string would cause an empty map
|
||||||
|
if len(val) == 0 {
|
||||||
|
return map[string]int{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make(map[string]int, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
out[kv[0]], err = strconv.Atoi(kv[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringToInt return the map[string]int value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) {
|
||||||
|
val, err := f.getFlagType(name, "stringToInt", stringToIntConv)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]int{}, err
|
||||||
|
}
|
||||||
|
return val.(map[string]int), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]int variable in which to store the values of the multiple flags.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
|
||||||
|
f.VarP(newStringToIntValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
|
||||||
|
f.VarP(newStringToIntValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]int variable in which to store the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
|
||||||
|
CommandLine.VarP(newStringToIntValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
|
||||||
|
CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]int variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int {
|
||||||
|
p := map[string]int{}
|
||||||
|
f.StringToIntVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
|
||||||
|
p := map[string]int{}
|
||||||
|
f.StringToIntVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]int variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToInt(name string, value map[string]int, usage string) *map[string]int {
|
||||||
|
return CommandLine.StringToIntP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
|
||||||
|
return CommandLine.StringToIntP(name, shorthand, value, usage)
|
||||||
|
}
|
160
vendor/github.com/spf13/pflag/string_to_string.go
generated
vendored
Normal file
160
vendor/github.com/spf13/pflag/string_to_string.go
generated
vendored
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- stringToString Value
|
||||||
|
type stringToStringValue struct {
|
||||||
|
value *map[string]string
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue {
|
||||||
|
ssv := new(stringToStringValue)
|
||||||
|
ssv.value = p
|
||||||
|
*ssv.value = val
|
||||||
|
return ssv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format: a=1,b=2
|
||||||
|
func (s *stringToStringValue) Set(val string) error {
|
||||||
|
var ss []string
|
||||||
|
n := strings.Count(val, "=")
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
return fmt.Errorf("%s must be formatted as key=value", val)
|
||||||
|
case 1:
|
||||||
|
ss = append(ss, strings.Trim(val, `"`))
|
||||||
|
default:
|
||||||
|
r := csv.NewReader(strings.NewReader(val))
|
||||||
|
var err error
|
||||||
|
ss, err = r.Read()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make(map[string]string, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
out[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
for k, v := range out {
|
||||||
|
(*s.value)[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToStringValue) Type() string {
|
||||||
|
return "stringToString"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToStringValue) String() string {
|
||||||
|
records := make([]string, 0, len(*s.value)>>1)
|
||||||
|
for k, v := range *s.value {
|
||||||
|
records = append(records, k+"="+v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := csv.NewWriter(&buf)
|
||||||
|
if err := w.Write(records); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
w.Flush()
|
||||||
|
return "[" + strings.TrimSpace(buf.String()) + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringToStringConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// An empty string would cause an empty map
|
||||||
|
if len(val) == 0 {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
}
|
||||||
|
r := csv.NewReader(strings.NewReader(val))
|
||||||
|
ss, err := r.Read()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out := make(map[string]string, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
out[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringToString return the map[string]string value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
|
||||||
|
val, err := f.getFlagType(name, "stringToString", stringToStringConv)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]string{}, err
|
||||||
|
}
|
||||||
|
return val.(map[string]string), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]string variable in which to store the values of the multiple flags.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
|
||||||
|
f.VarP(newStringToStringValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
|
||||||
|
f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]string variable in which to store the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
|
||||||
|
CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
|
||||||
|
CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToString defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]string variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
|
||||||
|
p := map[string]string{}
|
||||||
|
f.StringToStringVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
|
||||||
|
p := map[string]string{}
|
||||||
|
f.StringToStringVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToString defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]string variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToString(name string, value map[string]string, usage string) *map[string]string {
|
||||||
|
return CommandLine.StringToStringP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
|
||||||
|
return CommandLine.StringToStringP(name, shorthand, value, usage)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user