mirror of
https://github.com/golang/go
synced 2024-11-05 14:56:10 -07:00
imports: add configuration mechanism to exclude directories
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 <r@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
7c26c99973
commit
ffe4e61c64
@ -27,6 +27,18 @@ For GoSublime, follow the steps described here:
|
|||||||
|
|
||||||
For other editors, you probably know what to do.
|
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!
|
Happy hacking!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
package imports
|
package imports
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/build"
|
"go/build"
|
||||||
@ -311,10 +313,47 @@ var visitedSymlinks struct {
|
|||||||
m map[string]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.
|
// 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.
|
// It makes sure symlinks were never visited before to avoid symlink loops.
|
||||||
func shouldTraverse(dir string, fi os.FileInfo) bool {
|
func shouldTraverse(dir string, fi os.FileInfo) bool {
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
|
if skipDir(fi) {
|
||||||
|
if Debug {
|
||||||
|
log.Printf("skipping directory %q under %s", fi.Name(), dir)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,6 +421,9 @@ func scanGoDirs(goRoot bool) {
|
|||||||
if isGoroot != goRoot {
|
if isGoroot != goRoot {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !goRoot {
|
||||||
|
populateIgnoredDirs(path)
|
||||||
|
}
|
||||||
fsgate.enter()
|
fsgate.enter()
|
||||||
testHookScanDir(path)
|
testHookScanDir(path)
|
||||||
if Debug {
|
if Debug {
|
||||||
@ -554,7 +596,7 @@ func loadExportsGoPath(expectPackage, dir string) map[string]bool {
|
|||||||
exportList = append(exportList, k)
|
exportList = append(exportList, k)
|
||||||
}
|
}
|
||||||
sort.Strings(exportList)
|
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
|
return exports
|
||||||
}
|
}
|
||||||
|
@ -985,6 +985,7 @@ func withEmptyGoPath(fn func()) {
|
|||||||
scanGoRootOnce = &sync.Once{}
|
scanGoRootOnce = &sync.Once{}
|
||||||
scanGoPathOnce = &sync.Once{}
|
scanGoPathOnce = &sync.Once{}
|
||||||
dirScan = nil
|
dirScan = nil
|
||||||
|
ignoredDirs = nil
|
||||||
dirScanMu.Unlock()
|
dirScanMu.Unlock()
|
||||||
|
|
||||||
oldGOPATH := build.Default.GOPATH
|
oldGOPATH := build.Default.GOPATH
|
||||||
@ -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 {
|
func strSet(ss []string) map[string]bool {
|
||||||
m := make(map[string]bool)
|
m := make(map[string]bool)
|
||||||
for _, s := range ss {
|
for _, s := range ss {
|
||||||
|
Loading…
Reference in New Issue
Block a user