]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modload: avoid loading the full module graph when listing specific...
authorBryan C. Mills <bcmills@google.com>
Sat, 10 Apr 2021 03:40:22 +0000 (23:40 -0400)
committerBryan C. Mills <bcmills@google.com>
Fri, 30 Apr 2021 18:06:38 +0000 (18:06 +0000)
For #36460
For #41297
Updates #29666

Change-Id: I5f324c0ef9a164f8043d2188101d141bb5fa7454
Reviewed-on: https://go-review.googlesource.com/c/go/+/309191
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
src/cmd/go/internal/modload/list.go
src/cmd/go/testdata/script/mod_list_sums.txt

index 66927a82886aa4dc2f4433f979540fc3ab2a1919..344b2aa2c7912a13dffaeb3ef73163ba0b4a5fef 100644 (file)
@@ -82,19 +82,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                return rs, []*modinfo.ModulePublic{moduleInfo(ctx, rs, Target, mode)}, nil
        }
 
-       var mg *ModuleGraph
-       if go117LazyTODO {
-               // Pull the args-loop below into another (new) loop.
-               // If the main module is lazy, try it once with mg == nil, and then load mg
-               // and try again.
-       } else {
-               // TODO(#41297): Don't bother loading or expanding the graph if all
-               // arguments are explicit version queries (including if no arguments are
-               // present at all).
-               rs, mg, mgErr = expandGraph(ctx, rs)
-       }
-
-       matchedModule := map[module.Version]bool{}
+       needFullGraph := false
        for _, arg := range args {
                if strings.Contains(arg, `\`) {
                        base.Fatalf("go: module paths never use backslash")
@@ -102,19 +90,51 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                if search.IsRelativePath(arg) {
                        base.Fatalf("go: cannot use relative path %s to specify module", arg)
                }
-               if !HasModRoot() {
-                       if arg == "all" || strings.Contains(arg, "...") {
+               if arg == "all" || strings.Contains(arg, "...") {
+                       needFullGraph = true
+                       if !HasModRoot() {
                                base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
                        }
-                       if mode&ListVersions == 0 && !strings.Contains(arg, "@") {
+                       continue
+               }
+               if i := strings.Index(arg, "@"); i >= 0 {
+                       path := arg[:i]
+                       vers := arg[i+1:]
+                       if vers == "upgrade" || vers == "patch" {
+                               if _, ok := rs.rootSelected(path); !ok || rs.depth == eager {
+                                       needFullGraph = true
+                                       if !HasModRoot() {
+                                               base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
+                                       }
+                               }
+                       }
+                       continue
+               }
+               if _, ok := rs.rootSelected(arg); !ok || rs.depth == eager {
+                       needFullGraph = true
+                       if mode&ListVersions == 0 && !HasModRoot() {
                                base.Fatalf("go: cannot match %q without -versions or an explicit version: %v", arg, ErrNoModRoot)
                        }
                }
+       }
+
+       var mg *ModuleGraph
+       if needFullGraph {
+               rs, mg, mgErr = expandGraph(ctx, rs)
+       }
+
+       matchedModule := map[module.Version]bool{}
+       for _, arg := range args {
                if i := strings.Index(arg, "@"); i >= 0 {
                        path := arg[:i]
                        vers := arg[i+1:]
 
-                       current := mg.Selected(path)
+                       var current string
+                       if mg == nil {
+                               current, _ = rs.rootSelected(path)
+                       } else {
+                               current = mg.Selected(path)
+                       }
                        if current == "none" && mgErr != nil {
                                if vers == "upgrade" || vers == "patch" {
                                        // The module graph is incomplete, so we don't know what version we're
@@ -156,7 +176,18 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                } else if strings.Contains(arg, "...") {
                        match = search.MatchPattern(arg)
                } else {
-                       v := mg.Selected(arg)
+                       var v string
+                       if mg == nil {
+                               var ok bool
+                               v, ok = rs.rootSelected(arg)
+                               if !ok {
+                                       // We checked rootSelected(arg) in the earlier args loop, so if there
+                                       // is no such root we should have loaded a non-nil mg.
+                                       panic(fmt.Sprintf("internal error: root requirement expected but not found for %v", arg))
+                               }
+                       } else {
+                               v = mg.Selected(arg)
+                       }
                        if v == "none" && mgErr != nil {
                                // mgErr is already set, so just skip this module.
                                continue
index e5f80d7fb66372825def59301e705d78d662da8e..86c528f82907b0d2989b014bf49f154ba4b1353d 100644 (file)
@@ -4,16 +4,13 @@
 go mod init m
 go mod edit -require=rsc.io/quote@v1.5.1
 
-# 'go list' currently loads the whole build list, even when listing only
-# non-dependencies.
-#
-# TODO(#41297): Thes should not be errors.
+go list -m -mod=readonly rsc.io/quote@latest
+stdout '^rsc\.io/quote v1\.5\.2$'
+! stderr .
 
-! go list -m -mod=readonly rsc.io/quote@latest
-stderr '^go list -m: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n\tgo mod download rsc\.io/quote$'
-
-! go list -m -mod=readonly -versions rsc.io/quote
-stderr '^go list -m: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n\tgo mod download rsc\.io/quote$'
+go list -m -mod=readonly -versions rsc.io/quote
+stdout 'rsc\.io/quote v1\.0\.0 .* v1\.5\.3-pre1$'
+! stderr .
 
 # Incidentally fetching the required version of a module records its checksum,
 # just because it happens to be in the build list, and recording the checksum
@@ -21,8 +18,8 @@ stderr '^go list -m: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n
 #
 # TODO(#41297): This should not be an error.
 ! go list -m -mod=readonly rsc.io/quote@<v1.5.2
-stderr '^go list -m: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n\tgo mod download rsc\.io/quote$'
-! stderr '^go: updates to go.sum needed, disabled by -mod=readonly$'
+stderr '^go: updates to go.sum needed, disabled by -mod=readonly$'
+! stderr 'missing go.sum entry'
 
 # Attempting to list the versions of a module that is not a root dependency
 # causes the build list to be resolved (so that the selected version can *also*