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