From 6cebaa7b855f68bcad335f78da14f0747b9b078a Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Wed, 9 Jun 2021 12:37:06 +1000 Subject: [PATCH] Hermitise and bump golangci-lint. --- .golangci.yml | 21 +++++++++++++++++++++ bin/.go@latest.pkg | 1 + bin/.golangci-lint-1.40.1.pkg | 1 + bin/README.hermit.md | 7 +++++++ bin/activate-hermit | 19 +++++++++++++++++++ bin/go | 1 + bin/gofmt | 1 + bin/golangci-lint | 1 + bin/hermit | 26 ++++++++++++++++++++++++++ bin/hermit.hcl | 0 config_test.go | 5 +++-- context.go | 1 + defaults_test.go | 1 - help_test.go | 6 ------ kong.go | 2 +- kong_test.go | 3 --- mapper.go | 8 ++++---- model.go | 1 + options.go | 6 +++--- options_test.go | 2 +- resolver.go | 6 +++--- resolver_test.go | 1 - tag_test.go | 3 --- 23 files changed, 95 insertions(+), 28 deletions(-) create mode 120000 bin/.go@latest.pkg create mode 120000 bin/.golangci-lint-1.40.1.pkg create mode 100644 bin/README.hermit.md create mode 100755 bin/activate-hermit create mode 120000 bin/go create mode 120000 bin/gofmt create mode 120000 bin/golangci-lint create mode 100755 bin/hermit create mode 100644 bin/hermit.hcl diff --git a/.golangci.yml b/.golangci.yml index af55257..0d2c6f8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,6 +15,25 @@ linters: - gocognit - gomnd - goprintffuncname + - paralleltest + - nlreturn + - goerr113 + - ifshort + - testpackage + - wrapcheck + - exhaustivestruct + - forbidigo + - gci + - godot + - gofumpt + - cyclop + - errorlint + - nestif + - golint + - scopelint + - interfacer + - tagliatelle + - thelper linters-settings: govet: @@ -26,6 +45,8 @@ linters-settings: min-occurrences: 3 gocyclo: min-complexity: 20 + exhaustive: + default-signifies-exhaustive: true issues: max-per-linter: 0 diff --git a/bin/.go@latest.pkg b/bin/.go@latest.pkg new file mode 120000 index 0000000..383f451 --- /dev/null +++ b/bin/.go@latest.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/bin/.golangci-lint-1.40.1.pkg b/bin/.golangci-lint-1.40.1.pkg new file mode 120000 index 0000000..383f451 --- /dev/null +++ b/bin/.golangci-lint-1.40.1.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/bin/README.hermit.md b/bin/README.hermit.md new file mode 100644 index 0000000..e889550 --- /dev/null +++ b/bin/README.hermit.md @@ -0,0 +1,7 @@ +# Hermit environment + +This is a [Hermit](https://github.com/cashapp/hermit) bin directory. + +The symlinks in this directory are managed by Hermit and will automatically +download and install Hermit itself as well as packages. These packages are +local to this environment. diff --git a/bin/activate-hermit b/bin/activate-hermit new file mode 100755 index 0000000..3b191fb --- /dev/null +++ b/bin/activate-hermit @@ -0,0 +1,19 @@ +#!/bin/bash +# This file must be used with "source bin/activate-hermit" from bash or zsh. +# You cannot run it directly + +if [ "${BASH_SOURCE-}" = "$0" ]; then + echo "You must source this script: \$ source $0" >&2 + exit 33 +fi + +BIN_DIR="$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}")" +if "${BIN_DIR}/hermit" noop > /dev/null; then + eval "$("${BIN_DIR}/hermit" activate "${BIN_DIR}/..")" + + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ]; then + hash -r 2>/dev/null + fi + + echo "Hermit environment $("${HERMIT_ENV}"/bin/hermit env HERMIT_ENV) activated" +fi diff --git a/bin/go b/bin/go new file mode 120000 index 0000000..142d6ff --- /dev/null +++ b/bin/go @@ -0,0 +1 @@ +.go@latest.pkg \ No newline at end of file diff --git a/bin/gofmt b/bin/gofmt new file mode 120000 index 0000000..142d6ff --- /dev/null +++ b/bin/gofmt @@ -0,0 +1 @@ +.go@latest.pkg \ No newline at end of file diff --git a/bin/golangci-lint b/bin/golangci-lint new file mode 120000 index 0000000..09da506 --- /dev/null +++ b/bin/golangci-lint @@ -0,0 +1 @@ +.golangci-lint-1.40.1.pkg \ No newline at end of file diff --git a/bin/hermit b/bin/hermit new file mode 100755 index 0000000..d13a24d --- /dev/null +++ b/bin/hermit @@ -0,0 +1,26 @@ +#!/bin/bash + +set -eo pipefail + +if [ -z "${HERMIT_STATE_DIR}" ]; then + case "$(uname -s)" in + Darwin) + export HERMIT_STATE_DIR="${HOME}/Library/Caches/hermit" + ;; + Linux) + export HERMIT_STATE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/hermit" + ;; + esac +fi + +export HERMIT_DIST_URL="${HERMIT_DIST_URL:-https://github.com/cashapp/hermit/releases/download/stable}" +HERMIT_CHANNEL="$(basename "${HERMIT_DIST_URL}")" +export HERMIT_CHANNEL +export HERMIT_EXE=${HERMIT_EXE:-${HERMIT_STATE_DIR}/pkg/hermit@${HERMIT_CHANNEL}/hermit} + +if [ ! -x "${HERMIT_EXE}" ]; then + echo "Bootstrapping ${HERMIT_EXE} from ${HERMIT_DIST_URL}" 1>&2 + curl -fsSL "${HERMIT_DIST_URL}/install.sh" | /bin/bash 1>&2 +fi + +exec "${HERMIT_EXE}" --level=fatal exec "$0" -- "$@" diff --git a/bin/hermit.hcl b/bin/hermit.hcl new file mode 100644 index 0000000..e69de29 diff --git a/config_test.go b/config_test.go index 61d1b2e..69e279d 100644 --- a/config_test.go +++ b/config_test.go @@ -6,8 +6,9 @@ import ( "os" "testing" - "github.com/alecthomas/kong" "github.com/stretchr/testify/require" + + "github.com/alecthomas/kong" ) func TestMultipleConfigLoading(t *testing.T) { @@ -47,7 +48,7 @@ func makeConfig(t *testing.T, config interface{}) (path string, cleanup func()) t.Helper() w, err := ioutil.TempFile("", "") require.NoError(t, err) - defer w.Close() + defer w.Close() // nolint: gosec err = json.NewEncoder(w).Encode(config) require.NoError(t, err) return w.Name(), func() { os.Remove(w.Name()) } diff --git a/context.go b/context.go index d132b7d..1e5ae75 100644 --- a/context.go +++ b/context.go @@ -585,6 +585,7 @@ func (c *Context) getValue(value *Value) reflect.Value { v.Set(reflect.MakeSlice(v.Type(), 0, 0)) case reflect.Map: v.Set(reflect.MakeMap(v.Type())) + default: } c.values[value] = v } diff --git a/defaults_test.go b/defaults_test.go index 11a2612..b67640d 100644 --- a/defaults_test.go +++ b/defaults_test.go @@ -24,7 +24,6 @@ func TestApplyDefaults(t *testing.T) { expected: CLI{Str: "str", Duration: time.Second}}, } for _, tt := range tests { - // nolint: scopelint t.Run(tt.name, func(t *testing.T) { err := ApplyDefaults(&tt.target) require.NoError(t, err) diff --git a/help_test.go b/help_test.go index 730c189..566cf73 100644 --- a/help_test.go +++ b/help_test.go @@ -11,7 +11,6 @@ import ( "github.com/alecthomas/kong" ) -// nolint: govet type threeArg struct { RequiredThree bool `required` Three string `arg` @@ -54,7 +53,6 @@ Flags: } func TestHelp(t *testing.T) { - // nolint: govet var cli struct { String string `help:"A string flag."` Bool bool `help:"A bool flag with very long help that wraps a lot and is verbose and is really verbose."` @@ -163,7 +161,6 @@ Flags: } func TestFlagsLast(t *testing.T) { - // nolint: govet var cli struct { String string `help:"A string flag."` Bool bool `help:"A bool flag with very long help that wraps a lot and is verbose and is really verbose."` @@ -272,7 +269,6 @@ Flags: } func TestHelpTree(t *testing.T) { - // nolint: govet var cli struct { One struct { Thing struct { @@ -367,7 +363,6 @@ Commands: } func TestHelpCompactNoExpand(t *testing.T) { - // nolint: govet var cli struct { One struct { Thing struct { @@ -484,7 +479,6 @@ func TestCustomHelpFormatter(t *testing.T) { } func TestHelpGrouping(t *testing.T) { - // nolint: govet var cli struct { GroupedAString string `help:"A string flag grouped in A." group:"Group A"` FreeString string `help:"A non grouped string flag."` diff --git a/kong.go b/kong.go index 9c0e437..f02b867 100644 --- a/kong.go +++ b/kong.go @@ -385,7 +385,7 @@ func (k *Kong) LoadConfig(path string) (Resolver, error) { if err != nil { return nil, err } - defer r.Close() + defer r.Close() // nolint: gosec return k.loader(r) } diff --git a/kong_test.go b/kong_test.go index 6dec560..857c6ca 100644 --- a/kong_test.go +++ b/kong_test.go @@ -118,7 +118,6 @@ func TestFlagSliceWithSeparator(t *testing.T) { } func TestArgSlice(t *testing.T) { - // nolint: govet var cli struct { Slice []int `arg` Flag bool @@ -131,7 +130,6 @@ func TestArgSlice(t *testing.T) { } func TestArgSliceWithSeparator(t *testing.T) { - // nolint: govet var cli struct { Slice []string `arg` Flag bool @@ -498,7 +496,6 @@ func TestHooks(t *testing.T) { for _, test := range tests { *ctx = hookContext{} cli.One = hookCmd{} - // nolint: scopelint t.Run(test.name, func(t *testing.T) { _, err := p.Parse(strings.Split(test.input, " ")) require.NoError(t, err) diff --git a/mapper.go b/mapper.go index f5e1a3f..4c1bb2b 100644 --- a/mapper.go +++ b/mapper.go @@ -125,7 +125,7 @@ type BoolMapper interface { // A MapperFunc is a single function that complies with the Mapper interface. type MapperFunc func(ctx *DecodeContext, target reflect.Value) error -func (m MapperFunc) Decode(ctx *DecodeContext, target reflect.Value) error { // nolint: golint +func (m MapperFunc) Decode(ctx *DecodeContext, target reflect.Value) error { // nolint: revive return m(ctx, target) } @@ -737,7 +737,7 @@ func SplitEscaped(s string, sep rune) (out []string) { func JoinEscaped(s []string, sep rune) string { escaped := []string{} for _, e := range s { - escaped = append(escaped, strings.Replace(e, string(sep), `\`+string(sep), -1)) + escaped = append(escaped, strings.ReplaceAll(e, string(sep), `\`+string(sep))) } return strings.Join(escaped, string(sep)) } @@ -748,7 +748,7 @@ type NamedFileContentFlag struct { Contents []byte } -func (f *NamedFileContentFlag) Decode(ctx *DecodeContext) error { // nolint: golint +func (f *NamedFileContentFlag) Decode(ctx *DecodeContext) error { // nolint: revive var filename string err := ctx.Scan.PopValueInto("filename", &filename) if err != nil { @@ -772,7 +772,7 @@ func (f *NamedFileContentFlag) Decode(ctx *DecodeContext) error { // nolint: gol // FileContentFlag is a flag value that loads a file's contents into its value. type FileContentFlag []byte -func (f *FileContentFlag) Decode(ctx *DecodeContext) error { // nolint: golint +func (f *FileContentFlag) Decode(ctx *DecodeContext) error { // nolint: revive var filename string err := ctx.Scan.PopValueInto("filename", &filename) if err != nil { diff --git a/model.go b/model.go index da64356..928c613 100644 --- a/model.go +++ b/model.go @@ -205,6 +205,7 @@ func (n *Node) Path() (out string) { out += " " + n.Name case ArgumentNode: out += " " + "<" + n.Name + ">" + default: } return strings.TrimSpace(out) } diff --git a/options.go b/options.go index b7c4364..98620c5 100644 --- a/options.go +++ b/options.go @@ -19,7 +19,7 @@ type Option interface { // OptionFunc is function that adheres to the Option interface. type OptionFunc func(k *Kong) error -func (o OptionFunc) Apply(k *Kong) error { return o(k) } // nolint: golint +func (o OptionFunc) Apply(k *Kong) error { return o(k) } // nolint: revive // Vars sets the variables to use for interpolation into help strings and default values. // @@ -198,7 +198,7 @@ func BindToProvider(provider interface{}) Option { errv := out[1] var err error if !errv.IsNil() { - err = errv.Interface().(error) + err = errv.Interface().(error) // nolint } return out[0], err } @@ -254,7 +254,7 @@ func ConfigureHelp(options HelpOptions) Option { // See also ExplicitGroups for a more structured alternative. type Groups map[string]string -func (g Groups) Apply(k *Kong) error { // nolint: golint +func (g Groups) Apply(k *Kong) error { // nolint: revive for key, info := range g { lines := strings.Split(info, "\n") title := strings.TrimSpace(lines[0]) diff --git a/options_test.go b/options_test.go index 0924e50..c48949e 100644 --- a/options_test.go +++ b/options_test.go @@ -28,7 +28,7 @@ func TestBindTo(t *testing.T) { } saw := "" - method := func(i iface) error { // nolint: unparam + method := func(i iface) error { saw = string(i.(impl)) return nil } diff --git a/resolver.go b/resolver.go index 8ef764d..623a734 100644 --- a/resolver.go +++ b/resolver.go @@ -22,10 +22,10 @@ type ResolverFunc func(context *Context, parent *Path, flag *Flag) (interface{}, var _ Resolver = ResolverFunc(nil) -func (r ResolverFunc) Resolve(context *Context, parent *Path, flag *Flag) (interface{}, error) { // nolint: golint +func (r ResolverFunc) Resolve(context *Context, parent *Path, flag *Flag) (interface{}, error) { // nolint: revive return r(context, parent, flag) } -func (r ResolverFunc) Validate(app *Application) error { return nil } // nolint: golint +func (r ResolverFunc) Validate(app *Application) error { return nil } // nolint: revive // JSON returns a Resolver that retrieves values from a JSON source. // @@ -37,7 +37,7 @@ func JSON(r io.Reader) (Resolver, error) { return nil, err } var f ResolverFunc = func(context *Context, parent *Path, flag *Flag) (interface{}, error) { - name := strings.Replace(flag.Name, "-", "_", -1) + name := strings.ReplaceAll(flag.Name, "-", "_") raw, ok := values[name] if !ok { return nil, nil diff --git a/resolver_test.go b/resolver_test.go index fa9f41b..f601544 100644 --- a/resolver_test.go +++ b/resolver_test.go @@ -192,7 +192,6 @@ func TestLastResolverWins(t *testing.T) { } func TestResolverSatisfiesRequired(t *testing.T) { - // nolint: govet var cli struct { Int int `required` } diff --git a/tag_test.go b/tag_test.go index fc512c4..4da0bd0 100644 --- a/tag_test.go +++ b/tag_test.go @@ -68,7 +68,6 @@ func TestEscapedQuote(t *testing.T) { } func TestBareTags(t *testing.T) { - // nolint: govet var cli struct { Cmd struct { Arg string `arg` @@ -84,7 +83,6 @@ func TestBareTags(t *testing.T) { } func TestBareTagsWithJsonTag(t *testing.T) { - // nolint: govet var cli struct { Cmd struct { Arg string `json:"-" optional arg` @@ -100,7 +98,6 @@ func TestBareTagsWithJsonTag(t *testing.T) { } func TestManySeps(t *testing.T) { - // nolint: govet var cli struct { Arg string `arg optional default:"hi"` }