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