Skip to content

Commit 823f39c

Browse files
committed
chore: hack to append values on StringSlice
1 parent 5117034 commit 823f39c

File tree

7 files changed

+41
-15
lines changed

7 files changed

+41
-15
lines changed

docs/src/docs/usage/configuration.mdx

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ title: Configuration
44

55
The config file has lower priority than command-line options. If the same bool/string/int option is provided on the command-line
66
and in the config file, the option from command-line will be used.
7+
Slice options (e.g. list of enabled/disabled linters) are combined from the command-line and config file.
78

89
To see a list of linters enabled by your configuration use:
910

pkg/commands/config.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ func newConfigCommand(log logutils.Log) *configCommand {
5151
return c
5252
}
5353

54-
func (c *configCommand) preRunE(_ *cobra.Command, _ []string) error {
54+
func (c *configCommand) preRunE(cmd *cobra.Command, _ []string) error {
5555
// The command doesn't depend on the real configuration.
5656
// It only needs to know the path of the configuration file.
57-
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, config.LoaderOptions{}, config.NewDefault())
57+
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), config.LoaderOptions{}, config.NewDefault())
5858

5959
if err := loader.Load(); err != nil {
6060
return fmt.Errorf("can't load config: %w", err)

pkg/commands/flagsets.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ import (
1515
)
1616

1717
func setupLintersFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
18-
internal.VibraP(v, fs, fs.StringSliceP, "disable", "D", "linters.disable", nil, wh("Disable specific linter"))
18+
fs.StringSliceP("disable", "D", nil, wh("Disable specific linter")) // Hack see Loader.appendStringSlice
1919
internal.Vibra(v, fs, fs.Bool, "disable-all", "linters.disable-all", false, wh("Disable all linters"))
2020

21-
internal.VibraP(v, fs, fs.StringSliceP, "enable", "E", "linters.enable", nil, wh("Enable specific linter"))
21+
fs.StringSliceP("enable", "E", nil, wh("Enable specific linter")) // Hack see Loader.appendStringSlice
2222
internal.Vibra(v, fs, fs.Bool, "enable-all", "linters.enable-all", false, wh("Enable all linters"))
2323

2424
internal.Vibra(v, fs, fs.Bool, "fast", "linters.fast", false,
2525
wh("Enable only fast linters from enabled linters set (first run won't be fast)"))
2626

27-
internal.VibraP(v, fs, fs.StringSliceP, "presets", "p", "linters.presets", nil,
27+
// Hack see Loader.appendStringSlice
28+
fs.StringSliceP("presets", "p", nil,
2829
wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint help linters' to see "+
2930
"them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))))
3031
}
@@ -38,14 +39,14 @@ func setupRunFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
3839
internal.Vibra(v, fs, fs.Int, "issues-exit-code", "run.issues-exit-code", exitcodes.IssuesFound,
3940
wh("Exit code when issues were found"))
4041
internal.Vibra(v, fs, fs.String, "go", "run.go", "", wh("Targeted Go version"))
41-
internal.Vibra(v, fs, fs.StringSlice, "build-tags", "run.build-tags", nil, wh("Build tags"))
42+
fs.StringSlice("build-tags", nil, wh("Build tags")) // Hack see Loader.appendStringSlice
4243

4344
internal.Vibra(v, fs, fs.Duration, "timeout", "run.timeout", defaultTimeout, wh("Timeout for total work"))
4445

4546
internal.Vibra(v, fs, fs.Bool, "tests", "run.tests", true, wh("Analyze tests (*_test.go)"))
46-
internal.Vibra(v, fs, fs.StringSlice, "skip-dirs", "run.skip-dirs", nil, wh("Regexps of directories to skip"))
47+
fs.StringSlice("skip-dirs", nil, wh("Regexps of directories to skip")) // Hack see Loader.appendStringSlice
4748
internal.Vibra(v, fs, fs.Bool, "skip-dirs-use-default", "run.skip-dirs-use-default", true, getDefaultDirectoryExcludeHelp())
48-
internal.Vibra(v, fs, fs.StringSlice, "skip-files", "run.skip-files", nil, wh("Regexps of files to skip"))
49+
fs.StringSlice("skip-files", nil, wh("Regexps of files to skip")) // Hack see Loader.appendStringSlice
4950

5051
const allowParallelDesc = "Allow multiple parallel golangci-lint instances running. " +
5152
"If false (default) - golangci-lint acquires file lock on start."
@@ -69,7 +70,7 @@ func setupOutputFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
6970

7071
//nolint:gomnd
7172
func setupIssuesFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
72-
internal.VibraP(v, fs, fs.StringSliceP, "exclude", "e", "issues.exclude", nil, wh("Exclude issue by regexp"))
73+
fs.StringSliceP("exclude", "e", nil, wh("Exclude issue by regexp")) // Hack see Loader.appendStringSlice
7374
internal.Vibra(v, fs, fs.Bool, "exclude-use-default", "issues.exclude-use-default", true, getDefaultIssueExcludeHelp())
7475
internal.Vibra(v, fs, fs.Bool, "exclude-case-sensitive", "issues.exclude-case-sensitive", false,
7576
wh("If set to true exclude and exclude rules regular expressions are case-sensitive"))

pkg/commands/linters.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ func newLintersCommand(logger logutils.Log, cfg *config.Config) *lintersCommand
5858
return c
5959
}
6060

61-
func (c *lintersCommand) preRunE(_ *cobra.Command, _ []string) error {
62-
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, c.opts.LoaderOptions, c.cfg)
61+
func (c *lintersCommand) preRunE(cmd *cobra.Command, _ []string) error {
62+
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), c.opts.LoaderOptions, c.cfg)
6363

