Skip to content

Commit c5f13ba

Browse files
authored
dev: clean code arround CLI args usage (#4557)
1 parent dffe901 commit c5f13ba

File tree

10 files changed

+219
-99
lines changed

10 files changed

+219
-99
lines changed

pkg/commands/config.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func newConfigCommand(log logutils.Log, info BuildInfo) *configCommand {
7777
return c
7878
}
7979

80-
func (c *configCommand) preRunE(cmd *cobra.Command, _ []string) error {
80+
func (c *configCommand) preRunE(cmd *cobra.Command, args []string) error {
8181
// The command doesn't depend on the real configuration.
8282
// It only needs to know the path of the configuration file.
8383
cfg := config.NewDefault()
@@ -89,7 +89,7 @@ func (c *configCommand) preRunE(cmd *cobra.Command, _ []string) error {
8989
// TODO(ldez) add an option (check deprecation) to `Loader.Load()` but this require a dedicated PR.
9090
cfg.Run.UseDefaultSkipDirs = true
9191

92-
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), c.opts, cfg)
92+
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), c.opts, cfg, args)
9393

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

pkg/commands/linters.go

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

61-
func (c *lintersCommand) preRunE(cmd *cobra.Command, _ []string) error {
61+
func (c *lintersCommand) preRunE(cmd *cobra.Command, args []string) error {
6262
// Hack to hide deprecation messages related to `--skip-dirs-use-default`:
6363
// Flags are not bound then the default values, defined only through flags, are not applied.
6464
// In this command, linters information are the only requirements, i.e. it don't need flag values.
6565
//
6666
// TODO(ldez) add an option (check deprecation) to `Loader.Load()` but this require a dedicated PR.
6767
c.cfg.Run.UseDefaultSkipDirs = true
6868

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

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

pkg/commands/run.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,12 @@ func newRunCommand(logger logutils.Log, info BuildInfo) *runCommand {
147147
return c
148148
}
149149

150-
func (c *runCommand) persistentPreRunE(cmd *cobra.Command, _ []string) error {
150+
func (c *runCommand) persistentPreRunE(cmd *cobra.Command, args []string) error {
151151
if err := c.startTracing(); err != nil {
152152
return err
153153
}
154154

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

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

pkg/config/loader.go

+35-50
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"os"
77
"path/filepath"
88
"slices"
9-
"strings"
109

1110
"github.com/go-viper/mapstructure/v2"
1211
"github.com/mitchellh/go-homedir"
@@ -33,16 +32,18 @@ type Loader struct {
3332

3433
log logutils.Log
3534

36-
cfg *Config
35+
cfg *Config
36+
args []string
3737
}
3838

39-
func NewLoader(log logutils.Log, v *viper.Viper, fs *pflag.FlagSet, opts LoaderOptions, cfg *Config) *Loader {
39+
func NewLoader(log logutils.Log, v *viper.Viper, fs *pflag.FlagSet, opts LoaderOptions, cfg *Config, args []string) *Loader {
4040
return &Loader{
4141
opts: opts,
4242
viper: v,
4343
fs: fs,
4444
log: log,
4545
cfg: cfg,
46+
args: args,
4647
}
4748
}
4849

@@ -116,50 +117,59 @@ func (l *Loader) evaluateOptions() (string, error) {
116117
}
117118

118119
func (l *Loader) setupConfigFileSearch() {
119-
firstArg := extractFirstPathArg()
120+
l.viper.SetConfigName(".golangci")
121+
122+
configSearchPaths := l.getConfigSearchPaths()
123+
124+
l.log.Infof("Config search paths: %s", configSearchPaths)
125+
126+
for _, p := range configSearchPaths {
127+
l.viper.AddConfigPath(p)
128+
}
129+
}
130+
131+
func (l *Loader) getConfigSearchPaths() []string {
132+
firstArg := "./..."
133+
if len(l.args) > 0 {
134+
firstArg = l.args[0]
135+
}
120136

121-
absStartPath, err := filepath.Abs(firstArg)
137+
absPath, err := filepath.Abs(firstArg)
122138
if err != nil {
123139
l.log.Warnf("Can't make abs path for %q: %s", firstArg, err)
124-
absStartPath = filepath.Clean(firstArg)
140+
absPath = filepath.Clean(firstArg)
125141
}
126142

127143
// start from it
128-
var curDir string
129-
if fsutils.IsDir(absStartPath) {
130-
curDir = absStartPath
144+
var currentDir string
145+
if fsutils.IsDir(absPath) {
146+
currentDir = absPath
131147
} else {
132-
curDir = filepath.Dir(absStartPath)
148+
currentDir = filepath.Dir(absPath)
133149
}
134150

135151
// find all dirs from it up to the root
136-
configSearchPaths := []string{"./"}
152+
searchPaths := []string{"./"}
137153

138154
for {
139-
configSearchPaths = append(configSearchPaths, curDir)
155+
searchPaths = append(searchPaths, currentDir)
140156

141-
newCurDir := filepath.Dir(curDir)
142-
if curDir == newCurDir || newCurDir == "" {
157+
parent := filepath.Dir(currentDir)
158+
if currentDir == parent || parent == "" {
143159
break
144160
}
145161

146-
curDir = newCurDir
162+
currentDir = parent
147163
}
148164

149165
// find home directory for global config
150166
if home, err := homedir.Dir(); err != nil {
151-
l.log.Warnf("Can't get user's home directory: %s", err.Error())
152-
} else if !slices.Contains(configSearchPaths, home) {
153-
configSearchPaths = append(configSearchPaths, home)
167+
l.log.Warnf("Can't get user's home directory: %v", err)
168+
} else if !slices.Contains(searchPaths, home) {
169+
searchPaths = append(searchPaths, home)
154170
}
155171

156-
l.log.Infof("Config search paths: %s", configSearchPaths)
157-
158-
l.viper.SetConfigName(".golangci")
159-
160-
for _, p := range configSearchPaths {
161-
l.viper.AddConfigPath(p)
162-
}
172+
return searchPaths
163173
}
164174

165175
func (l *Loader) parseConfig() error {
@@ -416,28 +426,3 @@ func customDecoderHook() viper.DecoderConfigOption {
416426
mapstructure.TextUnmarshallerHookFunc(),
417427
))
418428
}
419-
420-
func extractFirstPathArg() string {
421-
args := os.Args
422-
423-
// skip all args ([golangci-lint, run/linters]) before files/dirs list
424-
for len(args) != 0 {
425-
if args[0] == "run" {
426-
args = args[1:]
427-
break
428-
}
429-
430-
args = args[1:]
431-
}
432-
433-
// find first file/dir arg
434-
firstArg := "./..."
435-
for _, arg := range args {
436-
if !strings.HasPrefix(arg, "-") {
437-
firstArg = arg
438-
break
439-
}
440-
}
441-
442-
return firstArg
443-
}

pkg/lint/package.go

+21-19
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ func (l *PackageLoader) loadPackages(ctx context.Context, loadMode packages.Load
7878
// TODO: use fset, parsefile, overlay
7979
}
8080

81-
args := l.buildArgs()
81+
args := buildArgs(l.args)
82+
8283
l.debugf("Built loader args are %s", args)
84+
8385
pkgs, err := packages.Load(conf, args...)
8486
if err != nil {
8587
return nil, fmt.Errorf("failed to load with go/packages: %w", err)
@@ -212,24 +214,6 @@ func (l *PackageLoader) prepareBuildContext() {
212214
build.Default.BuildTags = l.cfg.Run.BuildTags
213215
}
214216

215-
func (l *PackageLoader) buildArgs() []string {
216-
if len(l.args) == 0 {
217-
return []string{"./..."}
218-
}
219-
220-
var retArgs []string
221-
for _, arg := range l.args {
222-
if strings.HasPrefix(arg, ".") || filepath.IsAbs(arg) {
223-
retArgs = append(retArgs, arg)
224-
} else {
225-
// go/packages doesn't work well if we don't have the prefix ./ for local packages
226-
retArgs = append(retArgs, fmt.Sprintf(".%c%s", filepath.Separator, arg))
227-
}
228-
}
229-
230-
return retArgs
231-
}
232-
233217
func (l *PackageLoader) makeBuildFlags() []string {
234218
var buildFlags []string
235219

@@ -247,6 +231,24 @@ func (l *PackageLoader) makeBuildFlags() []string {
247231
return buildFlags
248232
}
249233

234+
func buildArgs(args []string) []string {
235+
if len(args) == 0 {
236+
return []string{"./..."}
237+
}
238+
239+
var retArgs []string
240+
for _, arg := range args {
241+
if strings.HasPrefix(arg, ".") || filepath.IsAbs(arg) {
242+
retArgs = append(retArgs, arg)
243+
} else {
244+
// go/packages doesn't work well if we don't have the prefix ./ for local packages
245+
retArgs = append(retArgs, fmt.Sprintf(".%c%s", filepath.Separator, arg))
246+
}
247+
}
248+
249+
return retArgs
250+
}
251+
250252
func findLoadMode(linters []*linter.Config) packages.LoadMode {
251253
loadMode := packages.LoadMode(0)
252254
for _, lc := range linters {

pkg/lint/package_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package lint
2+
3+
import (
4+
"path/filepath"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func Test_buildArgs(t *testing.T) {
12+
testCases := []struct {
13+
desc string
14+
args []string
15+
expected []string
16+
}{
17+
{
18+
desc: "empty",
19+
args: nil,
20+
expected: []string{"./..."},
21+
},
22+
{
23+
desc: "start with a dot",
24+
args: []string{filepath.FromSlash("./foo")},
25+
expected: []string{filepath.FromSlash("./foo")},
26+
},
27+
{
28+
desc: "start without a dot",
29+
args: []string{"foo"},
30+
expected: []string{filepath.FromSlash("./foo")},
31+
},
32+
{
33+
desc: "absolute path",
34+
args: []string{mustAbs(t, "/tmp/foo")},
35+
expected: []string{mustAbs(t, "/tmp/foo")},
36+
},
37+
}
38+
39+
for _, test := range testCases {
40+
test := test
41+
t.Run(test.desc, func(t *testing.T) {
42+
t.Parallel()
43+
44+
results := buildArgs(test.args)
45+
46+
assert.Equal(t, test.expected, results)
47+
})
48+
}
49+
}
50+
51+
func mustAbs(t *testing.T, p string) string {
52+
t.Helper()
53+
54+
abs, err := filepath.Abs(filepath.FromSlash(p))
55+
require.NoError(t, err)
56+
57+
return abs
58+
}

pkg/result/processors/autogenerated_exclude.go

-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"go/parser"
66
"go/token"
7-
"path/filepath"
87
"regexp"
98
"strings"
109

@@ -157,7 +156,3 @@ func getComments(filePath string) (string, error) {
157156

158157
return strings.Join(docLines, "\n"), nil
159158
}
160-
161-
func isGoFile(name string) bool {
162-
return filepath.Ext(name) == ".go"
163-
}

pkg/result/processors/invalid_issue.go

+4
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ func (p InvalidIssue) shouldPassIssue(issue *result.Issue) (bool, error) {
5050

5151
return true, nil
5252
}
53+
54+
func isGoFile(name string) bool {
55+
return filepath.Ext(name) == ".go"
56+
}

0 commit comments

Comments
 (0)