1
2
3
4
5 package modload
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 import (
98 "context"
99 "errors"
100 "fmt"
101 "go/build"
102 "internal/diff"
103 "io/fs"
104 "maps"
105 "os"
106 pathpkg "path"
107 "path/filepath"
108 "runtime"
109 "slices"
110 "sort"
111 "strings"
112 "sync"
113 "sync/atomic"
114
115 "cmd/go/internal/base"
116 "cmd/go/internal/cfg"
117 "cmd/go/internal/fips140"
118 "cmd/go/internal/fsys"
119 "cmd/go/internal/gover"
120 "cmd/go/internal/imports"
121 "cmd/go/internal/modfetch"
122 "cmd/go/internal/modindex"
123 "cmd/go/internal/mvs"
124 "cmd/go/internal/search"
125 "cmd/go/internal/str"
126 "cmd/internal/par"
127
128 "golang.org/x/mod/module"
129 )
130
131
132
133
134
135
136
137 var loaded *loader
138
139
140 type PackageOpts struct {
141
142
143
144
145
146
147 TidyGoVersion string
148
149
150
151
152 Tags map[string]bool
153
154
155
156
157 Tidy bool
158
159
160
161
162 TidyDiff bool
163
164
165
166
167
168
169 TidyCompatibleVersion string
170
171
172
173
174 VendorModulesInGOROOTSrc bool
175
176
177
178
179
180
181 ResolveMissingImports bool
182
183
184
185
186 AssumeRootsImported bool
187
188
189
190
191
192
193
194
195 AllowPackage func(ctx context.Context, path string, mod module.Version) error
196
197
198
199
200 LoadTests bool
201
202
203
204
205
206
207 UseVendorAll bool
208
209
210
211 AllowErrors bool
212
213
214
215
216
217
218
219
220
221
222 SilencePackageErrors bool
223
224
225
226
227
228 SilenceMissingStdImports bool
229
230
231
232
233
234
235
236
237 SilenceNoGoErrors bool
238
239
240
241 SilenceUnmatchedWarnings bool
242
243
244 MainModule module.Version
245
246
247
248 Switcher gover.Switcher
249 }
250
251
252
253 func LoadPackages(loaderstate *State, ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) {
254 if opts.Tags == nil {
255 opts.Tags = imports.Tags()
256 }
257
258 patterns = search.CleanPatterns(patterns)
259 matches = make([]*search.Match, 0, len(patterns))
260 allPatternIsRoot := false
261 for _, pattern := range patterns {
262 matches = append(matches, search.NewMatch(pattern))
263 if pattern == "all" {
264 allPatternIsRoot = true
265 }
266 }
267
268 updateMatches := func(rs *Requirements, ld *loader) {
269 for _, m := range matches {
270 switch {
271 case m.IsLocal():
272
273 if m.Dirs == nil {
274 matchModRoots := loaderstate.modRoots
275 if opts.MainModule != (module.Version{}) {
276 matchModRoots = []string{loaderstate.MainModules.ModRoot(opts.MainModule)}
277 }
278 matchLocalDirs(loaderstate, ctx, matchModRoots, m, rs)
279 }
280
281
282
283
284
285
286
287 m.Pkgs = m.Pkgs[:0]
288 for _, dir := range m.Dirs {
289 pkg, err := resolveLocalPackage(loaderstate, ctx, dir, rs)
290 if err != nil {
291 if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) {
292 continue
293 }
294
295
296
297 if !HasModRoot(loaderstate) {
298 die(loaderstate)
299 }
300
301 if ld != nil {
302 m.AddError(err)
303 }
304 continue
305 }
306 m.Pkgs = append(m.Pkgs, pkg)
307 }
308
309 case m.IsLiteral():
310 m.Pkgs = []string{m.Pattern()}
311
312 case strings.Contains(m.Pattern(), "..."):
313 m.Errs = m.Errs[:0]
314 mg, err := rs.Graph(loaderstate, ctx)
315 if err != nil {
316
317
318
319
320
321
322 m.Errs = append(m.Errs, err)
323 }
324 matchPackages(loaderstate, ctx, m, opts.Tags, includeStd, mg.BuildList())
325
326 case m.Pattern() == "work":
327 matchModules := loaderstate.MainModules.Versions()
328 if opts.MainModule != (module.Version{}) {
329 matchModules = []module.Version{opts.MainModule}
330 }
331 matchPackages(loaderstate, ctx, m, opts.Tags, omitStd, matchModules)
332
333 case m.Pattern() == "all":
334 if ld == nil {
335
336
337 m.Errs = m.Errs[:0]
338 matchModules := loaderstate.MainModules.Versions()
339 if opts.MainModule != (module.Version{}) {
340 matchModules = []module.Version{opts.MainModule}
341 }
342 matchPackages(loaderstate, ctx, m, opts.Tags, omitStd, matchModules)
343 for tool := range loaderstate.MainModules.Tools() {
344 m.Pkgs = append(m.Pkgs, tool)
345 }
346 } else {
347
348
349 m.Pkgs = ld.computePatternAll()
350 }
351
352 case m.Pattern() == "std" || m.Pattern() == "cmd":
353 if m.Pkgs == nil {
354 m.MatchPackages()
355 }
356
357 case m.Pattern() == "tool":
358 for tool := range loaderstate.MainModules.Tools() {
359 m.Pkgs = append(m.Pkgs, tool)
360 }
361 default:
362 panic(fmt.Sprintf("internal error: modload missing case for pattern %s", m.Pattern()))
363 }
364 }
365 }
366
367 initialRS, err := loadModFile(loaderstate, ctx, &opts)
368 if err != nil {
369 base.Fatal(err)
370 }
371
372 ld := loadFromRoots(loaderstate, ctx, loaderParams{
373 PackageOpts: opts,
374 requirements: initialRS,
375
376 allPatternIsRoot: allPatternIsRoot,
377
378 listRoots: func(rs *Requirements) (roots []string) {
379 updateMatches(rs, nil)
380 for _, m := range matches {
381 roots = append(roots, m.Pkgs...)
382 }
383 return roots
384 },
385 })
386
387
388 updateMatches(ld.requirements, ld)
389
390
391
392 if !ld.SilencePackageErrors {
393 for _, match := range matches {
394 for _, err := range match.Errs {
395 ld.error(err)
396 }
397 }
398 }
399 ld.exitIfErrors(ctx)
400
401 if !opts.SilenceUnmatchedWarnings {
402 search.WarnUnmatched(matches)
403 }
404
405 if opts.Tidy {
406 if cfg.BuildV {
407 mg, _ := ld.requirements.Graph(loaderstate, ctx)
408 for _, m := range initialRS.rootModules {
409 var unused bool
410 if ld.requirements.pruning == unpruned {
411
412
413
414 unused = mg.Selected(m.Path) == "none"
415 } else {
416
417
418
419 _, ok := ld.requirements.rootSelected(loaderstate, m.Path)
420 unused = !ok
421 }
422 if unused {
423 fmt.Fprintf(os.Stderr, "unused %s\n", m.Path)
424 }
425 }
426 }
427
428 keep := keepSums(loaderstate, ctx, ld, ld.requirements, loadedZipSumsOnly)
429 compatVersion := ld.TidyCompatibleVersion
430 goVersion := ld.requirements.GoVersion(loaderstate)
431 if compatVersion == "" {
432 if gover.Compare(goVersion, gover.GoStrictVersion) < 0 {
433 compatVersion = gover.Prev(goVersion)
434 } else {
435
436
437 compatVersion = goVersion
438 }
439 }
440 if gover.Compare(compatVersion, goVersion) > 0 {
441
442
443
444 compatVersion = goVersion
445 }
446 if compatPruning := pruningForGoVersion(compatVersion); compatPruning != ld.requirements.pruning {
447 compatRS := newRequirements(loaderstate, compatPruning, ld.requirements.rootModules, ld.requirements.direct)
448 ld.checkTidyCompatibility(loaderstate, ctx, compatRS, compatVersion)
449
450 for m := range keepSums(loaderstate, ctx, ld, compatRS, loadedZipSumsOnly) {
451 keep[m] = true
452 }
453 }
454
455 if opts.TidyDiff {
456 cfg.BuildMod = "readonly"
457 loaded = ld
458 loaderstate.requirements = loaded.requirements
459 currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(loaderstate, ctx, WriteOpts{})
460 if err != nil {
461 base.Fatal(err)
462 }
463 goModDiff := diff.Diff("current/go.mod", currentGoMod, "tidy/go.mod", updatedGoMod)
464
465 modfetch.TrimGoSum(keep)
466
467
468 if gover.Compare(compatVersion, "1.16") > 0 {
469 keep = keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums)
470 }
471 currentGoSum, tidyGoSum := modfetch.TidyGoSum(keep)
472 goSumDiff := diff.Diff("current/go.sum", currentGoSum, "tidy/go.sum", tidyGoSum)
473
474 if len(goModDiff) > 0 {
475 fmt.Println(string(goModDiff))
476 base.SetExitStatus(1)
477 }
478 if len(goSumDiff) > 0 {
479 fmt.Println(string(goSumDiff))
480 base.SetExitStatus(1)
481 }
482 base.Exit()
483 }
484
485 if !ExplicitWriteGoMod {
486 modfetch.TrimGoSum(keep)
487
488
489
490
491
492
493 if err := modfetch.WriteGoSum(ctx, keep, mustHaveCompleteRequirements(loaderstate)); err != nil {
494 base.Fatal(err)
495 }
496 }
497 }
498
499 if opts.TidyDiff && !opts.Tidy {
500 panic("TidyDiff is set but Tidy is not.")
501 }
502
503
504
505
506
507 loaded = ld
508 loaderstate.requirements = loaded.requirements
509
510 for _, pkg := range ld.pkgs {
511 if !pkg.isTest() {
512 loadedPackages = append(loadedPackages, pkg.path)
513 }
514 }
515 sort.Strings(loadedPackages)
516
517 if !ExplicitWriteGoMod && opts.ResolveMissingImports {
518 if err := commitRequirements(loaderstate, ctx, WriteOpts{}); err != nil {
519 base.Fatal(err)
520 }
521 }
522
523 return matches, loadedPackages
524 }
525
526
527
528 func matchLocalDirs(loaderstate *State, ctx context.Context, modRoots []string, m *search.Match, rs *Requirements) {
529 if !m.IsLocal() {
530 panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern()))
531 }
532
533 if i := strings.Index(m.Pattern(), "..."); i >= 0 {
534
535
536
537
538
539 dir := filepath.Dir(filepath.Clean(m.Pattern()[:i+3]))
540 absDir := dir
541 if !filepath.IsAbs(dir) {
542 absDir = filepath.Join(base.Cwd(), dir)
543 }
544
545 modRoot := findModuleRoot(absDir)
546 if !slices.Contains(modRoots, modRoot) && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(loaderstate, ctx, absDir, rs) == "" {
547 m.Dirs = []string{}
548 scope := "main module or its selected dependencies"
549 if inWorkspaceMode(loaderstate) {
550 scope = "modules listed in go.work or their selected dependencies"
551 }
552 m.AddError(fmt.Errorf("directory prefix %s does not contain %s", base.ShortPath(absDir), scope))
553 return
554 }
555 }
556
557 m.MatchDirs(modRoots)
558 }
559
560
561 func resolveLocalPackage(loaderstate *State, ctx context.Context, dir string, rs *Requirements) (string, error) {
562 var absDir string
563 if filepath.IsAbs(dir) {
564 absDir = filepath.Clean(dir)
565 } else {
566 absDir = filepath.Join(base.Cwd(), dir)
567 }
568
569 bp, err := cfg.BuildContext.ImportDir(absDir, 0)
570 if err != nil && (bp == nil || len(bp.IgnoredGoFiles) == 0) {
571
572
573
574
575
576
577
578 if _, err := fsys.Stat(absDir); err != nil {
579 if os.IsNotExist(err) {
580
581
582 return "", &fs.PathError{Op: "stat", Path: absDir, Err: errDirectoryNotFound}
583 }
584 return "", err
585 }
586 if _, noGo := err.(*build.NoGoError); noGo {
587
588
589
590
591
592
593
594
595 return "", err
596 }
597 }
598
599 for _, mod := range loaderstate.MainModules.Versions() {
600 modRoot := loaderstate.MainModules.ModRoot(mod)
601 if modRoot != "" && absDir == modRoot {
602 if absDir == cfg.GOROOTsrc {
603 return "", errPkgIsGorootSrc
604 }
605 return loaderstate.MainModules.PathPrefix(mod), nil
606 }
607 }
608
609
610
611
612 var pkgNotFoundErr error
613 pkgNotFoundLongestPrefix := ""
614 for _, mainModule := range loaderstate.MainModules.Versions() {
615 modRoot := loaderstate.MainModules.ModRoot(mainModule)
616 if modRoot != "" && str.HasFilePathPrefix(absDir, modRoot) && !strings.Contains(absDir[len(modRoot):], "@") {
617 suffix := filepath.ToSlash(str.TrimFilePathPrefix(absDir, modRoot))
618 if pkg, found := strings.CutPrefix(suffix, "vendor/"); found {
619 if cfg.BuildMod != "vendor" {
620 return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir)
621 }
622
623 readVendorList(VendorDir(loaderstate))
624 if _, ok := vendorPkgModule[pkg]; !ok {
625 return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir)
626 }
627 return pkg, nil
628 }
629
630 mainModulePrefix := loaderstate.MainModules.PathPrefix(mainModule)
631 if mainModulePrefix == "" {
632 pkg := suffix
633 if pkg == "builtin" {
634
635
636
637 return "", errPkgIsBuiltin
638 }
639 return pkg, nil
640 }
641
642 pkg := pathpkg.Join(mainModulePrefix, suffix)
643 if _, ok, err := dirInModule(pkg, mainModulePrefix, modRoot, true); err != nil {
644 return "", err
645 } else if !ok {
646
647
648
649
650 if len(mainModulePrefix) > len(pkgNotFoundLongestPrefix) {
651 pkgNotFoundLongestPrefix = mainModulePrefix
652 pkgNotFoundErr = &PackageNotInModuleError{MainModules: []module.Version{mainModule}, Pattern: pkg}
653 }
654 continue
655 }
656 return pkg, nil
657 }
658 }
659 if pkgNotFoundErr != nil {
660 return "", pkgNotFoundErr
661 }
662
663 if sub := search.InDir(absDir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
664 pkg := filepath.ToSlash(sub)
665 if pkg == "builtin" {
666 return "", errPkgIsBuiltin
667 }
668 return pkg, nil
669 }
670
671 pkg := pathInModuleCache(loaderstate, ctx, absDir, rs)
672 if pkg == "" {
673 dirstr := fmt.Sprintf("directory %s", base.ShortPath(absDir))
674 if dirstr == "directory ." {
675 dirstr = "current directory"
676 }
677 if inWorkspaceMode(loaderstate) {
678 if mr := findModuleRoot(absDir); mr != "" {
679 return "", fmt.Errorf("%s is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use %s", dirstr, base.ShortPath(mr))
680 }
681 return "", fmt.Errorf("%s outside modules listed in go.work or their selected dependencies", dirstr)
682 }
683 return "", fmt.Errorf("%s outside main module or its selected dependencies", dirstr)
684 }
685 return pkg, nil
686 }
687
688 var (
689 errDirectoryNotFound = errors.New("directory not found")
690 errPkgIsGorootSrc = errors.New("GOROOT/src is not an importable package")
691 errPkgIsBuiltin = errors.New(`"builtin" is a pseudo-package, not an importable package`)
692 )
693
694
695
696 func pathInModuleCache(loaderstate *State, ctx context.Context, dir string, rs *Requirements) string {
697 tryMod := func(m module.Version) (string, bool) {
698 if gover.IsToolchain(m.Path) {
699 return "", false
700 }
701 var root string
702 var err error
703 if repl := Replacement(loaderstate, m); repl.Path != "" && repl.Version == "" {
704 root = repl.Path
705 if !filepath.IsAbs(root) {
706 root = filepath.Join(replaceRelativeTo(loaderstate), root)
707 }
708 } else if repl.Path != "" {
709 root, err = modfetch.DownloadDir(ctx, repl)
710 } else {
711 root, err = modfetch.DownloadDir(ctx, m)
712 }
713 if err != nil {
714 return "", false
715 }
716
717 sub := search.InDir(dir, root)
718 if sub == "" {
719 return "", false
720 }
721 sub = filepath.ToSlash(sub)
722 if strings.Contains(sub, "/vendor/") || strings.HasPrefix(sub, "vendor/") || strings.Contains(sub, "@") {
723 return "", false
724 }
725
726 return pathpkg.Join(m.Path, filepath.ToSlash(sub)), true
727 }
728
729 if rs.pruning == pruned {
730 for _, m := range rs.rootModules {
731 if v, _ := rs.rootSelected(loaderstate, m.Path); v != m.Version {
732 continue
733 }
734 if importPath, ok := tryMod(m); ok {
735
736
737 return importPath
738 }
739 }
740 }
741
742
743
744
745
746
747
748
749
750 mg, _ := rs.Graph(loaderstate, ctx)
751 var importPath string
752 for _, m := range mg.BuildList() {
753 var found bool
754 importPath, found = tryMod(m)
755 if found {
756 break
757 }
758 }
759 return importPath
760 }
761
762
763
764
765
766
767
768
769 func ImportFromFiles(loaderstate *State, ctx context.Context, gofiles []string) {
770 rs := LoadModFile(loaderstate, ctx)
771
772 tags := imports.Tags()
773 imports, testImports, err := imports.ScanFiles(gofiles, tags)
774 if err != nil {
775 base.Fatal(err)
776 }
777
778 loaded = loadFromRoots(loaderstate, ctx, loaderParams{
779 PackageOpts: PackageOpts{
780 Tags: tags,
781 ResolveMissingImports: true,
782 SilencePackageErrors: true,
783 },
784 requirements: rs,
785 listRoots: func(*Requirements) (roots []string) {
786 roots = append(roots, imports...)
787 roots = append(roots, testImports...)
788 return roots
789 },
790 })
791 loaderstate.requirements = loaded.requirements
792
793 if !ExplicitWriteGoMod {
794 if err := commitRequirements(loaderstate, ctx, WriteOpts{}); err != nil {
795 base.Fatal(err)
796 }
797 }
798 }
799
800
801
802 func (mms *MainModuleSet) DirImportPath(loaderstate *State, ctx context.Context, dir string) (path string, m module.Version) {
803 if !HasModRoot(loaderstate) {
804 return ".", module.Version{}
805 }
806 LoadModFile(loaderstate, ctx)
807
808 if !filepath.IsAbs(dir) {
809 dir = filepath.Join(base.Cwd(), dir)
810 } else {
811 dir = filepath.Clean(dir)
812 }
813
814 var longestPrefix string
815 var longestPrefixPath string
816 var longestPrefixVersion module.Version
817 for _, v := range mms.Versions() {
818 modRoot := mms.ModRoot(v)
819 if dir == modRoot {
820 return mms.PathPrefix(v), v
821 }
822 if str.HasFilePathPrefix(dir, modRoot) {
823 pathPrefix := loaderstate.MainModules.PathPrefix(v)
824 if pathPrefix > longestPrefix {
825 longestPrefix = pathPrefix
826 longestPrefixVersion = v
827 suffix := filepath.ToSlash(str.TrimFilePathPrefix(dir, modRoot))
828 if strings.HasPrefix(suffix, "vendor/") {
829 longestPrefixPath = suffix[len("vendor/"):]
830 continue
831 }
832 longestPrefixPath = pathpkg.Join(mms.PathPrefix(v), suffix)
833 }
834 }
835 }
836 if len(longestPrefix) > 0 {
837 return longestPrefixPath, longestPrefixVersion
838 }
839
840 return ".", module.Version{}
841 }
842
843
844 func PackageModule(path string) module.Version {
845 pkg, ok := loaded.pkgCache.Get(path)
846 if !ok {
847 return module.Version{}
848 }
849 return pkg.mod
850 }
851
852
853
854
855
856 func Lookup(loaderstate *State, parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) {
857 if path == "" {
858 panic("Lookup called with empty package path")
859 }
860
861 if parentIsStd {
862 path = loaded.stdVendor(loaderstate, parentPath, path)
863 }
864 pkg, ok := loaded.pkgCache.Get(path)
865 if !ok {
866
867
868
869
870
871
872
873
874 dir := findStandardImportPath(path)
875 if dir != "" {
876 return dir, path, nil
877 }
878 return "", "", errMissing
879 }
880 return pkg.dir, pkg.path, pkg.err
881 }
882
883
884
885
886
887 type loader struct {
888 loaderParams
889
890
891
892
893
894 allClosesOverTests bool
895
896
897
898 skipImportModFiles bool
899
900 work *par.Queue
901
902
903 roots []*loadPkg
904 pkgCache *par.Cache[string, *loadPkg]
905 pkgs []*loadPkg
906 }
907
908
909
910 type loaderParams struct {
911 PackageOpts
912 requirements *Requirements
913
914 allPatternIsRoot bool
915
916 listRoots func(rs *Requirements) []string
917 }
918
919 func (ld *loader) reset() {
920 select {
921 case <-ld.work.Idle():
922 default:
923 panic("loader.reset when not idle")
924 }
925
926 ld.roots = nil
927 ld.pkgCache = new(par.Cache[string, *loadPkg])
928 ld.pkgs = nil
929 }
930
931
932
933 func (ld *loader) error(err error) {
934 if ld.AllowErrors {
935 fmt.Fprintf(os.Stderr, "go: %v\n", err)
936 } else if ld.Switcher != nil {
937 ld.Switcher.Error(err)
938 } else {
939 base.Error(err)
940 }
941 }
942
943
944 func (ld *loader) switchIfErrors(ctx context.Context) {
945 if ld.Switcher != nil {
946 ld.Switcher.Switch(ctx)
947 }
948 }
949
950
951
952 func (ld *loader) exitIfErrors(ctx context.Context) {
953 ld.switchIfErrors(ctx)
954 base.ExitIfErrors()
955 }
956
957
958
959
960 func (ld *loader) goVersion(loaderstate *State) string {
961 if ld.TidyGoVersion != "" {
962 return ld.TidyGoVersion
963 }
964 return ld.requirements.GoVersion(loaderstate)
965 }
966
967
968 type loadPkg struct {
969
970 path string
971 testOf *loadPkg
972
973
974 flags atomicLoadPkgFlags
975
976
977 mod module.Version
978 dir string
979 err error
980 imports []*loadPkg
981 testImports []string
982 inStd bool
983 altMods []module.Version
984
985
986 testOnce sync.Once
987 test *loadPkg
988
989
990 stack *loadPkg
991 }
992
993
994 type loadPkgFlags int8
995
996 const (
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 pkgInAll loadPkgFlags = 1 << iota
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018 pkgIsRoot
1019
1020
1021
1022
1023 pkgFromRoot
1024
1025
1026
1027 pkgImportsLoaded
1028 )
1029
1030
1031 func (f loadPkgFlags) has(cond loadPkgFlags) bool {
1032 return f&cond == cond
1033 }
1034
1035
1036
1037 type atomicLoadPkgFlags struct {
1038 bits atomic.Int32
1039 }
1040
1041
1042
1043
1044
1045 func (af *atomicLoadPkgFlags) update(flags loadPkgFlags) (old loadPkgFlags) {
1046 for {
1047 old := af.bits.Load()
1048 new := old | int32(flags)
1049 if new == old || af.bits.CompareAndSwap(old, new) {
1050 return loadPkgFlags(old)
1051 }
1052 }
1053 }
1054
1055
1056 func (af *atomicLoadPkgFlags) has(cond loadPkgFlags) bool {
1057 return loadPkgFlags(af.bits.Load())&cond == cond
1058 }
1059
1060
1061 func (pkg *loadPkg) isTest() bool {
1062 return pkg.testOf != nil
1063 }
1064
1065
1066
1067 func (pkg *loadPkg) fromExternalModule(loaderstate *State) bool {
1068 if pkg.mod.Path == "" {
1069 return false
1070 }
1071 return !loaderstate.MainModules.Contains(pkg.mod.Path)
1072 }
1073
1074 var errMissing = errors.New("cannot find package")
1075
1076
1077
1078
1079
1080
1081
1082 func loadFromRoots(loaderstate *State, ctx context.Context, params loaderParams) *loader {
1083 ld := &loader{
1084 loaderParams: params,
1085 work: par.NewQueue(runtime.GOMAXPROCS(0)),
1086 }
1087
1088 if ld.requirements.pruning == unpruned {
1089
1090
1091
1092
1093
1094
1095
1096
1097 var err error
1098 ld.requirements, _, err = expandGraph(loaderstate, ctx, ld.requirements)
1099 if err != nil {
1100 ld.error(err)
1101 }
1102 }
1103 ld.exitIfErrors(ctx)
1104
1105 updateGoVersion := func() {
1106 goVersion := ld.goVersion(loaderstate)
1107
1108 if ld.requirements.pruning != workspace {
1109 var err error
1110 ld.requirements, err = convertPruning(loaderstate, ctx, ld.requirements, pruningForGoVersion(goVersion))
1111 if err != nil {
1112 ld.error(err)
1113 ld.exitIfErrors(ctx)
1114 }
1115 }
1116
1117
1118
1119
1120 ld.skipImportModFiles = ld.Tidy && gover.Compare(goVersion, gover.TidyGoModSumVersion) < 0
1121
1122
1123
1124 ld.allClosesOverTests = gover.Compare(goVersion, gover.NarrowAllVersion) < 0 && !ld.UseVendorAll
1125 }
1126
1127 for {
1128 ld.reset()
1129 updateGoVersion()
1130
1131
1132
1133
1134
1135 rootPkgs := ld.listRoots(ld.requirements)
1136
1137 if ld.requirements.pruning == pruned && cfg.BuildMod == "mod" {
1138
1139
1140
1141
1142
1143
1144 changedBuildList := ld.preloadRootModules(loaderstate, ctx, rootPkgs)
1145 if changedBuildList {
1146
1147
1148
1149
1150
1151 continue
1152 }
1153 }
1154
1155 inRoots := map[*loadPkg]bool{}
1156 for _, path := range rootPkgs {
1157 root := ld.pkg(loaderstate, ctx, path, pkgIsRoot)
1158 if !inRoots[root] {
1159 ld.roots = append(ld.roots, root)
1160 inRoots[root] = true
1161 }
1162 }
1163
1164
1165
1166
1167
1168
1169 <-ld.work.Idle()
1170
1171 ld.buildStacks()
1172
1173 changed, err := ld.updateRequirements(loaderstate, ctx)
1174 if err != nil {
1175 ld.error(err)
1176 break
1177 }
1178 if changed {
1179
1180
1181
1182
1183
1184 continue
1185 }
1186
1187 if !ld.ResolveMissingImports || (!HasModRoot(loaderstate) && !allowMissingModuleImports) {
1188
1189 break
1190 }
1191
1192 modAddedBy, err := ld.resolveMissingImports(loaderstate, ctx)
1193 if err != nil {
1194 ld.error(err)
1195 break
1196 }
1197 if len(modAddedBy) == 0 {
1198
1199
1200 break
1201 }
1202
1203 toAdd := make([]module.Version, 0, len(modAddedBy))
1204 for m := range modAddedBy {
1205 toAdd = append(toAdd, m)
1206 }
1207 gover.ModSort(toAdd)
1208
1209
1210
1211
1212
1213
1214 var noPkgs []*loadPkg
1215
1216
1217
1218 direct := ld.requirements.direct
1219 rs, err := updateRoots(loaderstate, ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported)
1220 if err != nil {
1221
1222
1223
1224 if err, ok := err.(*mvs.BuildListError); ok {
1225 if pkg := modAddedBy[err.Module()]; pkg != nil {
1226 ld.error(fmt.Errorf("%s: %w", pkg.stackText(), err.Err))
1227 break
1228 }
1229 }
1230 ld.error(err)
1231 break
1232 }
1233 if slices.Equal(rs.rootModules, ld.requirements.rootModules) {
1234
1235
1236
1237
1238 panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules))
1239 }
1240 ld.requirements = rs
1241 }
1242 ld.exitIfErrors(ctx)
1243
1244
1245
1246 if ld.Tidy {
1247 rs, err := tidyRoots(loaderstate, ctx, ld.requirements, ld.pkgs)
1248 if err != nil {
1249 ld.error(err)
1250 } else {
1251 if ld.TidyGoVersion != "" {
1252
1253
1254
1255 tidy := overrideRoots(loaderstate, ctx, rs, []module.Version{{Path: "go", Version: ld.TidyGoVersion}})
1256 mg, err := tidy.Graph(loaderstate, ctx)
1257 if err != nil {
1258 ld.error(err)
1259 }
1260 if v := mg.Selected("go"); v == ld.TidyGoVersion {
1261 rs = tidy
1262 } else {
1263 conflict := Conflict{
1264 Path: mg.g.FindPath(func(m module.Version) bool {
1265 return m.Path == "go" && m.Version == v
1266 })[1:],
1267 Constraint: module.Version{Path: "go", Version: ld.TidyGoVersion},
1268 }
1269 msg := conflict.Summary()
1270 if cfg.BuildV {
1271 msg = conflict.String()
1272 }
1273 ld.error(errors.New(msg))
1274 }
1275 }
1276
1277 if ld.requirements.pruning == pruned {
1278
1279
1280
1281
1282
1283
1284 for _, m := range rs.rootModules {
1285 if m.Path == "go" && ld.TidyGoVersion != "" {
1286 continue
1287 }
1288 if v, ok := ld.requirements.rootSelected(loaderstate, m.Path); !ok || v != m.Version {
1289 ld.error(fmt.Errorf("internal error: a requirement on %v is needed but was not added during package loading (selected %s)", m, v))
1290 }
1291 }
1292 }
1293
1294 ld.requirements = rs
1295 }
1296
1297 ld.exitIfErrors(ctx)
1298 }
1299
1300
1301 for _, pkg := range ld.pkgs {
1302 if pkg.err == nil {
1303 continue
1304 }
1305
1306
1307 if sumErr, ok := errors.AsType[*ImportMissingSumError](pkg.err); ok {
1308 if importer := pkg.stack; importer != nil {
1309 sumErr.importer = importer.path
1310 sumErr.importerVersion = importer.mod.Version
1311 sumErr.importerIsTest = importer.testOf != nil
1312 }
1313 }
1314
1315 if stdErr, ok := errors.AsType[*ImportMissingError](pkg.err); ok && stdErr.isStd {
1316
1317
1318 if importer := pkg.stack; importer != nil {
1319 if v, ok := rawGoVersion.Load(importer.mod); ok && gover.Compare(gover.Local(), v.(string)) < 0 {
1320 stdErr.importerGoVersion = v.(string)
1321 }
1322 }
1323 if ld.SilenceMissingStdImports {
1324 continue
1325 }
1326 }
1327 if ld.SilencePackageErrors {
1328 continue
1329 }
1330 if ld.SilenceNoGoErrors && errors.Is(pkg.err, imports.ErrNoGo) {
1331 continue
1332 }
1333
1334 ld.error(fmt.Errorf("%s: %w", pkg.stackText(), pkg.err))
1335 }
1336
1337 ld.checkMultiplePaths(loaderstate)
1338 return ld
1339 }
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360 func (ld *loader) updateRequirements(loaderstate *State, ctx context.Context) (changed bool, err error) {
1361 rs := ld.requirements
1362
1363
1364
1365 var direct map[string]bool
1366
1367
1368
1369
1370
1371 loadedDirect := ld.allPatternIsRoot && maps.Equal(ld.Tags, imports.AnyTags())
1372 if loadedDirect {
1373 direct = make(map[string]bool)
1374 } else {
1375
1376
1377
1378 direct = make(map[string]bool, len(rs.direct))
1379 for mPath := range rs.direct {
1380 direct[mPath] = true
1381 }
1382 }
1383
1384 var maxTooNew *gover.TooNewError
1385 for _, pkg := range ld.pkgs {
1386 if pkg.err != nil {
1387 if tooNew, ok := errors.AsType[*gover.TooNewError](pkg.err); ok {
1388 if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 {
1389 maxTooNew = tooNew
1390 }
1391 }
1392 }
1393 if pkg.mod.Version != "" || !loaderstate.MainModules.Contains(pkg.mod.Path) {
1394 continue
1395 }
1396
1397 for _, dep := range pkg.imports {
1398 if !dep.fromExternalModule(loaderstate) {
1399 continue
1400 }
1401
1402 if inWorkspaceMode(loaderstate) {
1403
1404
1405
1406 if cfg.BuildMod == "vendor" {
1407
1408
1409
1410
1411
1412
1413 continue
1414 }
1415 if mg, err := rs.Graph(loaderstate, ctx); err != nil {
1416 return false, err
1417 } else if _, ok := mg.RequiredBy(dep.mod); !ok {
1418
1419
1420 pkg.err = &DirectImportFromImplicitDependencyError{
1421 ImporterPath: pkg.path,
1422 ImportedPath: dep.path,
1423 Module: dep.mod,
1424 }
1425 }
1426 } else if pkg.err == nil && cfg.BuildMod != "mod" {
1427 if v, ok := rs.rootSelected(loaderstate, dep.mod.Path); !ok || v != dep.mod.Version {
1428
1429
1430
1431
1432
1433
1434
1435
1436 pkg.err = &DirectImportFromImplicitDependencyError{
1437 ImporterPath: pkg.path,
1438 ImportedPath: dep.path,
1439 Module: dep.mod,
1440 }
1441
1442
1443 continue
1444 }
1445 }
1446
1447
1448
1449
1450 direct[dep.mod.Path] = true
1451 }
1452 }
1453 if maxTooNew != nil {
1454 return false, maxTooNew
1455 }
1456
1457 var addRoots []module.Version
1458 if ld.Tidy {
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493 tidy, err := tidyRoots(loaderstate, ctx, rs, ld.pkgs)
1494 if err != nil {
1495 return false, err
1496 }
1497 addRoots = tidy.rootModules
1498 }
1499
1500 rs, err = updateRoots(loaderstate, ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported)
1501 if err != nil {
1502
1503
1504 return false, err
1505 }
1506
1507 if rs.GoVersion(loaderstate) != ld.requirements.GoVersion(loaderstate) {
1508
1509
1510
1511
1512
1513 changed = true
1514 } else if rs != ld.requirements && !slices.Equal(rs.rootModules, ld.requirements.rootModules) {
1515
1516
1517
1518 mg, err := rs.Graph(loaderstate, ctx)
1519 if err != nil {
1520 return false, err
1521 }
1522 for _, pkg := range ld.pkgs {
1523 if pkg.fromExternalModule(loaderstate) && mg.Selected(pkg.mod.Path) != pkg.mod.Version {
1524 changed = true
1525 break
1526 }
1527 if pkg.err != nil {
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 if _, _, _, _, err = importFromModules(loaderstate, ctx, pkg.path, rs, nil, ld.skipImportModFiles); err == nil {
1544 changed = true
1545 break
1546 }
1547 }
1548 }
1549 }
1550
1551 ld.requirements = rs
1552 return changed, nil
1553 }
1554
1555
1556
1557
1558
1559
1560
1561 func (ld *loader) resolveMissingImports(loaderstate *State, ctx context.Context) (modAddedBy map[module.Version]*loadPkg, err error) {
1562 type pkgMod struct {
1563 pkg *loadPkg
1564 mod *module.Version
1565 }
1566 var pkgMods []pkgMod
1567 for _, pkg := range ld.pkgs {
1568 if pkg.err == nil {
1569 continue
1570 }
1571 if pkg.isTest() {
1572
1573
1574 continue
1575 }
1576 if _, ok := errors.AsType[*ImportMissingError](pkg.err); !ok {
1577
1578 continue
1579 }
1580
1581 pkg := pkg
1582 var mod module.Version
1583 ld.work.Add(func() {
1584 var err error
1585 mod, err = queryImport(loaderstate, ctx, pkg.path, ld.requirements)
1586 if err != nil {
1587 if ime, ok := errors.AsType[*ImportMissingError](err); ok {
1588 for curstack := pkg.stack; curstack != nil; curstack = curstack.stack {
1589 if loaderstate.MainModules.Contains(curstack.mod.Path) {
1590 ime.ImportingMainModule = curstack.mod
1591 break
1592 }
1593 }
1594 }
1595
1596
1597
1598
1599
1600 pkg.err = err
1601 }
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614 })
1615
1616 pkgMods = append(pkgMods, pkgMod{pkg: pkg, mod: &mod})
1617 }
1618 <-ld.work.Idle()
1619
1620 modAddedBy = map[module.Version]*loadPkg{}
1621
1622 var (
1623 maxTooNew *gover.TooNewError
1624 maxTooNewPkg *loadPkg
1625 )
1626 for _, pm := range pkgMods {
1627 if tooNew, ok := errors.AsType[*gover.TooNewError](pm.pkg.err); ok {
1628 if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 {
1629 maxTooNew = tooNew
1630 maxTooNewPkg = pm.pkg
1631 }
1632 }
1633 }
1634 if maxTooNew != nil {
1635 fmt.Fprintf(os.Stderr, "go: toolchain upgrade needed to resolve %s\n", maxTooNewPkg.path)
1636 return nil, maxTooNew
1637 }
1638
1639 for _, pm := range pkgMods {
1640 pkg, mod := pm.pkg, *pm.mod
1641 if mod.Path == "" {
1642 continue
1643 }
1644
1645 fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, mod.Path, mod.Version)
1646 if modAddedBy[mod] == nil {
1647 modAddedBy[mod] = pkg
1648 }
1649 }
1650
1651 return modAddedBy, nil
1652 }
1653
1654
1655
1656
1657
1658
1659
1660
1661 func (ld *loader) pkg(loaderstate *State, ctx context.Context, path string, flags loadPkgFlags) *loadPkg {
1662 if flags.has(pkgImportsLoaded) {
1663 panic("internal error: (*loader).pkg called with pkgImportsLoaded flag set")
1664 }
1665
1666 pkg := ld.pkgCache.Do(path, func() *loadPkg {
1667 pkg := &loadPkg{
1668 path: path,
1669 }
1670 ld.applyPkgFlags(loaderstate, ctx, pkg, flags)
1671
1672 ld.work.Add(func() { ld.load(loaderstate, ctx, pkg) })
1673 return pkg
1674 })
1675
1676 ld.applyPkgFlags(loaderstate, ctx, pkg, flags)
1677 return pkg
1678 }
1679
1680
1681
1682
1683 func (ld *loader) applyPkgFlags(loaderstate *State, ctx context.Context, pkg *loadPkg, flags loadPkgFlags) {
1684 if flags == 0 {
1685 return
1686 }
1687
1688 if flags.has(pkgInAll) && ld.allPatternIsRoot && !pkg.isTest() {
1689
1690 flags |= pkgIsRoot
1691 }
1692 if flags.has(pkgIsRoot) {
1693 flags |= pkgFromRoot
1694 }
1695
1696 old := pkg.flags.update(flags)
1697 new := old | flags
1698 if new == old || !new.has(pkgImportsLoaded) {
1699
1700
1701
1702 return
1703 }
1704
1705 if !pkg.isTest() {
1706
1707
1708
1709 wantTest := false
1710 switch {
1711 case ld.allPatternIsRoot && loaderstate.MainModules.Contains(pkg.mod.Path):
1712
1713
1714
1715
1716
1717 wantTest = true
1718
1719 case ld.allPatternIsRoot && ld.allClosesOverTests && new.has(pkgInAll):
1720
1721
1722
1723 wantTest = true
1724
1725 case ld.LoadTests && new.has(pkgIsRoot):
1726
1727 wantTest = true
1728 }
1729
1730 if wantTest {
1731 var testFlags loadPkgFlags
1732 if loaderstate.MainModules.Contains(pkg.mod.Path) || (ld.allClosesOverTests && new.has(pkgInAll)) {
1733
1734
1735
1736 testFlags |= pkgInAll
1737 }
1738 ld.pkgTest(loaderstate, ctx, pkg, testFlags)
1739 }
1740 }
1741
1742 if new.has(pkgInAll) && !old.has(pkgInAll|pkgImportsLoaded) {
1743
1744
1745 for _, dep := range pkg.imports {
1746 ld.applyPkgFlags(loaderstate, ctx, dep, pkgInAll)
1747 }
1748 }
1749
1750 if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {
1751 for _, dep := range pkg.imports {
1752 ld.applyPkgFlags(loaderstate, ctx, dep, pkgFromRoot)
1753 }
1754 }
1755 }
1756
1757
1758
1759
1760 func (ld *loader) preloadRootModules(loaderstate *State, ctx context.Context, rootPkgs []string) (changedBuildList bool) {
1761 needc := make(chan map[module.Version]bool, 1)
1762 needc <- map[module.Version]bool{}
1763 for _, path := range rootPkgs {
1764 path := path
1765 ld.work.Add(func() {
1766
1767
1768
1769
1770
1771 m, _, _, _, err := importFromModules(loaderstate, ctx, path, ld.requirements, nil, ld.skipImportModFiles)
1772 if err != nil {
1773 if _, ok := errors.AsType[*ImportMissingError](err); ok && ld.ResolveMissingImports {
1774
1775
1776 m, err = queryImport(loaderstate, ctx, path, ld.requirements)
1777 }
1778 if err != nil {
1779
1780
1781 return
1782 }
1783 }
1784 if m.Path == "" {
1785
1786 return
1787 }
1788
1789 v, ok := ld.requirements.rootSelected(loaderstate, m.Path)
1790 if !ok || v != m.Version {
1791
1792
1793
1794
1795
1796
1797
1798 need := <-needc
1799 need[m] = true
1800 needc <- need
1801 }
1802 })
1803 }
1804 <-ld.work.Idle()
1805
1806 need := <-needc
1807 if len(need) == 0 {
1808 return false
1809 }
1810
1811 toAdd := make([]module.Version, 0, len(need))
1812 for m := range need {
1813 toAdd = append(toAdd, m)
1814 }
1815 gover.ModSort(toAdd)
1816
1817 rs, err := updateRoots(loaderstate, ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported)
1818 if err != nil {
1819
1820
1821
1822 ld.error(err)
1823 ld.exitIfErrors(ctx)
1824 return false
1825 }
1826 if slices.Equal(rs.rootModules, ld.requirements.rootModules) {
1827
1828
1829
1830
1831 panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules))
1832 }
1833
1834 ld.requirements = rs
1835 return true
1836 }
1837
1838
1839 func (ld *loader) load(loaderstate *State, ctx context.Context, pkg *loadPkg) {
1840 var mg *ModuleGraph
1841 if ld.requirements.pruning == unpruned {
1842 var err error
1843 mg, err = ld.requirements.Graph(loaderstate, ctx)
1844 if err != nil {
1845
1846
1847
1848
1849
1850
1851
1852
1853 mg = nil
1854 }
1855 }
1856
1857 var modroot string
1858 pkg.mod, modroot, pkg.dir, pkg.altMods, pkg.err = importFromModules(loaderstate, ctx, pkg.path, ld.requirements, mg, ld.skipImportModFiles)
1859 if loaderstate.MainModules.Tools()[pkg.path] {
1860
1861
1862
1863 ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll)
1864 }
1865 if pkg.dir == "" {
1866 return
1867 }
1868 if loaderstate.MainModules.Contains(pkg.mod.Path) {
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll)
1879 }
1880 if ld.AllowPackage != nil {
1881 if err := ld.AllowPackage(ctx, pkg.path, pkg.mod); err != nil {
1882 pkg.err = err
1883 }
1884 }
1885
1886 pkg.inStd = (search.IsStandardImportPath(pkg.path) && search.InDir(pkg.dir, cfg.GOROOTsrc) != "")
1887
1888 var imports, testImports []string
1889
1890 if cfg.BuildContext.Compiler == "gccgo" && pkg.inStd {
1891
1892 } else {
1893 var err error
1894 imports, testImports, err = scanDir(modroot, pkg.dir, ld.Tags)
1895 if err != nil {
1896 pkg.err = err
1897 return
1898 }
1899 }
1900
1901 pkg.imports = make([]*loadPkg, 0, len(imports))
1902 var importFlags loadPkgFlags
1903 if pkg.flags.has(pkgInAll) {
1904 importFlags = pkgInAll
1905 }
1906 for _, path := range imports {
1907 if pkg.inStd {
1908
1909
1910 path = ld.stdVendor(loaderstate, pkg.path, path)
1911 }
1912 pkg.imports = append(pkg.imports, ld.pkg(loaderstate, ctx, path, importFlags))
1913 }
1914 pkg.testImports = testImports
1915
1916 ld.applyPkgFlags(loaderstate, ctx, pkg, pkgImportsLoaded)
1917 }
1918
1919
1920
1921
1922
1923
1924 func (ld *loader) pkgTest(loaderstate *State, ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
1925 if pkg.isTest() {
1926 panic("pkgTest called on a test package")
1927 }
1928
1929 createdTest := false
1930 pkg.testOnce.Do(func() {
1931 pkg.test = &loadPkg{
1932 path: pkg.path,
1933 testOf: pkg,
1934 mod: pkg.mod,
1935 dir: pkg.dir,
1936 err: pkg.err,
1937 inStd: pkg.inStd,
1938 }
1939 ld.applyPkgFlags(loaderstate, ctx, pkg.test, testFlags)
1940 createdTest = true
1941 })
1942
1943 test := pkg.test
1944 if createdTest {
1945 test.imports = make([]*loadPkg, 0, len(pkg.testImports))
1946 var importFlags loadPkgFlags
1947 if test.flags.has(pkgInAll) {
1948 importFlags = pkgInAll
1949 }
1950 for _, path := range pkg.testImports {
1951 if pkg.inStd {
1952 path = ld.stdVendor(loaderstate, test.path, path)
1953 }
1954 test.imports = append(test.imports, ld.pkg(loaderstate, ctx, path, importFlags))
1955 }
1956 pkg.testImports = nil
1957 ld.applyPkgFlags(loaderstate, ctx, test, pkgImportsLoaded)
1958 } else {
1959 ld.applyPkgFlags(loaderstate, ctx, test, testFlags)
1960 }
1961
1962 return test
1963 }
1964
1965
1966
1967 func (ld *loader) stdVendor(loaderstate *State, parentPath, path string) string {
1968 if p, _, ok := fips140.ResolveImport(path); ok {
1969 return p
1970 }
1971 if search.IsStandardImportPath(path) {
1972 return path
1973 }
1974
1975 if str.HasPathPrefix(parentPath, "cmd") {
1976 if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("cmd") {
1977 vendorPath := pathpkg.Join("cmd", "vendor", path)
1978
1979 if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
1980 return vendorPath
1981 }
1982 }
1983 } else if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") {
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996 vendorPath := pathpkg.Join("vendor", path)
1997 if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
1998 return vendorPath
1999 }
2000 }
2001
2002
2003 return path
2004 }
2005
2006
2007
2008 func (ld *loader) computePatternAll() (all []string) {
2009 for _, pkg := range ld.pkgs {
2010 if module.CheckImportPath(pkg.path) != nil {
2011
2012
2013
2014
2015 continue
2016 }
2017 if pkg.flags.has(pkgInAll) && !pkg.isTest() {
2018 all = append(all, pkg.path)
2019 }
2020 }
2021 sort.Strings(all)
2022 return all
2023 }
2024
2025
2026
2027
2028
2029 func (ld *loader) checkMultiplePaths(loaderstate *State) {
2030 mods := ld.requirements.rootModules
2031 if cached := ld.requirements.graph.Load(); cached != nil {
2032 if mg := cached.mg; mg != nil {
2033 mods = mg.BuildList()
2034 }
2035 }
2036
2037 firstPath := map[module.Version]string{}
2038 for _, mod := range mods {
2039 src := resolveReplacement(loaderstate, mod)
2040 if prev, ok := firstPath[src]; !ok {
2041 firstPath[src] = mod.Path
2042 } else if prev != mod.Path {
2043 ld.error(fmt.Errorf("%s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path))
2044 }
2045 }
2046 }
2047
2048
2049
2050 func (ld *loader) checkTidyCompatibility(loaderstate *State, ctx context.Context, rs *Requirements, compatVersion string) {
2051 goVersion := rs.GoVersion(loaderstate)
2052 suggestUpgrade := false
2053 suggestEFlag := false
2054 suggestFixes := func() {
2055 if ld.AllowErrors {
2056
2057
2058 return
2059 }
2060
2061
2062
2063
2064
2065 fmt.Fprintln(os.Stderr)
2066
2067 goFlag := ""
2068 if goVersion != loaderstate.MainModules.GoVersion(loaderstate) {
2069 goFlag = " -go=" + goVersion
2070 }
2071
2072 compatFlag := ""
2073 if compatVersion != gover.Prev(goVersion) {
2074 compatFlag = " -compat=" + compatVersion
2075 }
2076 if suggestUpgrade {
2077 eDesc := ""
2078 eFlag := ""
2079 if suggestEFlag {
2080 eDesc = ", leaving some packages unresolved"
2081 eFlag = " -e"
2082 }
2083 fmt.Fprintf(os.Stderr, "To upgrade to the versions selected by go %s%s:\n\tgo mod tidy%s -go=%s && go mod tidy%s -go=%s%s\n", compatVersion, eDesc, eFlag, compatVersion, eFlag, goVersion, compatFlag)
2084 } else if suggestEFlag {
2085
2086
2087
2088
2089 fmt.Fprintf(os.Stderr, "To proceed despite packages unresolved in go %s:\n\tgo mod tidy -e%s%s\n", compatVersion, goFlag, compatFlag)
2090 }
2091
2092 fmt.Fprintf(os.Stderr, "If reproducibility with go %s is not needed:\n\tgo mod tidy%s -compat=%s\n", compatVersion, goFlag, goVersion)
2093
2094 fmt.Fprintf(os.Stderr, "For information about 'go mod tidy' compatibility, see:\n\thttps://go.dev/ref/mod#graph-pruning\n")
2095 }
2096
2097 mg, err := rs.Graph(loaderstate, ctx)
2098 if err != nil {
2099 ld.error(fmt.Errorf("error loading go %s module graph: %w", compatVersion, err))
2100 ld.switchIfErrors(ctx)
2101 suggestFixes()
2102 ld.exitIfErrors(ctx)
2103 return
2104 }
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120 type mismatch struct {
2121 mod module.Version
2122 err error
2123 }
2124 mismatchMu := make(chan map[*loadPkg]mismatch, 1)
2125 mismatchMu <- map[*loadPkg]mismatch{}
2126 for _, pkg := range ld.pkgs {
2127 if pkg.mod.Path == "" && pkg.err == nil {
2128
2129
2130 continue
2131 }
2132
2133 pkg := pkg
2134 ld.work.Add(func() {
2135 mod, _, _, _, err := importFromModules(loaderstate, ctx, pkg.path, rs, mg, ld.skipImportModFiles)
2136 if mod != pkg.mod {
2137 mismatches := <-mismatchMu
2138 mismatches[pkg] = mismatch{mod: mod, err: err}
2139 mismatchMu <- mismatches
2140 }
2141 })
2142 }
2143 <-ld.work.Idle()
2144
2145 mismatches := <-mismatchMu
2146 if len(mismatches) == 0 {
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158 for _, m := range ld.requirements.rootModules {
2159 if v := mg.Selected(m.Path); v != m.Version {
2160 fmt.Fprintln(os.Stderr)
2161 base.Fatalf("go: internal error: failed to diagnose selected-version mismatch for module %s: go %s selects %s, but go %s selects %s\n\tPlease report this at https://golang.org/issue.", m.Path, goVersion, m.Version, compatVersion, v)
2162 }
2163 }
2164 return
2165 }
2166
2167
2168
2169 for _, pkg := range ld.pkgs {
2170 mismatch, ok := mismatches[pkg]
2171 if !ok {
2172 continue
2173 }
2174
2175 if pkg.isTest() {
2176
2177
2178 if _, ok := mismatches[pkg.testOf]; !ok {
2179 base.Fatalf("go: internal error: mismatch recorded for test %s, but not its non-test package", pkg.path)
2180 }
2181 continue
2182 }
2183
2184 switch {
2185 case mismatch.err != nil:
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197 if _, ok := errors.AsType[*ImportMissingError](mismatch.err); ok {
2198 selected := module.Version{
2199 Path: pkg.mod.Path,
2200 Version: mg.Selected(pkg.mod.Path),
2201 }
2202 ld.error(fmt.Errorf("%s loaded from %v,\n\tbut go %s would fail to locate it in %s", pkg.stackText(), pkg.mod, compatVersion, selected))
2203 } else {
2204 if _, ok := errors.AsType[*AmbiguousImportError](mismatch.err); ok {
2205
2206 }
2207 ld.error(fmt.Errorf("%s loaded from %v,\n\tbut go %s would fail to locate it:\n\t%v", pkg.stackText(), pkg.mod, compatVersion, mismatch.err))
2208 }
2209
2210 suggestEFlag = true
2211
2212
2213
2214
2215
2216
2217
2218
2219 if !suggestUpgrade {
2220 for _, m := range ld.requirements.rootModules {
2221 if v := mg.Selected(m.Path); v != m.Version {
2222 suggestUpgrade = true
2223 break
2224 }
2225 }
2226 }
2227
2228 case pkg.err != nil:
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244 suggestUpgrade = true
2245 ld.error(fmt.Errorf("%s failed to load from any module,\n\tbut go %s would load it from %v", pkg.path, compatVersion, mismatch.mod))
2246
2247 case pkg.mod != mismatch.mod:
2248
2249
2250
2251
2252 suggestUpgrade = true
2253 ld.error(fmt.Errorf("%s loaded from %v,\n\tbut go %s would select %v\n", pkg.stackText(), pkg.mod, compatVersion, mismatch.mod.Version))
2254
2255 default:
2256 base.Fatalf("go: internal error: mismatch recorded for package %s, but no differences found", pkg.path)
2257 }
2258 }
2259
2260 ld.switchIfErrors(ctx)
2261 suggestFixes()
2262 ld.exitIfErrors(ctx)
2263 }
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277 func scanDir(modroot string, dir string, tags map[string]bool) (imports_, testImports []string, err error) {
2278 if ip, mierr := modindex.GetPackage(modroot, dir); mierr == nil {
2279 imports_, testImports, err = ip.ScanDir(tags)
2280 goto Happy
2281 } else if !errors.Is(mierr, modindex.ErrNotIndexed) {
2282 return nil, nil, mierr
2283 }
2284
2285 imports_, testImports, err = imports.ScanDir(dir, tags)
2286 Happy:
2287
2288 filter := func(x []string) []string {
2289 w := 0
2290 for _, pkg := range x {
2291 if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") &&
2292 pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") {
2293 x[w] = pkg
2294 w++
2295 }
2296 }
2297 return x[:w]
2298 }
2299
2300 return filter(imports_), filter(testImports), err
2301 }
2302
2303
2304
2305
2306
2307
2308
2309
2310 func (ld *loader) buildStacks() {
2311 if len(ld.pkgs) > 0 {
2312 panic("buildStacks")
2313 }
2314 for _, pkg := range ld.roots {
2315 pkg.stack = pkg
2316 ld.pkgs = append(ld.pkgs, pkg)
2317 }
2318 for i := 0; i < len(ld.pkgs); i++ {
2319 pkg := ld.pkgs[i]
2320 for _, next := range pkg.imports {
2321 if next.stack == nil {
2322 next.stack = pkg
2323 ld.pkgs = append(ld.pkgs, next)
2324 }
2325 }
2326 if next := pkg.test; next != nil && next.stack == nil {
2327 next.stack = pkg
2328 ld.pkgs = append(ld.pkgs, next)
2329 }
2330 }
2331 for _, pkg := range ld.roots {
2332 pkg.stack = nil
2333 }
2334 }
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344 func (pkg *loadPkg) stackText() string {
2345 var stack []*loadPkg
2346 for p := pkg; p != nil; p = p.stack {
2347 stack = append(stack, p)
2348 }
2349
2350 var buf strings.Builder
2351 for i := len(stack) - 1; i >= 0; i-- {
2352 p := stack[i]
2353 fmt.Fprint(&buf, p.path)
2354 if p.testOf != nil {
2355 fmt.Fprint(&buf, ".test")
2356 }
2357 if i > 0 {
2358 if stack[i-1].testOf == p {
2359 fmt.Fprint(&buf, " tested by\n\t")
2360 } else {
2361 fmt.Fprint(&buf, " imports\n\t")
2362 }
2363 }
2364 }
2365 return buf.String()
2366 }
2367
2368
2369
2370 func (pkg *loadPkg) why() string {
2371 var buf strings.Builder
2372 var stack []*loadPkg
2373 for p := pkg; p != nil; p = p.stack {
2374 stack = append(stack, p)
2375 }
2376
2377 for i := len(stack) - 1; i >= 0; i-- {
2378 p := stack[i]
2379 if p.testOf != nil {
2380 fmt.Fprintf(&buf, "%s.test\n", p.testOf.path)
2381 } else {
2382 fmt.Fprintf(&buf, "%s\n", p.path)
2383 }
2384 }
2385 return buf.String()
2386 }
2387
2388
2389
2390
2391
2392
2393 func Why(path string) string {
2394 pkg, ok := loaded.pkgCache.Get(path)
2395 if !ok {
2396 return ""
2397 }
2398 return pkg.why()
2399 }
2400
2401
2402
2403
2404 func WhyDepth(path string) int {
2405 n := 0
2406 pkg, _ := loaded.pkgCache.Get(path)
2407 for p := pkg; p != nil; p = p.stack {
2408 n++
2409 }
2410 return n
2411 }
2412
View as plain text