@@ -5,13 +5,16 @@ import (
55 "context"
66 "fmt"
77 "os"
8+ "os/user"
9+ "path/filepath"
810 "regexp"
911 "strings"
1012
1113 errcheckAPI "github.com/golangci/errcheck/golangci"
1214 "github.com/pkg/errors"
1315
1416 "github.com/golangci/golangci-lint/pkg/config"
17+ "github.com/golangci/golangci-lint/pkg/fsutils"
1518 "github.com/golangci/golangci-lint/pkg/lint/linter"
1619 "github.com/golangci/golangci-lint/pkg/result"
1720)
@@ -111,13 +114,86 @@ func genConfig(errCfg *config.ErrcheckSettings) (*errcheckAPI.Config, error) {
111114 return c , nil
112115}
113116
114- func readExcludeFile (name string ) (map [string ]bool , error ) {
115- exclude := make (map [string ]bool )
116- fh , err := os .Open (name )
117+ func getFirstPathArg () string {
118+ args := os .Args
119+
120+ // skip all args ([golangci-lint, run/linters]) before files/dirs list
121+ for len (args ) != 0 {
122+ if args [0 ] == "run" {
123+ args = args [1 :]
124+ break
125+ }
126+
127+ args = args [1 :]
128+ }
129+
130+ // find first file/dir arg
131+ firstArg := "./..."
132+ for _ , arg := range args {
133+ if ! strings .HasPrefix (arg , "-" ) {
134+ firstArg = arg
135+ break
136+ }
137+ }
138+
139+ return firstArg
140+ }
141+
142+ func setupConfigFileSearch (name string ) []string {
143+ if strings .HasPrefix (name , "~" ) {
144+ if u , err := user .Current (); err == nil {
145+ name = strings .Replace (name , "~" , u .HomeDir , 1 )
146+ }
147+ }
148+
149+ if filepath .IsAbs (name ) {
150+ return []string {name }
151+ }
152+
153+ firstArg := getFirstPathArg ()
154+
155+ absStartPath , err := filepath .Abs (firstArg )
117156 if err != nil {
157+ absStartPath = filepath .Clean (firstArg )
158+ }
159+
160+ // start from it
161+ var curDir string
162+ if fsutils .IsDir (absStartPath ) {
163+ curDir = absStartPath
164+ } else {
165+ curDir = filepath .Dir (absStartPath )
166+ }
167+
168+ // find all dirs from it up to the root
169+ configSearchPaths := []string {filepath .Join ("." , name )}
170+ for {
171+ configSearchPaths = append (configSearchPaths , filepath .Join (curDir , name ))
172+ newCurDir := filepath .Dir (curDir )
173+ if curDir == newCurDir || newCurDir == "" {
174+ break
175+ }
176+ curDir = newCurDir
177+ }
178+
179+ return configSearchPaths
180+ }
181+
182+ func readExcludeFile (name string ) (map [string ]bool , error ) {
183+ var err error
184+ var fh * os.File
185+
186+ for _ , path := range setupConfigFileSearch (name ) {
187+ if fh , err = os .Open (path ); err == nil {
188+ break
189+ }
190+ }
191+
192+ if fh == nil {
118193 return nil , errors .Wrapf (err , "failed reading exclude file: %s" , name )
119194 }
120195 scanner := bufio .NewScanner (fh )
196+ exclude := make (map [string ]bool )
121197 for scanner .Scan () {
122198 exclude [scanner .Text ()] = true
123199 }
0 commit comments