internal/imports: use cache of mod cache pkgs in find packages
To check if a package is in a module that is in scope, the module
resolver checks if there are Go files that would be included in a
package in the directory matching the import path in scope.
If this directory is in the module cache and we have saved it as a
package, we know this directory contains Go files, and do not have to
read the directory.
Change-Id: I7c9365ce42c760ab95bc68b036212120895c89fb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/186922
Run-TryBot: Suzy Mueller <suzmue@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/imports/mod.go b/internal/imports/mod.go
index c9797be..98d5ff3 100644
--- a/internal/imports/mod.go
+++ b/internal/imports/mod.go
@@ -121,6 +121,17 @@
continue
}
+ if info, ok := r.moduleCacheInfo.Load(pkgDir); ok {
+ if packageScanned, err := info.reachedStatus(directoryScanned); packageScanned {
+ if err != nil {
+ // There was some error with scanning this directory.
+ // It does not contain a valid package.
+ continue
+ }
+ return m, pkgDir
+ }
+ }
+
pkgFiles, err := ioutil.ReadDir(pkgDir)
if err != nil {
continue
diff --git a/internal/imports/mod_cache.go b/internal/imports/mod_cache.go
index 884706a..ad28483 100644
--- a/internal/imports/mod_cache.go
+++ b/internal/imports/mod_cache.go
@@ -51,6 +51,18 @@
needsReplace bool
}
+// reachedStatus returns true when info has a status at least target and any error associated with
+// an attempt to reach target.
+func (info *directoryPackageInfo) reachedStatus(target directoryPackageStatus) (bool, error) {
+ if info.err == nil {
+ return info.status >= target, nil
+ }
+ if info.status == target {
+ return true, info.err
+ }
+ return true, nil
+}
+
// moduleCacheInfo is a concurrency safe map for storing information about
// the directories in the module cache.
//
diff --git a/internal/imports/mod_cache_test.go b/internal/imports/mod_cache_test.go
new file mode 100644
index 0000000..7d04560
--- /dev/null
+++ b/internal/imports/mod_cache_test.go
@@ -0,0 +1,52 @@
+package imports
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestDirectoryPackageInfoReachedStatus(t *testing.T) {
+ tests := []struct {
+ info directoryPackageInfo
+ target directoryPackageStatus
+ wantStatus bool
+ wantError bool
+ }{
+ {
+ info: directoryPackageInfo{
+ status: directoryScanned,
+ err: nil,
+ },
+ target: directoryScanned,
+ wantStatus: true,
+ },
+ {
+ info: directoryPackageInfo{
+ status: directoryScanned,
+ err: fmt.Errorf("error getting to directory scanned"),
+ },
+ target: directoryScanned,
+ wantStatus: true,
+ wantError: true,
+ },
+ {
+ info: directoryPackageInfo{},
+ target: directoryScanned,
+ wantStatus: false,
+ },
+ }
+
+ for _, tt := range tests {
+ gotStatus, gotErr := tt.info.reachedStatus(tt.target)
+ if gotErr != nil {
+ if !tt.wantError {
+ t.Errorf("unexpected error: %s", gotErr)
+ }
+ continue
+ }
+
+ if tt.wantStatus != gotStatus {
+ t.Errorf("reached status expected: %v, got: %v", tt.wantStatus, gotStatus)
+ }
+ }
+}