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