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