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