Skip to content

Commit

Permalink
cmd/go/internal/modload: avoid loading the full module graph when lis…
Browse files Browse the repository at this point in the history
…ting specific modules

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>
  • Loading branch information
Bryan C. Mills committed Apr 30, 2021
1 parent c05d50f commit 0e315ad
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 29 deletions.
67 changes: 49 additions & 18 deletions src/cmd/go/internal/modload/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,39 +82,59 @@ 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")
}
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
Expand Down Expand Up @@ -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
Expand Down
19 changes: 8 additions & 11 deletions src/cmd/go/testdata/script/mod_list_sums.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,22 @@
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
# triggers an error under -mod=readonly.
#
# 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*
Expand Down

0 comments on commit 0e315ad

Please sign in to comment.