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 ime.modRoot = loaderstate.MainModules.ModRoot(ime.ImportingMainModule)
1592 break
1593 }
1594 }
1595 }
1596
1597
1598
1599
1600
1601 pkg.err = err
1602 }
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615 })
1616
1617 pkgMods = append(pkgMods, pkgMod{pkg: pkg, mod: &mod})
1618 }
1619 <-ld.work.Idle()
1620
1621 modAddedBy = map[module.Version]*loadPkg{}
1622
1623 var (
1624 maxTooNew *gover.TooNewError
1625 maxTooNewPkg *loadPkg
1626 )
1627 for _, pm := range pkgMods {
1628 if tooNew, ok := errors.AsType[*gover.TooNewError](pm.pkg.err); ok {
1629 if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 {
1630 maxTooNew = tooNew
1631 maxTooNewPkg = pm.pkg
1632 }
1633 }
1634 }
1635 if maxTooNew != nil {
1636 fmt.Fprintf(os.Stderr, "go: toolchain upgrade needed to resolve %s\n", maxTooNewPkg.path)
1637 return nil, maxTooNew
1638 }
1639
1640 for _, pm := range pkgMods {
1641 pkg, mod := pm.pkg, *pm.mod
1642 if mod.Path == "" {
1643 continue
1644 }
1645
1646 fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, mod.Path, mod.Version)
1647 if modAddedBy[mod] == nil {
1648 modAddedBy[mod] = pkg
1649 }
1650 }
1651
1652 return modAddedBy, nil
1653 }
1654
1655
1656
1657
1658
1659
1660
1661
1662 func (ld *loader) pkg(loaderstate *State, ctx context.Context, path string, flags loadPkgFlags) *loadPkg {
1663 if flags.has(pkgImportsLoaded) {
1664 panic("internal error: (*loader).pkg called with pkgImportsLoaded flag set")
1665 }
1666
1667 pkg := ld.pkgCache.Do(path, func() *loadPkg {
1668 pkg := &loadPkg{
1669 path: path,
1670 }
1671 ld.applyPkgFlags(loaderstate, ctx, pkg, flags)
1672
1673 ld.work.Add(func() { ld.load(loaderstate, ctx, pkg) })
1674 return pkg
1675 })
1676
1677 ld.applyPkgFlags(loaderstate, ctx, pkg, flags)
1678 return pkg
1679 }
1680
1681
1682
1683
1684 func (ld *loader) applyPkgFlags(loaderstate *State, ctx context.Context, pkg *loadPkg, flags loadPkgFlags) {
1685 if flags == 0 {
1686 return
1687 }
1688
1689 if flags.has(pkgInAll) && ld.allPatternIsRoot && !pkg.isTest() {
1690
1691 flags |= pkgIsRoot
1692 }
1693 if flags.has(pkgIsRoot) {
1694 flags |= pkgFromRoot
1695 }
1696
1697 old := pkg.flags.update(flags)
1698 new := old | flags
1699 if new == old || !new.has(pkgImportsLoaded) {
1700
1701
1702
1703 return
1704 }
1705
1706 if !pkg.isTest() {
1707
1708
1709
1710 wantTest := false
1711 switch {
1712 case ld.allPatternIsRoot && loaderstate.MainModules.Contains(pkg.mod.Path):
1713
1714
1715
1716
1717
1718 wantTest = true
1719
1720 case ld.allPatternIsRoot && ld.allClosesOverTests && new.has(pkgInAll):
1721
1722
1723
1724 wantTest = true
1725
1726 case ld.LoadTests && new.has(pkgIsRoot):
1727
1728 wantTest = true
1729 }
1730
1731 if wantTest {
1732 var testFlags loadPkgFlags
1733 if loaderstate.MainModules.Contains(pkg.mod.Path) || (ld.allClosesOverTests && new.has(pkgInAll)) {
1734
1735
1736
1737 testFlags |= pkgInAll
1738 }
1739 ld.pkgTest(loaderstate, ctx, pkg, testFlags)
1740 }
1741 }
1742
1743 if new.has(pkgInAll) && !old.has(pkgInAll|pkgImportsLoaded) {
1744
1745
1746 for _, dep := range pkg.imports {
1747 ld.applyPkgFlags(loaderstate, ctx, dep, pkgInAll)
1748 }
1749 }
1750
1751 if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {
1752 for _, dep := range pkg.imports {
1753 ld.applyPkgFlags(loaderstate, ctx, dep, pkgFromRoot)
1754 }
1755 }
1756 }
1757
1758
1759
1760
1761 func (ld *loader) preloadRootModules(loaderstate *State, ctx context.Context, rootPkgs []string) (changedBuildList bool) {
1762 needc := make(chan map[module.Version]bool, 1)
1763 needc <- map[module.Version]bool{}
1764 for _, path := range rootPkgs {
1765 path := path
1766 ld.work.Add(func() {
1767
1768
1769
1770
1771
1772 m, _, _, _, err := importFromModules(loaderstate, ctx, path, ld.requirements, nil, ld.skipImportModFiles)
1773 if err != nil {
1774 if _, ok := errors.AsType[*ImportMissingError](err); ok && ld.ResolveMissingImports {
1775
1776
1777 m, err = queryImport(loaderstate, ctx, path, ld.requirements)
1778 }
1779 if err != nil {
1780
1781
1782 return
1783 }
1784 }
1785 if m.Path == "" {
1786
1787 return
1788 }
1789
1790 v, ok := ld.requirements.rootSelected(loaderstate, m.Path)
1791 if !ok || v != m.Version {
1792
1793
1794
1795
1796
1797
1798
1799 need := <-needc
1800 need[m] = true
1801 needc <- need
1802 }
1803 })
1804 }
1805 <-ld.work.Idle()
1806
1807 need := <-needc
1808 if len(need) == 0 {
1809 return false
1810 }
1811
1812 toAdd := make([]module.Version, 0, len(need))
1813 for m := range need {
1814 toAdd = append(toAdd, m)
1815 }
1816 gover.ModSort(toAdd)
1817
1818 rs, err := updateRoots(loaderstate, ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported)
1819 if err != nil {
1820
1821
1822
1823 ld.error(err)
1824 ld.exitIfErrors(ctx)
1825 return false
1826 }
1827 if slices.Equal(rs.rootModules, ld.requirements.rootModules) {
1828
1829
1830
1831
1832 panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules))
1833 }
1834
1835 ld.requirements = rs
1836 return true
1837 }
1838
1839
1840 func (ld *loader) load(loaderstate *State, ctx context.Context, pkg *loadPkg) {
1841 var mg *ModuleGraph
1842 if ld.requirements.pruning == unpruned {
1843 var err error
1844 mg, err = ld.requirements.Graph(loaderstate, ctx)
1845 if err != nil {
1846
1847
1848
1849
1850
1851
1852
1853
1854 mg = nil
1855 }
1856 }
1857
1858 var modroot string
1859 pkg.mod, modroot, pkg.dir, pkg.altMods, pkg.err = importFromModules(loaderstate, ctx, pkg.path, ld.requirements, mg, ld.skipImportModFiles)
1860 if loaderstate.MainModules.Tools()[pkg.path] {
1861
1862
1863
1864 ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll)
1865 }
1866 if pkg.dir == "" {
1867 return
1868 }
1869 if loaderstate.MainModules.Contains(pkg.mod.Path) {
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879 ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll)
1880 }
1881 if ld.AllowPackage != nil {
1882 if err := ld.AllowPackage(ctx, pkg.path, pkg.mod); err != nil {
1883 pkg.err = err
1884 }
1885 }
1886
1887 pkg.inStd = (search.IsStandardImportPath(pkg.path) && search.InDir(pkg.dir, cfg.GOROOTsrc) != "")
1888
1889 var imports, testImports []string
1890
1891 if cfg.BuildContext.Compiler == "gccgo" && pkg.inStd {
1892
1893 } else {
1894 var err error
1895 imports, testImports, err = scanDir(modroot, pkg.dir, ld.Tags)
1896 if err != nil {
1897 pkg.err = err
1898 return
1899 }
1900 }
1901
1902 pkg.imports = make([]*loadPkg, 0, len(imports))
1903 var importFlags loadPkgFlags
1904 if pkg.flags.has(pkgInAll) {
1905 importFlags = pkgInAll
1906 }
1907 for _, path := range imports {
1908 if pkg.inStd {
1909
1910
1911 path = ld.stdVendor(loaderstate, pkg.path, path)
1912 }
1913 pkg.imports = append(pkg.imports, ld.pkg(loaderstate, ctx, path, importFlags))
1914 }
1915 pkg.testImports = testImports
1916
1917 ld.applyPkgFlags(loaderstate, ctx, pkg, pkgImportsLoaded)
1918 }
1919
1920
1921
1922
1923
1924
1925 func (ld *loader) pkgTest(loaderstate *State, ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
1926 if pkg.isTest() {
1927 panic("pkgTest called on a test package")
1928 }
1929
1930 createdTest := false
1931 pkg.testOnce.Do(func() {
1932 pkg.test = &loadPkg{
1933 path: pkg.path,
1934 testOf: pkg,
1935 mod: pkg.mod,
1936 dir: pkg.dir,
1937 err: pkg.err,
1938 inStd: pkg.inStd,
1939 }
1940 ld.applyPkgFlags(loaderstate, ctx, pkg.test, testFlags)
1941 createdTest = true
1942 })
1943
1944 test := pkg.test
1945 if createdTest {
1946 test.imports = make([]*loadPkg, 0, len(pkg.testImports))
1947 var importFlags loadPkgFlags
1948 if test.flags.has(pkgInAll) {
1949 importFlags = pkgInAll
1950 }
1951 for _, path := range pkg.testImports {
1952 if pkg.inStd {
1953 path = ld.stdVendor(loaderstate, test.path, path)
1954 }
1955 test.imports = append(test.imports, ld.pkg(loaderstate, ctx, path, importFlags))
1956 }
1957 pkg.testImports = nil
1958 ld.applyPkgFlags(loaderstate, ctx, test, pkgImportsLoaded)
1959 } else {
1960 ld.applyPkgFlags(loaderstate, ctx, test, testFlags)
1961 }
1962
1963 return test
1964 }
1965
1966
1967
1968 func (ld *loader) stdVendor(loaderstate *State, parentPath, path string) string {
1969 if p, _, ok := fips140.ResolveImport(path); ok {
1970 return p
1971 }
1972 if search.IsStandardImportPath(path) {
1973 return path
1974 }
1975
1976 if str.HasPathPrefix(parentPath, "cmd") {
1977 if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("cmd") {
1978 vendorPath := pathpkg.Join("cmd", "vendor", path)
1979
1980 if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
1981 return vendorPath
1982 }
1983 }
1984 } else if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") {
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997 vendorPath := pathpkg.Join("vendor", path)
1998 if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
1999 return vendorPath
2000 }
2001 }
2002
2003
2004 return path
2005 }
2006
2007
2008
2009 func (ld *loader) computePatternAll() (all []string) {
2010 for _, pkg := range ld.pkgs {
2011 if module.CheckImportPath(pkg.path) != nil {
2012
2013
2014
2015
2016 continue
2017 }
2018 if pkg.flags.has(pkgInAll) && !pkg.isTest() {
2019 all = append(all, pkg.path)
2020 }
2021 }
2022 sort.Strings(all)
2023 return all
2024 }
2025
2026
2027
2028
2029
2030 func (ld *loader) checkMultiplePaths(loaderstate *State) {
2031 mods := ld.requirements.rootModules
2032 if cached := ld.requirements.graph.Load(); cached != nil {
2033 if mg := cached.mg; mg != nil {
2034 mods = mg.BuildList()
2035 }
2036 }
2037
2038 firstPath := map[module.Version]string{}
2039 for _, mod := range mods {
2040 src := resolveReplacement(loaderstate, mod)
2041 if prev, ok := firstPath[src]; !ok {
2042 firstPath[src] = mod.Path
2043 } else if prev != mod.Path {
2044 ld.error(fmt.Errorf("%s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path))
2045 }
2046 }
2047 }
2048
2049
2050
2051 func (ld *loader) checkTidyCompatibility(loaderstate *State, ctx context.Context, rs *Requirements, compatVersion string) {
2052 goVersion := rs.GoVersion(loaderstate)
2053 suggestUpgrade := false
2054 suggestEFlag := false
2055 suggestFixes := func() {
2056 if ld.AllowErrors {
2057
2058
2059 return
2060 }
2061
2062
2063
2064
2065
2066 fmt.Fprintln(os.Stderr)
2067
2068 goFlag := ""
2069 if goVersion != loaderstate.MainModules.GoVersion(loaderstate) {
2070 goFlag = " -go=" + goVersion
2071 }
2072
2073 compatFlag := ""
2074 if compatVersion != gover.Prev(goVersion) {
2075 compatFlag = " -compat=" + compatVersion
2076 }
2077 if suggestUpgrade {
2078 eDesc := ""
2079 eFlag := ""
2080 if suggestEFlag {
2081 eDesc = ", leaving some packages unresolved"
2082 eFlag = " -e"
2083 }
2084 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)
2085 } else if suggestEFlag {
2086
2087
2088
2089
2090 fmt.Fprintf(os.Stderr, "To proceed despite packages unresolved in go %s:\n\tgo mod tidy -e%s%s\n", compatVersion, goFlag, compatFlag)
2091 }
2092
2093 fmt.Fprintf(os.Stderr, "If reproducibility with go %s is not needed:\n\tgo mod tidy%s -compat=%s\n", compatVersion, goFlag, goVersion)
2094
2095 fmt.Fprintf(os.Stderr, "For information about 'go mod tidy' compatibility, see:\n\thttps://go.dev/ref/mod#graph-pruning\n")
2096 }
2097
2098 mg, err := rs.Graph(loaderstate, ctx)
2099 if err != nil {
2100 ld.error(fmt.Errorf("error loading go %s module graph: %w", compatVersion, err))
2101 ld.switchIfErrors(ctx)
2102 suggestFixes()
2103 ld.exitIfErrors(ctx)
2104 return
2105 }
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121 type mismatch struct {
2122 mod module.Version
2123 err error
2124 }
2125 mismatchMu := make(chan map[*loadPkg]mismatch, 1)
2126 mismatchMu <- map[*loadPkg]mismatch{}
2127 for _, pkg := range ld.pkgs {
2128 if pkg.mod.Path == "" && pkg.err == nil {
2129
2130
2131 continue
2132 }
2133
2134 pkg := pkg
2135 ld.work.Add(func() {
2136 mod, _, _, _, err := importFromModules(loaderstate, ctx, pkg.path, rs, mg, ld.skipImportModFiles)
2137 if mod != pkg.mod {
2138 mismatches := <-mismatchMu
2139 mismatches[pkg] = mismatch{mod: mod, err: err}
2140 mismatchMu <- mismatches
2141 }
2142 })
2143 }
2144 <-ld.work.Idle()
2145
2146 mismatches := <-mismatchMu
2147 if len(mismatches) == 0 {
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159 for _, m := range ld.requirements.rootModules {
2160 if v := mg.Selected(m.Path); v != m.Version {
2161 fmt.Fprintln(os.Stderr)
2162 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)
2163 }
2164 }
2165 return
2166 }
2167
2168
2169
2170 for _, pkg := range ld.pkgs {
2171 mismatch, ok := mismatches[pkg]
2172 if !ok {
2173 continue
2174 }
2175
2176 if pkg.isTest() {
2177
2178
2179 if _, ok := mismatches[pkg.testOf]; !ok {
2180 base.Fatalf("go: internal error: mismatch recorded for test %s, but not its non-test package", pkg.path)
2181 }
2182 continue
2183 }
2184
2185 switch {
2186 case mismatch.err != nil:
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198 if _, ok := errors.AsType[*ImportMissingError](mismatch.err); ok {
2199 selected := module.Version{
2200 Path: pkg.mod.Path,
2201 Version: mg.Selected(pkg.mod.Path),
2202 }
2203 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))
2204 } else {
2205 if _, ok := errors.AsType[*AmbiguousImportError](mismatch.err); ok {
2206
2207 }
2208 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))
2209 }
2210
2211 suggestEFlag = true
2212
2213
2214
2215
2216
2217
2218
2219
2220 if !suggestUpgrade {
2221 for _, m := range ld.requirements.rootModules {
2222 if v := mg.Selected(m.Path); v != m.Version {
2223 suggestUpgrade = true
2224 break
2225 }
2226 }
2227 }
2228
2229 case pkg.err != nil:
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245 suggestUpgrade = true
2246 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))
2247
2248 case pkg.mod != mismatch.mod:
2249
2250
2251
2252
2253 suggestUpgrade = true
2254 ld.error(fmt.Errorf("%s loaded from %v,\n\tbut go %s would select %v\n", pkg.stackText(), pkg.mod, compatVersion, mismatch.mod.Version))
2255
2256 default:
2257 base.Fatalf("go: internal error: mismatch recorded for package %s, but no differences found", pkg.path)
2258 }
2259 }
2260
2261 ld.switchIfErrors(ctx)
2262 suggestFixes()
2263 ld.exitIfErrors(ctx)
2264 }
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278 func scanDir(modroot string, dir string, tags map[string]bool) (imports_, testImports []string, err error) {
2279 if ip, mierr := modindex.GetPackage(modroot, dir); mierr == nil {
2280 imports_, testImports, err = ip.ScanDir(tags)
2281 goto Happy
2282 } else if !errors.Is(mierr, modindex.ErrNotIndexed) {
2283 return nil, nil, mierr
2284 }
2285
2286 imports_, testImports, err = imports.ScanDir(dir, tags)
2287 Happy:
2288
2289 filter := func(x []string) []string {
2290 w := 0
2291 for _, pkg := range x {
2292 if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") &&
2293 pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") {
2294 x[w] = pkg
2295 w++
2296 }
2297 }
2298 return x[:w]
2299 }
2300
2301 return filter(imports_), filter(testImports), err
2302 }
2303
2304
2305
2306
2307
2308
2309
2310
2311 func (ld *loader) buildStacks() {
2312 if len(ld.pkgs) > 0 {
2313 panic("buildStacks")
2314 }
2315 for _, pkg := range ld.roots {
2316 pkg.stack = pkg
2317 ld.pkgs = append(ld.pkgs, pkg)
2318 }
2319 for i := 0; i < len(ld.pkgs); i++ {
2320 pkg := ld.pkgs[i]
2321 for _, next := range pkg.imports {
2322 if next.stack == nil {
2323 next.stack = pkg
2324 ld.pkgs = append(ld.pkgs, next)
2325 }
2326 }
2327 if next := pkg.test; next != nil && next.stack == nil {
2328 next.stack = pkg
2329 ld.pkgs = append(ld.pkgs, next)
2330 }
2331 }
2332 for _, pkg := range ld.roots {
2333 pkg.stack = nil
2334 }
2335 }
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345 func (pkg *loadPkg) stackText() string {
2346 var stack []*loadPkg
2347 for p := pkg; p != nil; p = p.stack {
2348 stack = append(stack, p)
2349 }
2350
2351 var buf strings.Builder
2352 for i := len(stack) - 1; i >= 0; i-- {
2353 p := stack[i]
2354 fmt.Fprint(&buf, p.path)
2355 if p.testOf != nil {
2356 fmt.Fprint(&buf, ".test")
2357 }
2358 if i > 0 {
2359 if stack[i-1].testOf == p {
2360 fmt.Fprint(&buf, " tested by\n\t")
2361 } else {
2362 fmt.Fprint(&buf, " imports\n\t")
2363 }
2364 }
2365 }
2366 return buf.String()
2367 }
2368
2369
2370
2371 func (pkg *loadPkg) why() string {
2372 var buf strings.Builder
2373 var stack []*loadPkg
2374 for p := pkg; p != nil; p = p.stack {
2375 stack = append(stack, p)
2376 }
2377
2378 for i := len(stack) - 1; i >= 0; i-- {
2379 p := stack[i]
2380 if p.testOf != nil {
2381 fmt.Fprintf(&buf, "%s.test\n", p.testOf.path)
2382 } else {
2383 fmt.Fprintf(&buf, "%s\n", p.path)
2384 }
2385 }
2386 return buf.String()
2387 }
2388
2389
2390
2391
2392
2393
2394 func Why(path string) string {
2395 pkg, ok := loaded.pkgCache.Get(path)
2396 if !ok {
2397 return ""
2398 }
2399 return pkg.why()
2400 }
2401
2402
2403
2404
2405 func WhyDepth(path string) int {
2406 n := 0
2407 pkg, _ := loaded.pkgCache.Get(path)
2408 for p := pkg; p != nil; p = p.stack {
2409 n++
2410 }
2411 return n
2412 }
2413
View as plain text