Skip to content

Commit c66ab9b

Browse files
author
Bryan C. Mills
committed
cmd/go: query modules in parallel
Refactor modload.QueryPackage and modload.QueryPattern to share code. Fine-tune error reporting and make it consistent between QueryPackage and QueryPattern. Expand tests for pattern errors. Update a TODO in modget/get.go and add a test case that demonstrates it. Updates #26232 Change-Id: I900ca8de338ef9a51b7f85ed93d8bcf837621646 Reviewed-on: https://go-review.googlesource.com/c/go/+/173017 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 8e4f1a7 commit c66ab9b

File tree

7 files changed

+302
-126
lines changed

7 files changed

+302
-126
lines changed

src/cmd/go/internal/modget/get.go

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"cmd/go/internal/semver"
2020
"cmd/go/internal/str"
2121
"cmd/go/internal/work"
22+
"errors"
2223
"fmt"
2324
"os"
2425
"path/filepath"
@@ -351,10 +352,17 @@ func runGet(cmd *base.Command, args []string) {
351352
match := search.MatchPattern(path)
352353
matched := false
353354
for _, m := range modload.BuildList() {
354-
// TODO(bcmills): Patterns that don't contain the module path but do
355-
// contain partial package paths will not match here. For example,
356-
// ...html/... would not match html/template or golang.org/x/net/html.
357-
// Related golang.org/issue/26902.
355+
// TODO: If we have matching packages already in the build list and we
356+
// know which module(s) they are in, then we should not upgrade the
357+
// modules that do *not* contain those packages, even if the module path
358+
// is a prefix of the pattern.
359+
//
360+
// For example, if we have modules golang.org/x/tools and
361+
// golang.org/x/tools/playground, and all of the packages matching
362+
// golang.org/x/tools/playground... are in the
363+
// golang.org/x/tools/playground module, then we should not *also* try
364+
// to upgrade golang.org/x/tools if the user says 'go get
365+
// golang.org/x/tools/playground...@latest'.
358366
if match(m.Path) || str.HasPathPrefix(path, m.Path) {
359367
tasks = append(tasks, &task{arg: arg, path: m.Path, vers: vers, prevM: m, forceModulePath: true})
360368
matched = true
@@ -650,29 +658,31 @@ func getQuery(path, vers string, prevM module.Version, forceModulePath bool) (mo
650658
}
651659
}
652660

653-
// If the path has a wildcard, search for a module that matches the pattern.
654-
if strings.Contains(path, "...") {
655-
if forceModulePath {
656-
panic("forceModulePath is true for path with wildcard " + path)
661+
if forceModulePath || *getM || !strings.Contains(path, "...") {
662+
if path == modload.Target.Path {
663+
if vers != "latest" {
664+
return module.Version{}, fmt.Errorf("can't get a specific version of the main module")
665+
}
666+
}
667+
668+
// If the path doesn't contain a wildcard, try interpreting it as a module path.
669+
info, err := modload.Query(path, vers, modload.Allowed)
670+
if err == nil {
671+
return module.Version{Path: path, Version: info.Version}, nil
657672
}
658-
_, m, _, err := modload.QueryPattern(path, vers, modload.Allowed)
659-
return m, err
660-
}
661673

662-
// Try interpreting the path as a module path.
663-
info, err := modload.Query(path, vers, modload.Allowed)
664-
if err == nil {
665-
return module.Version{Path: path, Version: info.Version}, nil
674+
// If the query fails, and the path must be a real module, report the query error.
675+
if forceModulePath || *getM {
676+
return module.Version{}, err
677+
}
666678
}
667679

668-
// If the query fails, and the path must be a real module, report the query error.
669-
if forceModulePath || *getM {
680+
// Otherwise, try a package path or pattern.
681+
results, err := modload.QueryPattern(path, vers, modload.Allowed)
682+
if err != nil {
670683
return module.Version{}, err
671684
}
672-
673-
// Otherwise, try a package path.
674-
m, _, err := modload.QueryPackage(path, vers, modload.Allowed)
675-
return m, err
685+
return results[0].Mod, nil
676686
}
677687

678688
// An upgrader adapts an underlying mvs.Reqs to apply an
@@ -736,7 +746,8 @@ func (u *upgrader) Upgrade(m module.Version) (module.Version, error) {
736746
// even report the error. Because Query does not consider pseudo-versions,
737747
// it may happen that we have a pseudo-version but during -u=patch
738748
// the query v0.0 matches no versions (not even the one we're using).
739-
if !strings.Contains(err.Error(), "no matching versions") {
749+
var noMatch *modload.NoMatchingVersionError
750+
if !errors.As(err, &noMatch) {
740751
base.Errorf("go get: upgrading %s@%s: %v", m.Path, m.Version, err)
741752
}
742753
return m, nil

src/cmd/go/internal/modload/import.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -186,22 +186,31 @@ func Import(path string) (m module.Version, dir string, err error) {
186186
}
187187
}
188188

189-
m, _, err = QueryPackage(path, "latest", Allowed)
189+
candidates, err := QueryPackage(path, "latest", Allowed)
190190
if err != nil {
191191
if _, ok := err.(*codehost.VCSError); ok {
192192
return module.Version{}, "", err
193193
}
194194
return module.Version{}, "", &ImportMissingError{ImportPath: path}
195195
}
196+
m = candidates[0].Mod
196197
newMissingVersion := ""
197-
for _, bm := range buildList {
198-
if bm.Path == m.Path && semver.Compare(bm.Version, m.Version) > 0 {
199-
// This typically happens when a package is present at the "@latest"
200-
// version (e.g., v1.0.0) of a module, but we have a newer version
201-
// of the same module in the build list (e.g., v1.0.1-beta), and
202-
// the package is not present there.
203-
newMissingVersion = bm.Version
204-
break
198+
for _, c := range candidates {
199+
cm := c.Mod
200+
for _, bm := range buildList {
201+
if bm.Path == cm.Path && semver.Compare(bm.Version, cm.Version) > 0 {
202+
// QueryPackage proposed that we add module cm to provide the package,
203+
// but we already depend on a newer version of that module (and we don't
204+
// have the package).
205+
//
206+
// This typically happens when a package is present at the "@latest"
207+
// version (e.g., v1.0.0) of a module, but we have a newer version
208+
// of the same module in the build list (e.g., v1.0.1-beta), and
209+
// the package is not present there.
210+
m = cm
211+
newMissingVersion = bm.Version
212+
break
213+
}
205214
}
206215
}
207216
return m, "", &ImportMissingError{ImportPath: path, Module: m, newMissingVersion: newMissingVersion}

0 commit comments

Comments
 (0)