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