r.performLocalQueries(ctx)
r.performPathQueries(ctx)
r.performToolQueries(ctx)
+ r.performWorkQueries(ctx)
for {
r.performWildcardQueries(ctx)
pathQueries []*query // package path literal queries in original order
wildcardQueries []*query // path wildcard queries in original order
patternAllQueries []*query // queries with the pattern "all"
+ workQueries []*query // queries with the pattern "work"
toolQueries []*query // queries with the pattern "tool"
// Indexed "none" queries. These are also included in the slices above;
for _, q := range queries {
if q.pattern == "all" {
r.patternAllQueries = append(r.patternAllQueries, q)
+ } else if q.pattern == "work" {
+ r.workQueries = append(r.workQueries, q)
} else if q.pattern == "tool" {
r.toolQueries = append(r.toolQueries, q)
} else if q.patternIsLocal {
}
}
+// performWorkQueries populates the candidates for each query whose pattern is "work".
+// The candidate module to resolve the work pattern is exactly the single main module.
+func (r *resolver) performWorkQueries(ctx context.Context) {
+ for _, q := range r.workQueries {
+ q.pathOnce(q.pattern, func() pathSet {
+ // TODO(matloob): Maybe export MainModules.mustGetSingleMainModule and call that.
+ // There are a few other places outside the modload package where we expect
+ // a single main module.
+ if len(modload.MainModules.Versions()) != 1 {
+ panic("internal error: number of main modules is not exactly one in resolution phase of go get")
+ }
+ mainModule := modload.MainModules.Versions()[0]
+
+ // We know what the result is going to be, assuming the main module is not
+ // empty, (it's the main module itself) but first check to see that there
+ // are packages in the main module, so that if there aren't any, we can
+ // return the expected warning that the pattern matched no packages.
+ match := modload.MatchInModule(ctx, q.pattern, mainModule, imports.AnyTags())
+ if len(match.Errs) > 0 {
+ return pathSet{err: match.Errs[0]}
+ }
+ if len(match.Pkgs) == 0 {
+ search.WarnUnmatched([]*search.Match{match})
+ return pathSet{} // There are no packages in the main module, so the main module isn't needed to resolve them.
+ }
+
+ return pathSet{pkgMods: []module.Version{mainModule}}
+ })
+ }
+}
+
// performPatternAllQueries populates the candidates for each query whose
// pattern is "all".
//
--- /dev/null
+# Test go get with the work pattern.
+
+# go get work gets dependencies to satisfy missing imports in the
+# main modules' package graph. Before the 'work' pattern existed, users
+# would have to run './...' in the root of the work (main) module.
+cp go.mod go.mod.orig
+go get work
+cmp go.mod go.mod.want
+
+# 'go get work' and 'go get all' behave very differently. Because
+# 'all' evaluates to work packages but also to their dependencies,
+# 'go get all' will run the 'get' logic on all the dependency module
+# packages, bumping all their modules to the latest versions.
+cp go.mod.orig go.mod
+go get all
+cmp go.mod go.mod.all.want
+-- go.mod --
+module example.com/a
+
+go 1.25
+-- go.mod.want --
+module example.com/a
+
+go 1.25
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.0 // indirect
+)
+-- go.mod.all.want --
+module example.com/a
+
+go 1.25
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.3.0 // indirect
+ rsc.io/sampler v1.99.99 // indirect
+)
+-- a.go --
+package a
+
+import _ "rsc.io/quote"