@@ -8,12 +8,14 @@ import (
88 "io/ioutil"
99 "log"
1010 "os"
11+ "path/filepath"
1112 "runtime"
1213 "strings"
1314 "time"
1415
1516 "github.com/fatih/color"
1617 "github.com/golangci/golangci-lint/pkg/config"
18+ "github.com/golangci/golangci-lint/pkg/fsutils"
1719 "github.com/golangci/golangci-lint/pkg/lint"
1820 "github.com/golangci/golangci-lint/pkg/lint/lintersdb"
1921 "github.com/golangci/golangci-lint/pkg/printers"
@@ -318,16 +320,80 @@ func (e *Executor) parseConfig() {
318320 return
319321 }
320322
321- if configFile == "" {
322- viper .SetConfigName (".golangci" )
323- viper .AddConfigPath ("./" )
324- } else {
323+ if configFile != "" {
325324 viper .SetConfigFile (configFile )
325+ } else {
326+ setupConfigFileSearch (fs .Args ())
326327 }
327328
328329 e .parseConfigImpl ()
329330}
330331
332+ func setupConfigFileSearch (args []string ) {
333+ // skip all args ([golangci-lint, run/linters]) before files/dirs list
334+ for len (args ) != 0 {
335+ if args [0 ] == "run" {
336+ args = args [1 :]
337+ break
338+ }
339+
340+ args = args [1 :]
341+ }
342+
343+ // find first file/dir arg
344+ firstArg := "./..."
345+ if len (args ) != 0 {
346+ firstArg = args [0 ]
347+ }
348+
349+ absStartPath , err := filepath .Abs (firstArg )
350+ if err != nil {
351+ logrus .Infof ("Can't make abs path for %q: %s" , firstArg , err )
352+ absStartPath = filepath .Clean (firstArg )
353+ }
354+
355+ // start from it
356+ var curDir string
357+ if fsutils .IsDir (absStartPath ) {
358+ curDir = absStartPath
359+ } else {
360+ curDir = filepath .Dir (absStartPath )
361+ }
362+
363+ // find all dirs from it up to the root
364+ configSearchPaths := []string {"./" }
365+ for {
366+ configSearchPaths = append (configSearchPaths , curDir )
367+ newCurDir := filepath .Dir (curDir )
368+ if curDir == newCurDir || newCurDir == "" {
369+ break
370+ }
371+ curDir = newCurDir
372+ }
373+
374+ logrus .Infof ("Config search paths: %s" , configSearchPaths )
375+ viper .SetConfigName (".golangci" )
376+ for _ , p := range configSearchPaths {
377+ viper .AddConfigPath (p )
378+ }
379+ }
380+
381+ func getRelPath (p string ) string {
382+ wd , err := os .Getwd ()
383+ if err != nil {
384+ logrus .Infof ("Can't get wd: %s" , err )
385+ return p
386+ }
387+
388+ r , err := filepath .Rel (wd , p )
389+ if err != nil {
390+ logrus .Infof ("Can't make path %s relative to %s: %s" , p , wd , err )
391+ return p
392+ }
393+
394+ return r
395+ }
396+
331397func (e * Executor ) parseConfigImpl () {
332398 commandLineConfig := * e .cfg // make copy
333399
@@ -338,13 +404,24 @@ func (e *Executor) parseConfigImpl() {
338404 logrus .Fatalf ("Can't read viper config: %s" , err )
339405 }
340406
407+ usedConfigFile := viper .ConfigFileUsed ()
408+ if usedConfigFile == "" {
409+ return
410+ }
411+ logrus .Infof ("Used config file %s" , getRelPath (usedConfigFile ))
412+
341413 if err := viper .Unmarshal (& e .cfg ); err != nil {
342414 logrus .Fatalf ("Can't unmarshal config by viper: %s" , err )
343415 }
344416
345417 if err := e .validateConfig (& commandLineConfig ); err != nil {
346418 logrus .Fatal (err )
347419 }
420+
421+ if e .cfg .InternalTest { // just for testing purposes: to detect config file usage
422+ fmt .Fprintln (printers .StdOut , "test" )
423+ os .Exit (0 )
424+ }
348425}
349426
350427func (e * Executor ) validateConfig (commandLineConfig * config.Config ) error {
0 commit comments