6464
if err := loader.Load(); err != nil {
6565
return fmt.Errorf("can't load config: %w", err)

pkg/commands/run.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,12 @@ func newRunCommand(logger logutils.Log, cfg *config.Config, reportData *report.D
143143
return c
144144
}
145145

146-
func (c *runCommand) persistentPreRunE(_ *cobra.Command, _ []string) error {
146+
func (c *runCommand) persistentPreRunE(cmd *cobra.Command, _ []string) error {
147147
if err := c.startTracing(); err != nil {
148148
return err
149149
}
150150

151-
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, c.opts.LoaderOptions, c.cfg)
151+
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), c.opts.LoaderOptions, c.cfg)
152152

153153
if err := loader.Load(); err != nil {
154154
return fmt.Errorf("can't load config: %w", err)

pkg/config/loader.go

+25-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/go-viper/mapstructure/v2"
1212
"github.com/mitchellh/go-homedir"
13+
"github.com/spf13/pflag"
1314
"github.com/spf13/viper"
1415

1516
"github.com/golangci/golangci-lint/pkg/exitcodes"
@@ -28,16 +29,18 @@ type Loader struct {
2829
opts LoaderOptions
2930

3031
viper *viper.Viper
32+
fs *pflag.FlagSet
3133

3234
log logutils.Log
3335

3436
cfg *Config
3537
}
3638

37-
func NewLoader(log logutils.Log, v *viper.Viper, opts LoaderOptions, cfg *Config) *Loader {
39+
func NewLoader(log logutils.Log, v *viper.Viper, fs *pflag.FlagSet, opts LoaderOptions, cfg *Config) *Loader {
3840
return &Loader{
3941
opts: opts,
4042
viper: v,
43+
fs: fs,
4144
log: log,
4245
cfg: cfg,
4346
}
@@ -54,6 +57,16 @@ func (r *Loader) Load() error {
5457
return err
5558
}
5659

60+
if r.fs != nil {
61+
r.appendStringSlice("enable", &r.cfg.Linters.Enable)
62+
r.appendStringSlice("disable", &r.cfg.Linters.Disable)
63+
r.appendStringSlice("presets", &r.cfg.Linters.Presets)
64+
r.appendStringSlice("build-tags", &r.cfg.Run.BuildTags)
65+
r.appendStringSlice("skip-dirs", &r.cfg.Run.SkipDirs)
66+
r.appendStringSlice("skip-files", &r.cfg.Run.SkipFiles)
67+
r.appendStringSlice("exclude", &r.cfg.Issues.ExcludePatterns)
68+
}
69+
5770
if r.cfg.Run.Go == "" {
5871
r.cfg.Run.Go = detectGoVersion()
5972
}
@@ -220,6 +233,17 @@ func (r *Loader) setConfigDir() error {
220233
return nil
221234
}
222235

236+
// Hack to append values from StringSlice flags.
237+
// Viper always overrides StringSlice values.
238+
// https://github.com/spf13/viper/issues/1448
239+
// So StringSlice flags are not bind to Viper like that their values are obtain via Cobra Flags.
240+
func (r *Loader) appendStringSlice(name string, current *[]string) {
241+
if r.fs.Changed(name) {
242+
val, _ := r.fs.GetStringSlice(name)
243+
*current = append(*current, val...)
244+
}
245+
}
246+
223247
func fileDecoderHook() viper.DecoderConfigOption {
224248
return viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
225249
// Default hooks (https://github.com/spf13/viper/blob/518241257478c557633ab36e474dfcaeb9a3c623/viper.go#L135-L138).

test/enabled_linters_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func TestEnabledLinters(t *testing.T) {
5353
enable:
5454
- revive
5555
`,
56-
enabledLinters: getEnabledByDefaultFastLintersWith("gofmt"),
56+
enabledLinters: getEnabledByDefaultFastLintersWith("revive", "gofmt"),
5757
},
5858
{
5959
name: "fast option in config",

0 commit comments

Comments
 (0)