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