1
2
3
4
5
6 package modget
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import (
28 "context"
29 "errors"
30 "fmt"
31 "os"
32 "path/filepath"
33 "runtime"
34 "sort"
35 "strconv"
36 "strings"
37 "sync"
38
39 "cmd/go/internal/base"
40 "cmd/go/internal/cfg"
41 "cmd/go/internal/gover"
42 "cmd/go/internal/imports"
43 "cmd/go/internal/modfetch"
44 "cmd/go/internal/modload"
45 "cmd/go/internal/search"
46 "cmd/go/internal/toolchain"
47 "cmd/go/internal/work"
48 "cmd/internal/par"
49
50 "golang.org/x/mod/modfile"
51 "golang.org/x/mod/module"
52 )
53
54 var CmdGet = &base.Command{
55
56
57 UsageLine: "go get [-t] [-u] [-tool] [build flags] [packages]",
58 Short: "add dependencies to current module and install them",
59 Long: `
60 Get resolves its command-line arguments to packages at specific module versions,
61 updates go.mod to require those versions, and downloads source code into the
62 module cache.
63
64 To add a dependency for a package or upgrade it to its latest version:
65
66 go get example.com/pkg
67
68 To upgrade or downgrade a package to a specific version:
69
70 go get example.com/pkg@v1.2.3
71
72 To remove a dependency on a module and downgrade modules that require it:
73
74 go get example.com/mod@none
75
76 To upgrade the minimum required Go version to the latest released Go version:
77
78 go get go@latest
79
80 To upgrade the Go toolchain to the latest patch release of the current Go toolchain:
81
82 go get toolchain@patch
83
84 See https://go.dev/ref/mod#go-get for details.
85
86 In earlier versions of Go, 'go get' was used to build and install packages.
87 Now, 'go get' is dedicated to adjusting dependencies in go.mod. 'go install'
88 may be used to build and install commands instead. When a version is specified,
89 'go install' runs in module-aware mode and ignores the go.mod file in the
90 current directory. For example:
91
92 go install example.com/pkg@v1.2.3
93 go install example.com/pkg@latest
94
95 See 'go help install' or https://go.dev/ref/mod#go-install for details.
96
97 'go get' accepts the following flags.
98
99 The -t flag instructs get to consider modules needed to build tests of
100 packages specified on the command line.
101
102 The -u flag instructs get to update modules providing dependencies
103 of packages named on the command line to use newer minor or patch
104 releases when available.
105
106 The -u=patch flag (not -u patch) also instructs get to update dependencies,
107 but changes the default to select patch releases.
108
109 When the -t and -u flags are used together, get will update
110 test dependencies as well.
111
112 The -tool flag instructs go to add a matching tool line to go.mod for each
113 listed package. If -tool is used with @none, the line will be removed.
114
115 The -x flag prints commands as they are executed. This is useful for
116 debugging version control commands when a module is downloaded directly
117 from a repository.
118
119 For more about build flags, see 'go help build'.
120
121 For more about modules, see https://go.dev/ref/mod.
122
123 For more about using 'go get' to update the minimum Go version and
124 suggested Go toolchain, see https://go.dev/doc/toolchain.
125
126 For more about specifying packages, see 'go help packages'.
127
128 See also: go build, go install, go clean, go mod.
129 `,
130 }
131
132 var HelpVCS = &base.Command{
133 UsageLine: "vcs",
134 Short: "controlling version control with GOVCS",
135 Long: `
136 The go command can run version control commands like git
137 to download imported code. This functionality is critical to the decentralized
138 Go package ecosystem, in which code can be imported from any server,
139 but it is also a potential security problem, if a malicious server finds a
140 way to cause the invoked version control command to run unintended code.
141
142 To balance the functionality and security concerns, the go command
143 by default will only use git and hg to download code from public servers.
144 But it will use any known version control system (bzr, fossil, git, hg, svn)
145 to download code from private servers, defined as those hosting packages
146 matching the GOPRIVATE variable (see 'go help private'). The rationale behind
147 allowing only Git and Mercurial is that these two systems have had the most
148 attention to issues of being run as clients of untrusted servers. In contrast,
149 Bazaar, Fossil, and Subversion have primarily been used in trusted,
150 authenticated environments and are not as well scrutinized as attack surfaces.
151
152 The version control command restrictions only apply when using direct version
153 control access to download code. When downloading modules from a proxy,
154 the go command uses the proxy protocol instead, which is always permitted.
155 By default, the go command uses the Go module mirror (proxy.golang.org)
156 for public packages and only falls back to version control for private
157 packages or when the mirror refuses to serve a public package (typically for
158 legal reasons). Therefore, clients can still access public code served from
159 Bazaar, Fossil, or Subversion repositories by default, because those downloads
160 use the Go module mirror, which takes on the security risk of running the
161 version control commands using a custom sandbox.
162
163 The GOVCS variable can be used to change the allowed version control systems
164 for specific packages (identified by a module or import path).
165 The GOVCS variable applies when building package in both module-aware mode
166 and GOPATH mode. When using modules, the patterns match against the module path.
167 When using GOPATH, the patterns match against the import path corresponding to
168 the root of the version control repository.
169
170 The general form of the GOVCS setting is a comma-separated list of
171 pattern:vcslist rules. The pattern is a glob pattern that must match
172 one or more leading elements of the module or import path. The vcslist
173 is a pipe-separated list of allowed version control commands, or "all"
174 to allow use of any known command, or "off" to disallow all commands.
175 Note that if a module matches a pattern with vcslist "off", it may still be
176 downloaded if the origin server uses the "mod" scheme, which instructs the
177 go command to download the module using the GOPROXY protocol.
178 The earliest matching pattern in the list applies, even if later patterns
179 might also match.
180
181 For example, consider:
182
183 GOVCS=github.com:git,evil.com:off,*:git|hg
184
185 With this setting, code with a module or import path beginning with
186 github.com/ can only use git; paths on evil.com cannot use any version
187 control command, and all other paths (* matches everything) can use
188 only git or hg.
189
190 The special patterns "public" and "private" match public and private
191 module or import paths. A path is private if it matches the GOPRIVATE
192 variable; otherwise it is public.
193
194 If no rules in the GOVCS variable match a particular module or import path,
195 the 'go get' command applies its default rule, which can now be summarized
196 in GOVCS notation as 'public:git|hg,private:all'.
197
198 To allow unfettered use of any version control system for any package, use:
199
200 GOVCS=*:all
201
202 To disable all use of version control, use:
203
204 GOVCS=*:off
205
206 The 'go env -w' command (see 'go help env') can be used to set the GOVCS
207 variable for future go command invocations.
208 `,
209 }
210
211 var (
212 getD dFlag
213 getF = CmdGet.Flag.Bool("f", false, "")
214 getFix = CmdGet.Flag.Bool("fix", false, "")
215 getM = CmdGet.Flag.Bool("m", false, "")
216 getT = CmdGet.Flag.Bool("t", false, "")
217 getU upgradeFlag
218 getTool = CmdGet.Flag.Bool("tool", false, "")
219 getInsecure = CmdGet.Flag.Bool("insecure", false, "")
220 )
221
222
223 type upgradeFlag struct {
224 rawVersion string
225 version string
226 }
227
228 func (*upgradeFlag) IsBoolFlag() bool { return true }
229
230 func (v *upgradeFlag) Set(s string) error {
231 if s == "false" {
232 v.version = ""
233 v.rawVersion = ""
234 } else if s == "true" {
235 v.version = "upgrade"
236 v.rawVersion = ""
237 } else {
238 v.version = s
239 v.rawVersion = s
240 }
241 return nil
242 }
243
244 func (v *upgradeFlag) String() string { return "" }
245
246
247
248
249 type dFlag struct {
250 value bool
251 set bool
252 }
253
254 func (v *dFlag) IsBoolFlag() bool { return true }
255
256 func (v *dFlag) Set(s string) error {
257 v.set = true
258 value, err := strconv.ParseBool(s)
259 if err != nil {
260 err = errors.New("parse error")
261 }
262 v.value = value
263 return err
264 }
265
266 func (b *dFlag) String() string { return "" }
267
268 func init() {
269 work.AddBuildFlags(CmdGet, work.OmitModFlag)
270 CmdGet.Run = runGet
271 CmdGet.Flag.Var(&getD, "d", "")
272 CmdGet.Flag.Var(&getU, "u", "")
273 }
274
275 func runGet(ctx context.Context, cmd *base.Command, args []string) {
276 moduleLoaderState := modload.NewState()
277 switch getU.version {
278 case "", "upgrade", "patch":
279
280 default:
281 base.Fatalf("go: unknown upgrade flag -u=%s", getU.rawVersion)
282 }
283 if getD.set {
284 if !getD.value {
285 base.Fatalf("go: -d flag may not be set to false")
286 }
287 fmt.Fprintf(os.Stderr, "go: -d flag is deprecated. -d=true is a no-op\n")
288 }
289 if *getF {
290 fmt.Fprintf(os.Stderr, "go: -f flag is a no-op\n")
291 }
292 if *getFix {
293 fmt.Fprintf(os.Stderr, "go: -fix flag is a no-op\n")
294 }
295 if *getM {
296 base.Fatalf("go: -m flag is no longer supported")
297 }
298 if *getInsecure {
299 base.Fatalf("go: -insecure flag is no longer supported; use GOINSECURE instead")
300 }
301
302 moduleLoaderState.ForceUseModules = true
303
304
305
306
307 modload.ExplicitWriteGoMod = true
308
309
310
311 moduleLoaderState.AllowMissingModuleImports()
312
313
314
315
316
317 modload.Init(moduleLoaderState)
318 if !moduleLoaderState.HasModRoot() {
319 base.Fatalf("go: go.mod file not found in current directory or any parent directory.\n" +
320 "\t'go get' is no longer supported outside a module.\n" +
321 "\tTo build and install a command, use 'go install' with a version,\n" +
322 "\tlike 'go install example.com/cmd@latest'\n" +
323 "\tFor more information, see https://go.dev/doc/go-get-install-deprecation\n" +
324 "\tor run 'go help get' or 'go help install'.")
325 }
326
327 dropToolchain, queries := parseArgs(moduleLoaderState, ctx, args)
328 opts := modload.WriteOpts{
329 DropToolchain: dropToolchain,
330 }
331 for _, q := range queries {
332 if q.pattern == "toolchain" {
333 opts.ExplicitToolchain = true
334 }
335 }
336
337 r := newResolver(moduleLoaderState, ctx, queries)
338 r.performLocalQueries(moduleLoaderState, ctx)
339 r.performPathQueries(moduleLoaderState, ctx)
340 r.performToolQueries(moduleLoaderState, ctx)
341 r.performWorkQueries(moduleLoaderState, ctx)
342
343 for {
344 r.performWildcardQueries(moduleLoaderState, ctx)
345 r.performPatternAllQueries(moduleLoaderState, ctx)
346
347 if changed := r.resolveQueries(moduleLoaderState, ctx, queries); changed {
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 continue
370 }
371
372
373
374
375
376
377
378
379
380
381
382
383 upgrades := r.findAndUpgradeImports(moduleLoaderState, ctx, queries)
384 if changed := r.applyUpgrades(moduleLoaderState, ctx, upgrades); changed {
385 continue
386 }
387
388 r.findMissingWildcards(moduleLoaderState, ctx)
389 if changed := r.resolveQueries(moduleLoaderState, ctx, r.wildcardQueries); changed {
390 continue
391 }
392
393 break
394 }
395
396 r.checkWildcardVersions(moduleLoaderState, ctx)
397
398 var pkgPatterns []string
399 for _, q := range queries {
400 if q.matchesPackages {
401 pkgPatterns = append(pkgPatterns, q.pattern)
402 }
403 }
404
405 if *getTool {
406 updateTools(moduleLoaderState, ctx, r, queries, &opts)
407 }
408
409
410
411 r.checkPackageProblems(moduleLoaderState, ctx, pkgPatterns)
412
413
414 oldReqs := reqsFromGoMod(modload.ModFile(moduleLoaderState))
415
416 if err := modload.WriteGoMod(moduleLoaderState, ctx, opts); err != nil {
417
418
419
420
421
422 toolchain.SwitchOrFatal(moduleLoaderState, ctx, err)
423 }
424
425 newReqs := reqsFromGoMod(modload.ModFile(moduleLoaderState))
426 r.reportChanges(oldReqs, newReqs)
427
428 if gowork := moduleLoaderState.FindGoWork(base.Cwd()); gowork != "" {
429 wf, err := modload.ReadWorkFile(gowork)
430 if err == nil && modload.UpdateWorkGoVersion(wf, moduleLoaderState.MainModules.GoVersion(moduleLoaderState)) {
431 modload.WriteWorkFile(gowork, wf)
432 }
433 }
434 }
435
436 func updateTools(loaderstate *modload.State, ctx context.Context, r *resolver, queries []*query, opts *modload.WriteOpts) {
437 pkgOpts := modload.PackageOpts{
438 VendorModulesInGOROOTSrc: true,
439 LoadTests: *getT,
440 ResolveMissingImports: false,
441 AllowErrors: true,
442 SilenceNoGoErrors: true,
443 }
444 patterns := []string{}
445 for _, q := range queries {
446 if search.IsMetaPackage(q.pattern) || q.pattern == "toolchain" {
447 base.Fatalf("go: go get -tool does not work with \"%s\".", q.pattern)
448 }
449 patterns = append(patterns, q.pattern)
450 }
451
452 matches, _ := modload.LoadPackages(loaderstate, ctx, pkgOpts, patterns...)
453 for i, m := range matches {
454 if queries[i].version == "none" {
455 opts.DropTools = append(opts.DropTools, m.Pkgs...)
456 } else {
457 opts.AddTools = append(opts.AddTools, m.Pkgs...)
458 }
459 }
460
461 mg, err := modload.LoadModGraph(loaderstate, ctx, "")
462 if err != nil {
463 toolchain.SwitchOrFatal(loaderstate, ctx, err)
464 }
465 r.buildList = mg.BuildList()
466 r.buildListVersion = make(map[string]string, len(r.buildList))
467 for _, m := range r.buildList {
468 r.buildListVersion[m.Path] = m.Version
469 }
470 }
471
472
473
474
475
476 func parseArgs(loaderstate *modload.State, ctx context.Context, rawArgs []string) (dropToolchain bool, queries []*query) {
477 defer base.ExitIfErrors()
478
479 for _, arg := range search.CleanPatterns(rawArgs) {
480 q, err := newQuery(loaderstate, arg)
481 if err != nil {
482 base.Error(err)
483 continue
484 }
485
486 if q.version == "none" {
487 switch q.pattern {
488 case "go":
489 base.Errorf("go: cannot use go@none")
490 continue
491 case "toolchain":
492 dropToolchain = true
493 continue
494 }
495 }
496
497
498
499 if len(rawArgs) == 0 {
500 q.raw = ""
501 }
502
503
504
505
506 if strings.HasSuffix(q.raw, ".go") && q.rawVersion == "" {
507 if !strings.Contains(q.raw, "/") {
508 base.Errorf("go: %s: arguments must be package or module paths", q.raw)
509 continue
510 }
511 if fi, err := os.Stat(q.raw); err == nil && !fi.IsDir() {
512 base.Errorf("go: %s exists as a file, but 'go get' requires package arguments", q.raw)
513 continue
514 }
515 }
516
517 queries = append(queries, q)
518 }
519
520 return dropToolchain, queries
521 }
522
523 type resolver struct {
524 localQueries []*query
525 pathQueries []*query
526 wildcardQueries []*query
527 patternAllQueries []*query
528 workQueries []*query
529 toolQueries []*query
530
531
532
533 nonesByPath map[string]*query
534 wildcardNones []*query
535
536
537
538
539 resolvedVersion map[string]versionReason
540
541 buildList []module.Version
542 buildListVersion map[string]string
543
544 initialVersion map[string]string
545
546 missing []pathSet
547
548 work *par.Queue
549
550 matchInModuleCache par.ErrCache[matchInModuleKey, []string]
551
552
553
554 workspace *workspace
555 }
556
557 type versionReason struct {
558 version string
559 reason *query
560 }
561
562 type matchInModuleKey struct {
563 pattern string
564 m module.Version
565 }
566
567 func newResolver(loaderstate *modload.State, ctx context.Context, queries []*query) *resolver {
568
569
570 mg, err := modload.LoadModGraph(loaderstate, ctx, "")
571 if err != nil {
572 toolchain.SwitchOrFatal(loaderstate, ctx, err)
573 }
574
575 buildList := mg.BuildList()
576 initialVersion := make(map[string]string, len(buildList))
577 for _, m := range buildList {
578 initialVersion[m.Path] = m.Version
579 }
580
581 r := &resolver{
582 work: par.NewQueue(runtime.GOMAXPROCS(0)),
583 resolvedVersion: map[string]versionReason{},
584 buildList: buildList,
585 buildListVersion: initialVersion,
586 initialVersion: initialVersion,
587 nonesByPath: map[string]*query{},
588 workspace: loadWorkspace(loaderstate.FindGoWork(base.Cwd())),
589 }
590
591 for _, q := range queries {
592 if q.pattern == "all" {
593 r.patternAllQueries = append(r.patternAllQueries, q)
594 } else if q.pattern == "work" {
595 r.workQueries = append(r.workQueries, q)
596 } else if q.pattern == "tool" {
597 r.toolQueries = append(r.toolQueries, q)
598 } else if q.patternIsLocal {
599 r.localQueries = append(r.localQueries, q)
600 } else if q.isWildcard() {
601 r.wildcardQueries = append(r.wildcardQueries, q)
602 } else {
603 r.pathQueries = append(r.pathQueries, q)
604 }
605
606 if q.version == "none" {
607
608 if q.isWildcard() {
609 r.wildcardNones = append(r.wildcardNones, q)
610 } else {
611
612
613 r.nonesByPath[q.pattern] = q
614 }
615 }
616 }
617
618 return r
619 }
620
621
622
623 func (r *resolver) initialSelected(mPath string) (version string) {
624 v, ok := r.initialVersion[mPath]
625 if !ok {
626 return "none"
627 }
628 return v
629 }
630
631
632
633 func (r *resolver) selected(mPath string) (version string) {
634 v, ok := r.buildListVersion[mPath]
635 if !ok {
636 return "none"
637 }
638 return v
639 }
640
641
642
643 func (r *resolver) noneForPath(mPath string) (nq *query, found bool) {
644 if nq = r.nonesByPath[mPath]; nq != nil {
645 return nq, true
646 }
647 for _, nq := range r.wildcardNones {
648 if nq.matchesPath(mPath) {
649 return nq, true
650 }
651 }
652 return nil, false
653 }
654
655
656
657 func (r *resolver) queryModule(loaderstate *modload.State, ctx context.Context, mPath, query string, selected func(string) string) (module.Version, error) {
658 current := r.initialSelected(mPath)
659 rev, err := modload.Query(loaderstate, ctx, mPath, query, current, r.checkAllowedOr(loaderstate, query, selected))
660 if err != nil {
661 return module.Version{}, err
662 }
663 return module.Version{Path: mPath, Version: rev.Version}, nil
664 }
665
666
667
668 func (r *resolver) queryPackages(loaderstate *modload.State, ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, err error) {
669 results, err := modload.QueryPackages(loaderstate, ctx, pattern, query, selected, r.checkAllowedOr(loaderstate, query, selected))
670 if len(results) > 0 {
671 pkgMods = make([]module.Version, 0, len(results))
672 for _, qr := range results {
673 pkgMods = append(pkgMods, qr.Mod)
674 }
675 }
676 return pkgMods, err
677 }
678
679
680
681 func (r *resolver) queryPattern(loaderstate *modload.State, ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, mod module.Version, err error) {
682 results, modOnly, err := modload.QueryPattern(loaderstate, ctx, pattern, query, selected, r.checkAllowedOr(loaderstate, query, selected))
683 if len(results) > 0 {
684 pkgMods = make([]module.Version, 0, len(results))
685 for _, qr := range results {
686 pkgMods = append(pkgMods, qr.Mod)
687 }
688 }
689 if modOnly != nil {
690 mod = modOnly.Mod
691 }
692 return pkgMods, mod, err
693 }
694
695
696
697 func (r *resolver) checkAllowedOr(s *modload.State, requested string, selected func(string) string) modload.AllowedFunc {
698 return func(ctx context.Context, m module.Version) error {
699 if m.Version == requested {
700 return s.CheckExclusions(ctx, m)
701 }
702 if (requested == "upgrade" || requested == "patch") && m.Version == selected(m.Path) {
703 return nil
704 }
705 return s.CheckAllowed(ctx, m)
706 }
707 }
708
709
710 func (r *resolver) matchInModule(loaderstate *modload.State, ctx context.Context, pattern string, m module.Version) (packages []string, err error) {
711 return r.matchInModuleCache.Do(matchInModuleKey{pattern, m}, func() ([]string, error) {
712 match := modload.MatchInModule(loaderstate, ctx, pattern, m, imports.AnyTags())
713 if len(match.Errs) > 0 {
714 return match.Pkgs, match.Errs[0]
715 }
716 return match.Pkgs, nil
717 })
718 }
719
720
721
722
723
724
725
726
727
728 func (r *resolver) queryNone(loaderstate *modload.State, ctx context.Context, q *query) {
729 if search.IsMetaPackage(q.pattern) {
730 panic(fmt.Sprintf("internal error: queryNone called with pattern %q", q.pattern))
731 }
732
733 if !q.isWildcard() {
734 q.pathOnce(q.pattern, func() pathSet {
735 hasModRoot := loaderstate.HasModRoot()
736 if hasModRoot && loaderstate.MainModules.Contains(q.pattern) {
737 v := module.Version{Path: q.pattern}
738
739
740
741
742
743
744
745
746
747
748 return errSet(&modload.QueryMatchesMainModulesError{
749 MainModules: []module.Version{v},
750 Pattern: q.pattern,
751 Query: q.version,
752 PatternIsModule: loaderstate.MainModules.Contains(q.pattern),
753 })
754 }
755
756 return pathSet{mod: module.Version{Path: q.pattern, Version: "none"}}
757 })
758 }
759
760 for _, curM := range r.buildList {
761 if !q.matchesPath(curM.Path) {
762 continue
763 }
764 q.pathOnce(curM.Path, func() pathSet {
765 if loaderstate.HasModRoot() && curM.Version == "" && loaderstate.MainModules.Contains(curM.Path) {
766 return errSet(&modload.QueryMatchesMainModulesError{
767 MainModules: []module.Version{curM},
768 Pattern: q.pattern,
769 Query: q.version,
770 PatternIsModule: loaderstate.MainModules.Contains(q.pattern),
771 })
772 }
773 return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}}
774 })
775 }
776 }
777
778 func (r *resolver) performLocalQueries(loaderstate *modload.State, ctx context.Context) {
779 for _, q := range r.localQueries {
780 q.pathOnce(q.pattern, func() pathSet {
781 absDetail := ""
782 if !filepath.IsAbs(q.pattern) {
783 if absPath, err := filepath.Abs(q.pattern); err == nil {
784 absDetail = fmt.Sprintf(" (%s)", absPath)
785 }
786 }
787
788
789
790 pkgPattern, mainModule := loaderstate.MainModules.DirImportPath(loaderstate, ctx, q.pattern)
791 if pkgPattern == "." {
792 loaderstate.MustHaveModRoot()
793 versions := loaderstate.MainModules.Versions()
794 modRoots := make([]string, 0, len(versions))
795 for _, m := range versions {
796 modRoots = append(modRoots, loaderstate.MainModules.ModRoot(m))
797 }
798 var plural string
799 if len(modRoots) != 1 {
800 plural = "s"
801 }
802 return errSet(fmt.Errorf("%s%s is not within module%s rooted at %s", q.pattern, absDetail, plural, strings.Join(modRoots, ", ")))
803 }
804
805 match := modload.MatchInModule(loaderstate, ctx, pkgPattern, mainModule, imports.AnyTags())
806 if len(match.Errs) > 0 {
807 return pathSet{err: match.Errs[0]}
808 }
809
810 if len(match.Pkgs) == 0 {
811 if q.raw == "" || q.raw == "." {
812 return errSet(fmt.Errorf("no package to get in current directory"))
813 }
814 if !q.isWildcard() {
815 loaderstate.MustHaveModRoot()
816 return errSet(fmt.Errorf("%s%s is not a package in module rooted at %s", q.pattern, absDetail, loaderstate.MainModules.ModRoot(mainModule)))
817 }
818 search.WarnUnmatched([]*search.Match{match})
819 return pathSet{}
820 }
821
822 return pathSet{pkgMods: []module.Version{mainModule}}
823 })
824 }
825 }
826
827
828
829
830
831
832
833
834
835 func (r *resolver) performWildcardQueries(loaderstate *modload.State, ctx context.Context) {
836 for _, q := range r.wildcardQueries {
837 q := q
838 r.work.Add(func() {
839 if q.version == "none" {
840 r.queryNone(loaderstate, ctx, q)
841 } else {
842 r.queryWildcard(loaderstate, ctx, q)
843 }
844 })
845 }
846 <-r.work.Idle()
847 }
848
849
850
851
852
853
854 func (r *resolver) queryWildcard(loaderstate *modload.State, ctx context.Context, q *query) {
855
856
857
858
859
860
861 for _, curM := range r.buildList {
862 if !q.canMatchInModule(curM.Path) {
863 continue
864 }
865 q.pathOnce(curM.Path, func() pathSet {
866 if _, hit := r.noneForPath(curM.Path); hit {
867
868
869 return pathSet{}
870 }
871
872 if loaderstate.MainModules.Contains(curM.Path) && !versionOkForMainModule(q.version) {
873 if q.matchesPath(curM.Path) {
874 return errSet(&modload.QueryMatchesMainModulesError{
875 MainModules: []module.Version{curM},
876 Pattern: q.pattern,
877 Query: q.version,
878 PatternIsModule: loaderstate.MainModules.Contains(q.pattern),
879 })
880 }
881
882 packages, err := r.matchInModule(loaderstate, ctx, q.pattern, curM)
883 if err != nil {
884 return errSet(err)
885 }
886 if len(packages) > 0 {
887 return errSet(&modload.QueryMatchesPackagesInMainModuleError{
888 Pattern: q.pattern,
889 Query: q.version,
890 Packages: packages,
891 })
892 }
893
894 return r.tryWildcard(loaderstate, ctx, q, curM)
895 }
896
897 m, err := r.queryModule(loaderstate, ctx, curM.Path, q.version, r.initialSelected)
898 if err != nil {
899 if !isNoSuchModuleVersion(err) {
900
901 return errSet(err)
902 }
903
904
905
906
907
908
909
910
911
912
913
914
915
916 return pathSet{}
917 }
918
919 return r.tryWildcard(loaderstate, ctx, q, m)
920 })
921 }
922
923
924
925
926 }
927
928
929
930 func (r *resolver) tryWildcard(loaderstate *modload.State, ctx context.Context, q *query, m module.Version) pathSet {
931 mMatches := q.matchesPath(m.Path)
932 packages, err := r.matchInModule(loaderstate, ctx, q.pattern, m)
933 if err != nil {
934 return errSet(err)
935 }
936 if len(packages) > 0 {
937 return pathSet{pkgMods: []module.Version{m}}
938 }
939 if mMatches {
940 return pathSet{mod: m}
941 }
942 return pathSet{}
943 }
944
945
946
947 func (r *resolver) findMissingWildcards(loaderstate *modload.State, ctx context.Context) {
948 for _, q := range r.wildcardQueries {
949 if q.version == "none" || q.matchesPackages {
950 continue
951 }
952 r.work.Add(func() {
953 q.pathOnce(q.pattern, func() pathSet {
954 pkgMods, mod, err := r.queryPattern(loaderstate, ctx, q.pattern, q.version, r.initialSelected)
955 if err != nil {
956 if isNoSuchPackageVersion(err) && len(q.resolved) > 0 {
957
958
959
960 return pathSet{}
961 }
962 return errSet(err)
963 }
964
965 return pathSet{pkgMods: pkgMods, mod: mod}
966 })
967 })
968 }
969 <-r.work.Idle()
970 }
971
972
973
974
975 func (r *resolver) checkWildcardVersions(loaderstate *modload.State, ctx context.Context) {
976 defer base.ExitIfErrors()
977
978 for _, q := range r.wildcardQueries {
979 for _, curM := range r.buildList {
980 if !q.canMatchInModule(curM.Path) {
981 continue
982 }
983 if !q.matchesPath(curM.Path) {
984 packages, err := r.matchInModule(loaderstate, ctx, q.pattern, curM)
985 if len(packages) == 0 {
986 if err != nil {
987 reportError(q, err)
988 }
989 continue
990 }
991 }
992
993 rev, err := r.queryModule(loaderstate, ctx, curM.Path, q.version, r.initialSelected)
994 if err != nil {
995 reportError(q, err)
996 continue
997 }
998 if rev.Version == curM.Version {
999 continue
1000 }
1001
1002 if !q.matchesPath(curM.Path) {
1003 m := module.Version{Path: curM.Path, Version: rev.Version}
1004 packages, err := r.matchInModule(loaderstate, ctx, q.pattern, m)
1005 if err != nil {
1006 reportError(q, err)
1007 continue
1008 }
1009 if len(packages) == 0 {
1010
1011
1012
1013 var version any = m
1014 if rev.Version != q.version {
1015 version = fmt.Sprintf("%s@%s (%s)", m.Path, q.version, m.Version)
1016 }
1017 reportError(q, fmt.Errorf("%v matches packages in %v but not %v: specify a different version for module %s", q, curM, version, m.Path))
1018 continue
1019 }
1020 }
1021
1022
1023
1024
1025
1026
1027 reportError(q, fmt.Errorf("internal error: selected %v instead of %v", curM, rev.Version))
1028 }
1029 }
1030 }
1031
1032
1033
1034
1035
1036
1037
1038 func (r *resolver) performPathQueries(loaderstate *modload.State, ctx context.Context) {
1039 for _, q := range r.pathQueries {
1040 q := q
1041 r.work.Add(func() {
1042 if q.version == "none" {
1043 r.queryNone(loaderstate, ctx, q)
1044 } else {
1045 r.queryPath(loaderstate, ctx, q)
1046 }
1047 })
1048 }
1049 <-r.work.Idle()
1050 }
1051
1052
1053
1054
1055
1056 func (r *resolver) queryPath(loaderstate *modload.State, ctx context.Context, q *query) {
1057 q.pathOnce(q.pattern, func() pathSet {
1058 if search.IsMetaPackage(q.pattern) || q.isWildcard() {
1059 panic(fmt.Sprintf("internal error: queryPath called with pattern %q", q.pattern))
1060 }
1061 if q.version == "none" {
1062 panic(`internal error: queryPath called with version "none"`)
1063 }
1064
1065 if search.IsStandardImportPath(q.pattern) {
1066 stdOnly := module.Version{}
1067 packages, _ := r.matchInModule(loaderstate, ctx, q.pattern, stdOnly)
1068 if len(packages) > 0 {
1069 if q.rawVersion != "" {
1070 return errSet(fmt.Errorf("can't request explicit version %q of standard library package %s", q.version, q.pattern))
1071 }
1072
1073 q.matchesPackages = true
1074 return pathSet{}
1075 }
1076 }
1077
1078 pkgMods, mod, err := r.queryPattern(loaderstate, ctx, q.pattern, q.version, r.initialSelected)
1079 if err != nil {
1080 return errSet(err)
1081 }
1082 return pathSet{pkgMods: pkgMods, mod: mod}
1083 })
1084 }
1085
1086
1087
1088 func (r *resolver) performToolQueries(loaderstate *modload.State, ctx context.Context) {
1089 for _, q := range r.toolQueries {
1090 for tool := range loaderstate.MainModules.Tools() {
1091 q.pathOnce(tool, func() pathSet {
1092 pkgMods, err := r.queryPackages(loaderstate, ctx, tool, q.version, r.initialSelected)
1093 return pathSet{pkgMods: pkgMods, err: err}
1094 })
1095 }
1096 }
1097 }
1098
1099
1100
1101 func (r *resolver) performWorkQueries(loaderstate *modload.State, ctx context.Context) {
1102 for _, q := range r.workQueries {
1103 q.pathOnce(q.pattern, func() pathSet {
1104
1105
1106
1107 if len(loaderstate.MainModules.Versions()) != 1 {
1108 panic("internal error: number of main modules is not exactly one in resolution phase of go get")
1109 }
1110 mainModule := loaderstate.MainModules.Versions()[0]
1111
1112
1113
1114
1115
1116 match := modload.MatchInModule(loaderstate, ctx, q.pattern, mainModule, imports.AnyTags())
1117 if len(match.Errs) > 0 {
1118 return pathSet{err: match.Errs[0]}
1119 }
1120 if len(match.Pkgs) == 0 {
1121 search.WarnUnmatched([]*search.Match{match})
1122 return pathSet{}
1123 }
1124
1125 return pathSet{pkgMods: []module.Version{mainModule}}
1126 })
1127 }
1128 }
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138 func (r *resolver) performPatternAllQueries(loaderstate *modload.State, ctx context.Context) {
1139 if len(r.patternAllQueries) == 0 {
1140 return
1141 }
1142
1143 findPackage := func(ctx context.Context, path string, m module.Version) (versionOk bool) {
1144 versionOk = true
1145 for _, q := range r.patternAllQueries {
1146 q.pathOnce(path, func() pathSet {
1147 pkgMods, err := r.queryPackages(loaderstate, ctx, path, q.version, r.initialSelected)
1148 if len(pkgMods) != 1 || pkgMods[0] != m {
1149
1150
1151
1152
1153
1154 versionOk = false
1155 }
1156 return pathSet{pkgMods: pkgMods, err: err}
1157 })
1158 }
1159 return versionOk
1160 }
1161
1162 r.loadPackages(loaderstate, ctx, []string{"all"}, findPackage)
1163
1164
1165
1166
1167
1168 for _, q := range r.patternAllQueries {
1169 sort.Slice(q.candidates, func(i, j int) bool {
1170 return q.candidates[i].path < q.candidates[j].path
1171 })
1172 }
1173 }
1174
1175
1176
1177
1178
1179
1180
1181
1182 func (r *resolver) findAndUpgradeImports(loaderstate *modload.State, ctx context.Context, queries []*query) (upgrades []pathSet) {
1183 patterns := make([]string, 0, len(queries))
1184 for _, q := range queries {
1185 if q.matchesPackages {
1186 patterns = append(patterns, q.pattern)
1187 }
1188 }
1189 if len(patterns) == 0 {
1190 return nil
1191 }
1192
1193
1194
1195 var mu sync.Mutex
1196
1197 findPackage := func(ctx context.Context, path string, m module.Version) (versionOk bool) {
1198 version := "latest"
1199 if m.Path != "" {
1200 if getU.version == "" {
1201
1202 return true
1203 }
1204 if _, ok := r.resolvedVersion[m.Path]; ok {
1205
1206
1207 return true
1208 }
1209 version = getU.version
1210 }
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223 pkgMods, err := r.queryPackages(loaderstate, ctx, path, version, r.selected)
1224 for _, u := range pkgMods {
1225 if u == m {
1226
1227
1228 return true
1229 }
1230 }
1231
1232 if err != nil {
1233 if isNoSuchPackageVersion(err) || (m.Path == "" && module.CheckPath(path) != nil) {
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244 return true
1245 }
1246 }
1247
1248 mu.Lock()
1249 upgrades = append(upgrades, pathSet{path: path, pkgMods: pkgMods, err: err})
1250 mu.Unlock()
1251 return false
1252 }
1253
1254 r.loadPackages(loaderstate, ctx, patterns, findPackage)
1255
1256
1257
1258
1259
1260 sort.Slice(upgrades, func(i, j int) bool {
1261 return upgrades[i].path < upgrades[j].path
1262 })
1263 return upgrades
1264 }
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278 func (r *resolver) loadPackages(loaderstate *modload.State, ctx context.Context, patterns []string, findPackage func(ctx context.Context, path string, m module.Version) (versionOk bool)) {
1279 opts := modload.PackageOpts{
1280 Tags: imports.AnyTags(),
1281 VendorModulesInGOROOTSrc: true,
1282 LoadTests: *getT,
1283 AssumeRootsImported: true,
1284 SilencePackageErrors: true,
1285 Switcher: toolchain.NewSwitcher(loaderstate),
1286 }
1287
1288 opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error {
1289 if m.Path == "" || m.Version == "" {
1290
1291
1292 return nil
1293 }
1294 if ok := findPackage(ctx, path, m); !ok {
1295 return errVersionChange
1296 }
1297 return nil
1298 }
1299
1300 _, pkgs := modload.LoadPackages(loaderstate, ctx, opts, patterns...)
1301 for _, pkgPath := range pkgs {
1302 const (
1303 parentPath = ""
1304 parentIsStd = false
1305 )
1306 _, _, err := modload.Lookup(loaderstate, parentPath, parentIsStd, pkgPath)
1307 if err == nil {
1308 continue
1309 }
1310 if errors.Is(err, errVersionChange) {
1311
1312 continue
1313 }
1314 if r.workspace != nil && r.workspace.hasPackage(pkgPath) {
1315
1316 continue
1317 }
1318
1319 if _, ok := errors.AsType[*modload.ImportMissingError](err); !ok {
1320 if _, ok := errors.AsType[*modload.AmbiguousImportError](err); !ok {
1321
1322
1323
1324 continue
1325 }
1326 }
1327
1328 path := pkgPath
1329 r.work.Add(func() {
1330 findPackage(ctx, path, module.Version{})
1331 })
1332 }
1333 <-r.work.Idle()
1334 }
1335
1336
1337
1338 var errVersionChange = errors.New("version change needed")
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352 func (r *resolver) resolveQueries(loaderstate *modload.State, ctx context.Context, queries []*query) (changed bool) {
1353 defer base.ExitIfErrors()
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 resolved := 0
1366 for {
1367 prevResolved := resolved
1368
1369
1370
1371 sw := toolchain.NewSwitcher(loaderstate)
1372 for _, q := range queries {
1373 for _, cs := range q.candidates {
1374 sw.Error(cs.err)
1375 }
1376 }
1377
1378
1379 if sw.NeedSwitch() {
1380 sw.Switch(ctx)
1381
1382
1383 base.Exit()
1384 }
1385
1386 for _, q := range queries {
1387 unresolved := q.candidates[:0]
1388
1389 for _, cs := range q.candidates {
1390 if cs.err != nil {
1391 reportError(q, cs.err)
1392 resolved++
1393 continue
1394 }
1395
1396 filtered, isPackage, m, unique := r.disambiguate(loaderstate, cs)
1397 if !unique {
1398 unresolved = append(unresolved, filtered)
1399 continue
1400 }
1401
1402 if m.Path == "" {
1403
1404
1405 isPackage, m = r.chooseArbitrarily(cs)
1406 }
1407 if isPackage {
1408 q.matchesPackages = true
1409 }
1410 r.resolve(loaderstate, q, m)
1411 resolved++
1412 }
1413
1414 q.candidates = unresolved
1415 }
1416
1417 base.ExitIfErrors()
1418 if resolved == prevResolved {
1419 break
1420 }
1421 }
1422
1423 if resolved > 0 {
1424 if changed = r.updateBuildList(loaderstate, ctx, nil); changed {
1425
1426
1427
1428 return true
1429 }
1430 }
1431
1432
1433
1434
1435
1436
1437
1438
1439 resolvedArbitrarily := 0
1440 for _, q := range queries {
1441 for _, cs := range q.candidates {
1442 isPackage, m := r.chooseArbitrarily(cs)
1443 if isPackage {
1444 q.matchesPackages = true
1445 }
1446 r.resolve(loaderstate, q, m)
1447 resolvedArbitrarily++
1448 }
1449 }
1450 if resolvedArbitrarily > 0 {
1451 changed = r.updateBuildList(loaderstate, ctx, nil)
1452 }
1453 return changed
1454 }
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467 func (r *resolver) applyUpgrades(loaderstate *modload.State, ctx context.Context, upgrades []pathSet) (changed bool) {
1468 defer base.ExitIfErrors()
1469
1470
1471
1472
1473 var tentative []module.Version
1474 for _, cs := range upgrades {
1475 if cs.err != nil {
1476 base.Error(cs.err)
1477 continue
1478 }
1479
1480 filtered, _, m, unique := r.disambiguate(loaderstate, cs)
1481 if !unique {
1482 _, m = r.chooseArbitrarily(filtered)
1483 }
1484 if m.Path == "" {
1485
1486
1487 continue
1488 }
1489 tentative = append(tentative, m)
1490 }
1491 base.ExitIfErrors()
1492
1493 changed = r.updateBuildList(loaderstate, ctx, tentative)
1494 return changed
1495 }
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507 func (r *resolver) disambiguate(s *modload.State, cs pathSet) (filtered pathSet, isPackage bool, m module.Version, unique bool) {
1508 if len(cs.pkgMods) == 0 && cs.mod.Path == "" {
1509 panic("internal error: resolveIfUnambiguous called with empty pathSet")
1510 }
1511
1512 for _, m := range cs.pkgMods {
1513 if _, ok := r.noneForPath(m.Path); ok {
1514
1515
1516 continue
1517 }
1518
1519 if s.MainModules.Contains(m.Path) {
1520 if m.Version == "" {
1521 return pathSet{}, true, m, true
1522 }
1523
1524 continue
1525 }
1526
1527 vr, ok := r.resolvedVersion[m.Path]
1528 if !ok {
1529
1530
1531 filtered.pkgMods = append(filtered.pkgMods, m)
1532 continue
1533 }
1534
1535 if vr.version != m.Version {
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546 continue
1547 }
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562 return pathSet{}, true, m, true
1563 }
1564
1565 if cs.mod.Path != "" {
1566 vr, ok := r.resolvedVersion[cs.mod.Path]
1567 if !ok || vr.version == cs.mod.Version {
1568 filtered.mod = cs.mod
1569 }
1570 }
1571
1572 if len(filtered.pkgMods) == 1 &&
1573 (filtered.mod.Path == "" || filtered.mod == filtered.pkgMods[0]) {
1574
1575
1576 return pathSet{}, true, filtered.pkgMods[0], true
1577 }
1578
1579 if len(filtered.pkgMods) == 0 {
1580
1581
1582
1583
1584 return pathSet{}, false, filtered.mod, true
1585 }
1586
1587
1588
1589 return filtered, false, module.Version{}, false
1590 }
1591
1592
1593
1594
1595
1596
1597
1598
1599 func (r *resolver) chooseArbitrarily(cs pathSet) (isPackage bool, m module.Version) {
1600
1601 for _, m := range cs.pkgMods {
1602 if r.initialSelected(m.Path) != "none" {
1603 return true, m
1604 }
1605 }
1606
1607
1608 if len(cs.pkgMods) > 0 {
1609 return true, cs.pkgMods[0]
1610 }
1611
1612 return false, cs.mod
1613 }
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624 func (r *resolver) checkPackageProblems(loaderstate *modload.State, ctx context.Context, pkgPatterns []string) {
1625 defer base.ExitIfErrors()
1626
1627
1628
1629
1630
1631
1632
1633
1634 var exitWorkspace func()
1635 if r.workspace != nil && r.workspace.hasModule(loaderstate.MainModules.Versions()[0].Path) {
1636 var err error
1637 exitWorkspace, err = modload.EnterWorkspace(loaderstate, ctx)
1638 if err != nil {
1639
1640
1641
1642
1643
1644 toolchain.SwitchOrFatal(loaderstate, ctx, err)
1645 }
1646 }
1647
1648
1649
1650
1651
1652 type modFlags int
1653 const (
1654 resolved modFlags = 1 << iota
1655 named
1656 hasPkg
1657 direct
1658 )
1659 relevantMods := make(map[module.Version]modFlags)
1660 for path, reason := range r.resolvedVersion {
1661 m := module.Version{Path: path, Version: reason.version}
1662 relevantMods[m] |= resolved
1663 }
1664
1665
1666 if len(pkgPatterns) > 0 {
1667
1668
1669 pkgOpts := modload.PackageOpts{
1670 VendorModulesInGOROOTSrc: true,
1671 LoadTests: *getT,
1672 ResolveMissingImports: false,
1673 AllowErrors: true,
1674 SilenceNoGoErrors: true,
1675 }
1676 matches, pkgs := modload.LoadPackages(loaderstate, ctx, pkgOpts, pkgPatterns...)
1677 for _, m := range matches {
1678 if len(m.Errs) > 0 {
1679 base.SetExitStatus(1)
1680 break
1681 }
1682 }
1683 for _, pkg := range pkgs {
1684 if dir, _, err := modload.Lookup(loaderstate, "", false, pkg); err != nil {
1685 if dir != "" && errors.Is(err, imports.ErrNoGo) {
1686
1687
1688
1689
1690
1691
1692
1693 continue
1694 }
1695
1696 base.SetExitStatus(1)
1697 if ambiguousErr, ok := errors.AsType[*modload.AmbiguousImportError](err); ok {
1698 for _, m := range ambiguousErr.Modules {
1699 relevantMods[m] |= hasPkg
1700 }
1701 }
1702 }
1703 if m := loaderstate.PackageModule(pkg); m.Path != "" {
1704 relevantMods[m] |= hasPkg
1705 }
1706 }
1707 for _, match := range matches {
1708 for _, pkg := range match.Pkgs {
1709 m := loaderstate.PackageModule(pkg)
1710 relevantMods[m] |= named
1711 }
1712 }
1713 }
1714
1715 reqs := modload.LoadModFile(loaderstate, ctx)
1716 for m := range relevantMods {
1717 if reqs.IsDirect(m.Path) {
1718 relevantMods[m] |= direct
1719 }
1720 }
1721
1722
1723
1724
1725 type modMessage struct {
1726 m module.Version
1727 message string
1728 }
1729 retractions := make([]modMessage, 0, len(relevantMods))
1730 for m, flags := range relevantMods {
1731 if flags&(resolved|named|hasPkg) != 0 {
1732 retractions = append(retractions, modMessage{m: m})
1733 }
1734 }
1735 sort.Slice(retractions, func(i, j int) bool { return retractions[i].m.Path < retractions[j].m.Path })
1736 for i := range retractions {
1737 i := i
1738 r.work.Add(func() {
1739 err := loaderstate.CheckRetractions(ctx, retractions[i].m)
1740 if _, ok := errors.AsType[*modload.ModuleRetractedError](err); ok {
1741 retractions[i].message = err.Error()
1742 }
1743 })
1744 }
1745
1746
1747
1748
1749
1750 deprecations := make([]modMessage, 0, len(relevantMods))
1751 for m, flags := range relevantMods {
1752 if flags&(resolved|named) != 0 || flags&(hasPkg|direct) == hasPkg|direct {
1753 deprecations = append(deprecations, modMessage{m: m})
1754 }
1755 }
1756 sort.Slice(deprecations, func(i, j int) bool { return deprecations[i].m.Path < deprecations[j].m.Path })
1757 for i := range deprecations {
1758 i := i
1759 r.work.Add(func() {
1760 deprecation, err := modload.CheckDeprecation(loaderstate, ctx, deprecations[i].m)
1761 if err != nil || deprecation == "" {
1762 return
1763 }
1764 deprecations[i].message = modload.ShortMessage(deprecation, "")
1765 })
1766 }
1767
1768
1769
1770 if exitWorkspace != nil {
1771
1772
1773
1774 <-r.work.Idle()
1775 exitWorkspace()
1776 }
1777
1778
1779
1780
1781
1782
1783
1784
1785 sumErrs := make([]error, len(r.buildList))
1786 for i := range r.buildList {
1787 i := i
1788 m := r.buildList[i]
1789 mActual := m
1790 if mRepl := modload.Replacement(loaderstate, m); mRepl.Path != "" {
1791 mActual = mRepl
1792 }
1793 old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]}
1794 if old.Version == "" {
1795 continue
1796 }
1797 oldActual := old
1798 if oldRepl := modload.Replacement(loaderstate, old); oldRepl.Path != "" {
1799 oldActual = oldRepl
1800 }
1801 if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(loaderstate.Fetcher(), oldActual) {
1802 continue
1803 }
1804 r.work.Add(func() {
1805 if _, err := loaderstate.Fetcher().DownloadZip(ctx, mActual); err != nil {
1806 verb := "upgraded"
1807 if gover.ModCompare(m.Path, m.Version, old.Version) < 0 {
1808 verb = "downgraded"
1809 }
1810 replaced := ""
1811 if mActual != m {
1812 replaced = fmt.Sprintf(" (replaced by %s)", mActual)
1813 }
1814 err = fmt.Errorf("%s %s %s => %s%s: error finding sum for %s: %v", verb, m.Path, old.Version, m.Version, replaced, mActual, err)
1815 sumErrs[i] = err
1816 }
1817 })
1818 }
1819
1820 <-r.work.Idle()
1821
1822
1823
1824 for _, mm := range deprecations {
1825 if mm.message != "" {
1826 fmt.Fprintf(os.Stderr, "go: module %s is deprecated: %s\n", mm.m.Path, mm.message)
1827 }
1828 }
1829 var retractPath string
1830 for _, mm := range retractions {
1831 if mm.message != "" {
1832 fmt.Fprintf(os.Stderr, "go: warning: %v\n", mm.message)
1833 if retractPath == "" {
1834 retractPath = mm.m.Path
1835 } else {
1836 retractPath = "<module>"
1837 }
1838 }
1839 }
1840 if retractPath != "" {
1841 fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest\n", retractPath)
1842 }
1843 for _, err := range sumErrs {
1844 if err != nil {
1845 base.Error(err)
1846 }
1847 }
1848 }
1849
1850
1851
1852
1853
1854
1855
1856
1857 func (r *resolver) reportChanges(oldReqs, newReqs []module.Version) {
1858 type change struct {
1859 path, old, new string
1860 }
1861 changes := make(map[string]change)
1862
1863
1864 for path, reason := range r.resolvedVersion {
1865 if gover.IsToolchain(path) {
1866 continue
1867 }
1868 old := r.initialVersion[path]
1869 new := reason.version
1870 if old != new && (old != "" || new != "none") {
1871 changes[path] = change{path, old, new}
1872 }
1873 }
1874
1875
1876 for _, req := range oldReqs {
1877 if gover.IsToolchain(req.Path) {
1878 continue
1879 }
1880 path := req.Path
1881 old := req.Version
1882 new := r.buildListVersion[path]
1883 if old != new {
1884 changes[path] = change{path, old, new}
1885 }
1886 }
1887 for _, req := range newReqs {
1888 if gover.IsToolchain(req.Path) {
1889 continue
1890 }
1891 path := req.Path
1892 old := r.initialVersion[path]
1893 new := req.Version
1894 if old != new {
1895 changes[path] = change{path, old, new}
1896 }
1897 }
1898
1899
1900 toolchainVersions := func(reqs []module.Version) (goV, toolchain string) {
1901 for _, req := range reqs {
1902 if req.Path == "go" {
1903 goV = req.Version
1904 }
1905 if req.Path == "toolchain" {
1906 toolchain = req.Version
1907 }
1908 }
1909 return
1910 }
1911 oldGo, oldToolchain := toolchainVersions(oldReqs)
1912 newGo, newToolchain := toolchainVersions(newReqs)
1913 if oldGo != newGo {
1914 changes["go"] = change{"go", oldGo, newGo}
1915 }
1916 if oldToolchain != newToolchain {
1917 changes["toolchain"] = change{"toolchain", oldToolchain, newToolchain}
1918 }
1919
1920 sortedChanges := make([]change, 0, len(changes))
1921 for _, c := range changes {
1922 sortedChanges = append(sortedChanges, c)
1923 }
1924 sort.Slice(sortedChanges, func(i, j int) bool {
1925 pi := sortedChanges[i].path
1926 pj := sortedChanges[j].path
1927 if pi == pj {
1928 return false
1929 }
1930
1931 switch {
1932 case pi == "go":
1933 return true
1934 case pj == "go":
1935 return false
1936 case pi == "toolchain":
1937 return true
1938 case pj == "toolchain":
1939 return false
1940 }
1941 return pi < pj
1942 })
1943
1944 for _, c := range sortedChanges {
1945 if c.old == "" {
1946 fmt.Fprintf(os.Stderr, "go: added %s %s\n", c.path, c.new)
1947 } else if c.new == "none" || c.new == "" {
1948 fmt.Fprintf(os.Stderr, "go: removed %s %s\n", c.path, c.old)
1949 } else if gover.ModCompare(c.path, c.new, c.old) > 0 {
1950 fmt.Fprintf(os.Stderr, "go: upgraded %s %s => %s\n", c.path, c.old, c.new)
1951 if c.path == "go" && gover.Compare(c.old, gover.ExplicitIndirectVersion) < 0 && gover.Compare(c.new, gover.ExplicitIndirectVersion) >= 0 {
1952 fmt.Fprintf(os.Stderr, "\tnote: expanded dependencies to upgrade to go %s or higher; run 'go mod tidy' to clean up\n", gover.ExplicitIndirectVersion)
1953 }
1954
1955 } else {
1956 fmt.Fprintf(os.Stderr, "go: downgraded %s %s => %s\n", c.path, c.old, c.new)
1957 }
1958 }
1959
1960
1961
1962
1963
1964 }
1965
1966
1967
1968
1969 func (r *resolver) resolve(s *modload.State, q *query, m module.Version) {
1970 if m.Path == "" {
1971 panic("internal error: resolving a module.Version with an empty path")
1972 }
1973
1974 if s.MainModules.Contains(m.Path) && m.Version != "" {
1975 reportError(q, &modload.QueryMatchesMainModulesError{
1976 MainModules: []module.Version{{Path: m.Path}},
1977 Pattern: q.pattern,
1978 Query: q.version,
1979 PatternIsModule: s.MainModules.Contains(q.pattern),
1980 })
1981 return
1982 }
1983
1984 vr, ok := r.resolvedVersion[m.Path]
1985 if ok && vr.version != m.Version {
1986 reportConflict(q, m, vr)
1987 return
1988 }
1989 r.resolvedVersion[m.Path] = versionReason{m.Version, q}
1990 q.resolved = append(q.resolved, m)
1991 }
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002 func (r *resolver) updateBuildList(loaderstate *modload.State, ctx context.Context, additions []module.Version) (changed bool) {
2003 defer base.ExitIfErrors()
2004
2005 resolved := make([]module.Version, 0, len(r.resolvedVersion))
2006 for mPath, rv := range r.resolvedVersion {
2007 if !loaderstate.MainModules.Contains(mPath) {
2008 resolved = append(resolved, module.Version{Path: mPath, Version: rv.version})
2009 }
2010 }
2011
2012 changed, err := modload.EditBuildList(loaderstate, ctx, additions, resolved)
2013 if err != nil {
2014 if errors.Is(err, gover.ErrTooNew) {
2015 toolchain.SwitchOrFatal(loaderstate, ctx, err)
2016 }
2017
2018 constraint, ok := errors.AsType[*modload.ConstraintError](err)
2019 if !ok {
2020 base.Fatal(err)
2021 }
2022
2023 if cfg.BuildV {
2024
2025 for _, c := range constraint.Conflicts {
2026 fmt.Fprintf(os.Stderr, "go: %v\n", c.String())
2027 }
2028 }
2029
2030
2031
2032
2033 reason := func(m module.Version) string {
2034 rv, ok := r.resolvedVersion[m.Path]
2035 if !ok {
2036 return fmt.Sprintf("(INTERNAL ERROR: no reason found for %v)", m)
2037 }
2038 return rv.reason.ResolvedString(module.Version{Path: m.Path, Version: rv.version})
2039 }
2040 for _, c := range constraint.Conflicts {
2041 adverb := ""
2042 if len(c.Path) > 2 {
2043 adverb = "indirectly "
2044 }
2045 firstReason := reason(c.Path[0])
2046 last := c.Path[len(c.Path)-1]
2047 if c.Err != nil {
2048 base.Errorf("go: %v %srequires %v: %v", firstReason, adverb, last, c.UnwrapModuleError())
2049 } else {
2050 base.Errorf("go: %v %srequires %v, not %v", firstReason, adverb, last, reason(c.Constraint))
2051 }
2052 }
2053 return false
2054 }
2055 if !changed {
2056 return false
2057 }
2058
2059 mg, err := modload.LoadModGraph(loaderstate, ctx, "")
2060 if err != nil {
2061 toolchain.SwitchOrFatal(loaderstate, ctx, err)
2062 }
2063
2064 r.buildList = mg.BuildList()
2065 r.buildListVersion = make(map[string]string, len(r.buildList))
2066 for _, m := range r.buildList {
2067 r.buildListVersion[m.Path] = m.Version
2068 }
2069 return true
2070 }
2071
2072 func reqsFromGoMod(f *modfile.File) []module.Version {
2073 reqs := make([]module.Version, len(f.Require), 2+len(f.Require))
2074 for i, r := range f.Require {
2075 reqs[i] = r.Mod
2076 }
2077 if f.Go != nil {
2078 reqs = append(reqs, module.Version{Path: "go", Version: f.Go.Version})
2079 }
2080 if f.Toolchain != nil {
2081 reqs = append(reqs, module.Version{Path: "toolchain", Version: f.Toolchain.Name})
2082 }
2083 return reqs
2084 }
2085
2086
2087
2088
2089 func isNoSuchModuleVersion(err error) bool {
2090 if errors.Is(err, os.ErrNotExist) {
2091 return true
2092 }
2093 _, ok := errors.AsType[*modload.NoMatchingVersionError](err)
2094 return ok
2095 }
2096
2097
2098
2099
2100
2101 func isNoSuchPackageVersion(err error) bool {
2102 if isNoSuchModuleVersion(err) {
2103 return true
2104 }
2105 _, ok := errors.AsType[*modload.PackageNotInModuleError](err)
2106 return ok
2107 }
2108
2109
2110
2111 type workspace struct {
2112 modules map[string]string
2113 }
2114
2115
2116
2117 func loadWorkspace(workFilePath string) *workspace {
2118 if workFilePath == "" {
2119
2120 return nil
2121 }
2122
2123 _, modRoots, err := modload.LoadWorkFile(workFilePath)
2124 if err != nil {
2125 return nil
2126 }
2127
2128 w := &workspace{modules: make(map[string]string)}
2129 for _, modRoot := range modRoots {
2130 modFile := filepath.Join(modRoot, "go.mod")
2131 _, f, err := modload.ReadModFile(modFile, nil)
2132 if err != nil {
2133 continue
2134 }
2135 w.modules[f.Module.Mod.Path] = modRoot
2136 }
2137
2138 return w
2139 }
2140
2141
2142
2143 func (w *workspace) hasPackage(pkgpath string) bool {
2144 for modPath, modroot := range w.modules {
2145 if modload.PkgIsInLocalModule(pkgpath, modPath, modroot) {
2146 return true
2147 }
2148 }
2149 return false
2150 }
2151
2152
2153
2154 func (w *workspace) hasModule(modPath string) bool {
2155 _, ok := w.modules[modPath]
2156 return ok
2157 }
2158
View as plain text