Skip to content

Commit

Permalink
imports: add configuration mechanism to exclude directories
Browse files Browse the repository at this point in the history
Each $GOPATH entry may have a file $GOPATH/src/.goimportsignore which
may contain blank lines, #comment lines, or lines naming a directory
relative to the configuration file to ignore when scanning.  No
globbing or regex patterns are allowed.

Updates golang/go#16367 (goimports speed)
Fixes golang/go#16386 (add mechanism to ignore directories)

Change-Id: I8f1a88ae6c4d0ed3075444d70aec3e2228c5ce6a
Reviewed-on: https://go-review.googlesource.com/24971
Reviewed-by: Rob Pike <[email protected]>
Run-TryBot: Brad Fitzpatrick <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
bradfitz committed Jul 15, 2016
1 parent 7c26c99 commit ffe4e61
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
12 changes: 12 additions & 0 deletions cmd/goimports/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ For GoSublime, follow the steps described here:
For other editors, you probably know what to do.
To exclude directories in your $GOPATH from being scanned for Go
files, goimports respects a configuration file at
$GOPATH/src/.goimportsignore which may contain blank lines, comment
lines (beginning with '#'), or lines naming a directory relative to
the configuration file to ignore when scanning. No globbing or regex
patterns are allowed. Use the "-v" verbose flag to verify it's
working and see what goimports is doing.
File bugs or feature requests at:
https://golang.org/issues/new?title=x/tools/cmd/goimports:+
Happy hacking!
*/
Expand Down
44 changes: 43 additions & 1 deletion imports/fix.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package imports

import (
"bufio"
"bytes"
"fmt"
"go/ast"
"go/build"
Expand Down Expand Up @@ -311,10 +313,47 @@ var visitedSymlinks struct {
m map[string]struct{}
}

var ignoredDirs []os.FileInfo

// populateIgnoredDirs reads an optional config file at <path>/.goimportsignore
// of relative directories to ignore when scanning for go files.
// The provided path is one of the $GOPATH entries with "src" appended.
func populateIgnoredDirs(path string) {
slurp, err := ioutil.ReadFile(filepath.Join(path, ".goimportsignore"))
if err != nil {
return
}
bs := bufio.NewScanner(bytes.NewReader(slurp))
for bs.Scan() {
line := strings.TrimSpace(bs.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
if fi, err := os.Stat(filepath.Join(path, line)); err == nil {
ignoredDirs = append(ignoredDirs, fi)
}
}
}

func skipDir(fi os.FileInfo) bool {
for _, ignoredDir := range ignoredDirs {
if os.SameFile(fi, ignoredDir) {
return true
}
}
return false
}

// shouldTraverse checks if fi, found in dir, is a directory or a symlink to a directory.
// It makes sure symlinks were never visited before to avoid symlink loops.
func shouldTraverse(dir string, fi os.FileInfo) bool {
if fi.IsDir() {
if skipDir(fi) {
if Debug {
log.Printf("skipping directory %q under %s", fi.Name(), dir)
}
return false
}
return true
}

Expand Down Expand Up @@ -382,6 +421,9 @@ func scanGoDirs(goRoot bool) {
if isGoroot != goRoot {
continue
}
if !goRoot {
populateIgnoredDirs(path)
}
fsgate.enter()
testHookScanDir(path)
if Debug {
Expand Down Expand Up @@ -554,7 +596,7 @@ func loadExportsGoPath(expectPackage, dir string) map[string]bool {
exportList = append(exportList, k)
}
sort.Strings(exportList)
log.Printf("scanned dir %v (package %v): exports = %v", dir, expectPackage, strings.Join(exportList, ", "))
log.Printf("loaded exports in dir %v (package %v): %v", dir, expectPackage, strings.Join(exportList, ", "))
}
return exports
}
Expand Down
21 changes: 21 additions & 0 deletions imports/fix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,7 @@ func withEmptyGoPath(fn func()) {
scanGoRootOnce = &sync.Once{}
scanGoPathOnce = &sync.Once{}
dirScan = nil
ignoredDirs = nil
dirScanMu.Unlock()

oldGOPATH := build.Default.GOPATH
Expand Down Expand Up @@ -1304,6 +1305,26 @@ func TestImportPathToNameGoPathParse(t *testing.T) {
})
}

func TestIgnoreConfiguration(t *testing.T) {
testConfig{
gopathFiles: map[string]string{
".goimportsignore": "# comment line\n\n example.net", // tests comment, blank line, whitespace trimming
"example.net/pkg/pkg.go": "package pkg\nconst X = 1",
"otherwise-longer-so-worse.example.net/foo/pkg/pkg.go": "package pkg\nconst X = 1",
},
}.test(t, func(t *goimportTest) {
const in = "package x\n\nconst _ = pkg.X\n"
const want = "package x\n\nimport \"otherwise-longer-so-worse.example.net/foo/pkg\"\n\nconst _ = pkg.X\n"
buf, err := Process(t.gopath+"/src/x/x.go", []byte(in), nil)
if err != nil {
t.Fatal(err)
}
if string(buf) != want {
t.Errorf("wrong output.\ngot:\n%q\nwant:\n%q\n", buf, want)
}
})
}

func strSet(ss []string) map[string]bool {
m := make(map[string]bool)
for _, s := range ss {
Expand Down

0 comments on commit ffe4e61

Please sign in to comment.