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(ld *Loader, 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, pld *packageLoader) {
261 for _, m := range matches {
262 switch {
263 case m.IsLocal():
264
265 if m.Dirs == nil {
266 matchModRoots := ld.modRoots
267 if opts.MainModule != (module.Version{}) {
268 matchModRoots = []string{ld.MainModules.ModRoot(opts.MainModule)}
269 }
270 matchLocalDirs(ld, 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(ld, ctx, dir, rs)
282 if err != nil {
283 if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) {
284 continue
285 }
286
287
288
289 if !ld.HasModRoot() {
290 die(ld)
291 }
292
293 if pld != 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(ld, ctx)
307 if err != nil {
308
309
310
311
312
313
314 m.Errs = append(m.Errs, err)
315 }
316 matchPackages(ld, ctx, m, opts.Tags, includeStd, mg.BuildList())
317
318 case m.Pattern() == "work":
319 matchModules := ld.MainModules.Versions()
320 if opts.MainModule != (module.Version{}) {
321 matchModules = []module.Version{opts.MainModule}
322 }
323 matchPackages(ld, ctx, m, opts.Tags, omitStd, matchModules)
324
325 case m.Pattern() == "all":
326 if pld == nil {
327
328
329 m.Errs = m.Errs[:0]
330 matchModules := ld.MainModules.Versions()
331 if opts.MainModule != (module.Version{}) {
332 matchModules = []module.Version{opts.MainModule}
333 }
334 matchPackages(ld, ctx, m, opts.Tags, omitStd, matchModules)
335 for tool := range ld.MainModules.Tools() {
336 m.Pkgs = append(m.Pkgs, tool)
337 }
338 } else {
339
340
341 m.Pkgs = pld.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 ld.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(ld, ctx, &opts)
360 if err != nil {
361 base.Fatal(err)
362 }
363
364 pld := loadFromRoots(ld, 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(pld.requirements, pld)
381
382
383
384 if !pld.SilencePackageErrors {
385 for _, match := range matches {
386 for _, err := range match.Errs {
387 pld.error(err)
388 }
389 }
390 }
391 pld.exitIfErrors(ctx)
392
393 if !opts.SilenceUnmatchedWarnings {
394 search.WarnUnmatched(matches)
395 }
396
397 if opts.Tidy {
398 if cfg.BuildV {
399 mg, _ := pld.requirements.Graph(ld, ctx)
400 for _, m := range initialRS.rootModules {
401 var unused bool
402 if pld.requirements.pruning == unpruned {
403
404
405
406 unused = mg.Selected(m.Path) == "none"
407 } else {
408
409
410
411 _, ok := pld.requirements.rootSelected(ld, 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(ld, ctx, pld, pld.requirements, loadedZipSumsOnly)
421 compatVersion := pld.TidyCompatibleVersion
422 goVersion := pld.requirements.GoVersion(ld)
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 != pld.requirements.pruning {
439 compatRS := newRequirements(ld, compatPruning, pld.requirements.rootModules, pld.requirements.direct)
440 pld.checkTidyCompatibility(ld, ctx, compatRS, compatVersion)
441
442 for m := range keepSums(ld, ctx, pld, compatRS, loadedZipSumsOnly) {
443 keep[m] = true
444 }
445 }
446
447 if opts.TidyDiff {
448 cfg.BuildMod = "readonly"
449 ld.pkgLoader = pld
450 ld.requirements = ld.pkgLoader.requirements
451 currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(ld, 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 ld.Fetcher().TrimGoSum(keep)
458
459
460 if gover.Compare(compatVersion, "1.16") > 0 {
461 keep = keepSums(ld, ctx, ld.pkgLoader, ld.requirements, addBuildListZipSums)
462 }
463 currentGoSum, tidyGoSum := ld.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 ld.Fetcher().TrimGoSum(keep)
479
480
481
482
483
484
485 if err := ld.Fetcher().WriteGoSum(ctx, keep, mustHaveCompleteRequirements(ld)); 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 ld.pkgLoader = pld
500 ld.requirements = ld.pkgLoader.requirements
501
502 for _, pkg := range pld.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(ld, ctx, WriteOpts{}); err != nil {
511 base.Fatal(err)
512 }
513 }
514
515 return matches, loadedPackages
516 }
517
518
519
520 func matchLocalDirs(ld *Loader, 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(ld, ctx, absDir, rs) == "" {
539 m.Dirs = []string{}
540 scope := "main module or its selected dependencies"
541 if ld.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(ld *Loader, 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 ld.MainModules.Versions() {
592 modRoot := ld.MainModules.ModRoot(mod)
593 if modRoot != "" && absDir == modRoot {
594 if absDir == cfg.GOROOTsrc {
595 return "", errPkgIsGorootSrc
596 }
597 return ld.MainModules.PathPrefix(mod), nil
598 }
599 }
600
601
602
603
604 var pkgNotFoundErr error
605 pkgNotFoundLongestPrefix := ""
606 for _, mainModule := range ld.MainModules.Versions() {
607 modRoot := ld.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(ld))
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 := ld.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(ld, 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 ld.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(ld *Loader, 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(ld, m); repl.Path != "" && repl.Version == "" {
696 root = repl.Path
697 if !filepath.IsAbs(root) {
698 root = filepath.Join(replaceRelativeTo(ld), 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(ld, 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(ld, 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(ld *Loader, ctx context.Context, gofiles []string) {
762 rs := LoadModFile(ld, 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 ld.pkgLoader = loadFromRoots(ld, 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 ld.requirements = ld.pkgLoader.requirements
784
785 if !ExplicitWriteGoMod {
786 if err := commitRequirements(ld, ctx, WriteOpts{}); err != nil {
787 base.Fatal(err)
788 }
789 }
790 }
791
792
793
794 func (mms *MainModuleSet) DirImportPath(ld *Loader, ctx context.Context, dir string) (path string, m module.Version) {
795 if !ld.HasModRoot() {
796 return ".", module.Version{}
797 }
798 LoadModFile(ld, 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 := ld.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 (ld *Loader) PackageModule(path string) module.Version {
837 pkg, ok := ld.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(ld *Loader, 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 = ld.pkgLoader.stdVendor(ld, parentPath, path)
855 }
856 pkg, ok := ld.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 (pld *packageLoader) reset() {
912 select {
913 case <-pld.work.Idle():
914 default:
915 panic("loader.reset when not idle")
916 }
917
918 pld.roots = nil
919 pld.pkgCache = new(par.Cache[string, *loadPkg])
920 pld.pkgs = nil
921 }
922
923
924
925 func (pld *packageLoader) error(err error) {
926 if pld.AllowErrors {
927 fmt.Fprintf(os.Stderr, "go: %v\n", err)
928 } else if pld.Switcher != nil {
929 pld.Switcher.Error(err)
930 } else {
931 base.Error(err)
932 }
933 }
934
935
936 func (pld *packageLoader) switchIfErrors(ctx context.Context) {
937 if pld.Switcher != nil {
938 pld.Switcher.Switch(ctx)
939 }
940 }
941
942
943
944 func (pld *packageLoader) exitIfErrors(ctx context.Context) {
945 pld.switchIfErrors(ctx)
946 base.ExitIfErrors()
947 }
948
949
950
951
952 func (pld *packageLoader) goVersion(ld *Loader) string {
953 if pld.TidyGoVersion != "" {
954 return pld.TidyGoVersion
955 }
956 return pld.requirements.GoVersion(ld)
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(ld *Loader) bool {
1060 if pkg.mod.Path == "" {
1061 return false
1062 }
1063 return !ld.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(ld *Loader, ctx context.Context, params loaderParams) *packageLoader {
1075 pld := &packageLoader{
1076 loaderParams: params,
1077 work: par.NewQueue(runtime.GOMAXPROCS(0)),
1078 }
1079
1080 if pld.requirements.pruning == unpruned {
1081
1082
1083
1084
1085
1086
1087
1088
1089 var err error
1090 pld.requirements, _, err = expandGraph(ld, ctx, pld.requirements)
1091 if err != nil {
1092 pld.error(err)
1093 }
1094 }
1095 pld.exitIfErrors(ctx)
1096
1097 updateGoVersion := func() {
1098 goVersion := pld.goVersion(ld)
1099
1100 if pld.requirements.pruning != workspace {
1101 var err error
1102 pld.requirements, err = convertPruning(ld, ctx, pld.requirements, pruningForGoVersion(goVersion))
1103 if err != nil {
1104 pld.error(err)
1105 pld.exitIfErrors(ctx)
1106 }
1107 }
1108
1109
1110
1111
1112 pld.skipImportModFiles = pld.Tidy && gover.Compare(goVersion, gover.TidyGoModSumVersion) < 0
1113
1114
1115
1116 pld.allClosesOverTests = gover.Compare(goVersion, gover.NarrowAllVersion) < 0 && !pld.UseVendorAll
1117 }
1118
1119 for {
1120 pld.reset()
1121 updateGoVersion()
1122
1123
1124
1125
1126
1127 rootPkgs := pld.listRoots(pld.requirements)
1128
1129 if pld.requirements.pruning == pruned && cfg.BuildMod == "mod" {
1130
1131
1132
1133
1134
1135
1136 changedBuildList := pld.preloadRootModules(ld, 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 := pld.pkg(ld, ctx, path, pkgIsRoot)
1150 if !inRoots[root] {
1151 pld.roots = append(pld.roots, root)
1152 inRoots[root] = true
1153 }
1154 }
1155
1156
1157
1158
1159
1160
1161 <-pld.work.Idle()
1162
1163 pld.buildStacks()
1164
1165 changed, err := pld.updateRequirements(ld, ctx)
1166 if err != nil {
1167 pld.error(err)
1168 break
1169 }
1170 if changed {
1171
1172
1173
1174
1175
1176 continue
1177 }
1178
1179 if !pld.ResolveMissingImports || (!ld.HasModRoot() && !ld.allowMissingModuleImports) {
1180
1181 break
1182 }
1183
1184 modAddedBy, err := pld.resolveMissingImports(ld, ctx)
1185 if err != nil {
1186 pld.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 := pld.requirements.direct
1211 rs, err := updateRoots(ld, ctx, direct, pld.requirements, noPkgs, toAdd, pld.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 pld.error(fmt.Errorf("%s: %w", pkg.stackText(), err.Err))
1219 break
1220 }
1221 }
1222 pld.error(err)
1223 break
1224 }
1225 if slices.Equal(rs.rootModules, pld.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 pld.requirements = rs
1233 }
1234 pld.exitIfErrors(ctx)
1235
1236
1237
1238 if pld.Tidy {
1239 rs, err := tidyRoots(ld, ctx, pld.requirements, pld.pkgs)
1240 if err != nil {
1241 pld.error(err)
1242 } else {
1243 if pld.TidyGoVersion != "" {
1244
1245
1246
1247 tidy := overrideRoots(ld, ctx, rs, []module.Version{{Path: "go", Version: pld.TidyGoVersion}})
1248 mg, err := tidy.Graph(ld, ctx)
1249 if err != nil {
1250 pld.error(err)
1251 }
1252 if v := mg.Selected("go"); v == pld.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: pld.TidyGoVersion},
1260 }
1261 msg := conflict.Summary()
1262 if cfg.BuildV {
1263 msg = conflict.String()
1264 }
1265 pld.error(errors.New(msg))
1266 }
1267 }
1268
1269 if pld.requirements.pruning == pruned {
1270
1271
1272
1273
1274
1275
1276 for _, m := range rs.rootModules {
1277 if m.Path == "go" && pld.TidyGoVersion != "" {
1278 continue
1279 }
1280 if v, ok := pld.requirements.rootSelected(ld, m.Path); !ok || v != m.Version {
1281 pld.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 pld.requirements = rs
1287 }
1288
1289 pld.exitIfErrors(ctx)
1290 }
1291
1292
1293 for _, pkg := range pld.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 pld.SilenceMissingStdImports {
1316 continue
1317 }
1318 }
1319 if pld.SilencePackageErrors {
1320 continue
1321 }
1322 if pld.SilenceNoGoErrors && errors.Is(pkg.err, imports.ErrNoGo) {
1323 continue
1324 }
1325
1326 pld.error(fmt.Errorf("%s: %w", pkg.stackText(), pkg.err))
1327 }
1328
1329 pld.checkMultiplePaths(ld)
1330 return pld
1331 }
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352 func (pld *packageLoader) updateRequirements(ld *Loader, ctx context.Context) (changed bool, err error) {
1353 rs := pld.requirements
1354
1355
1356
1357 var direct map[string]bool
1358
1359
1360
1361
1362
1363 loadedDirect := pld.allPatternIsRoot && maps.Equal(pld.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 pld.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 != "" || !ld.MainModules.Contains(pkg.mod.Path) {
1386 continue
1387 }
1388
1389 for _, dep := range pkg.imports {
1390 if !dep.fromExternalModule(ld) {
1391 continue
1392 }
1393
1394 if ld.inWorkspaceMode() {
1395
1396
1397
1398 if cfg.BuildMod == "vendor" {
1399
1400
1401
1402
1403
1404
1405 continue
1406 }
1407 if mg, err := rs.Graph(ld, 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(ld, 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 pld.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(ld, ctx, rs, pld.pkgs)
1486 if err != nil {
1487 return false, err
1488 }
1489 addRoots = tidy.rootModules
1490 }
1491
1492 rs, err = updateRoots(ld, ctx, direct, rs, pld.pkgs, addRoots, pld.AssumeRootsImported)
1493 if err != nil {
1494
1495
1496 return false, err
1497 }
1498
1499 if rs.GoVersion(ld) != pld.requirements.GoVersion(ld) {
1500
1501
1502
1503
1504
1505 changed = true
1506 } else if rs != pld.requirements && !slices.Equal(rs.rootModules, pld.requirements.rootModules) {
1507
1508
1509
1510 mg, err := rs.Graph(ld, ctx)
1511 if err != nil {
1512 return false, err
1513 }
1514 for _, pkg := range pld.pkgs {
1515 if pkg.fromExternalModule(ld) && 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(ld, ctx, pkg.path, rs, nil, pld.skipImportModFiles); err == nil {
1536 changed = true
1537 break
1538 }
1539 }
1540 }
1541 }
1542
1543 pld.requirements = rs
1544 return changed, nil
1545 }
1546
1547
1548
1549
1550
1551
1552
1553 func (pld *packageLoader) resolveMissingImports(ld *Loader, 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 pld.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 pld.work.Add(func() {
1576 var err error
1577 mod, err = queryImport(ld, ctx, pkg.path, pld.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 ld.MainModules.Contains(curstack.mod.Path) {
1582 ime.ImportingMainModule = curstack.mod
1583 ime.modRoot = ld.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 <-pld.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 (pld *packageLoader) pkg(ld *Loader, 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 := pld.pkgCache.Do(path, func() *loadPkg {
1660 pkg := &loadPkg{
1661 path: path,
1662 }
1663 pld.applyPkgFlags(ld, ctx, pkg, flags)
1664
1665 pld.work.Add(func() { pld.load(ld, ctx, pkg) })
1666 return pkg
1667 })
1668
1669 pld.applyPkgFlags(ld, ctx, pkg, flags)
1670 return pkg
1671 }
1672
1673
1674
1675
1676 func (pld *packageLoader) applyPkgFlags(ld *Loader, ctx context.Context, pkg *loadPkg, flags loadPkgFlags) {
1677 if flags == 0 {
1678 return
1679 }
1680
1681 if flags.has(pkgInAll) && pld.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 pld.allPatternIsRoot && ld.MainModules.Contains(pkg.mod.Path):
1705
1706
1707
1708
1709
1710 wantTest = true
1711
1712 case pld.allPatternIsRoot && pld.allClosesOverTests && new.has(pkgInAll):
1713
1714
1715
1716 wantTest = true
1717
1718 case pld.LoadTests && new.has(pkgIsRoot):
1719
1720 wantTest = true
1721 }
1722
1723 if wantTest {
1724 var testFlags loadPkgFlags
1725 if ld.MainModules.Contains(pkg.mod.Path) || (pld.allClosesOverTests && new.has(pkgInAll)) {
1726
1727
1728
1729 testFlags |= pkgInAll
1730 }
1731 pld.pkgTest(ld, ctx, pkg, testFlags)
1732 }
1733 }
1734
1735 if new.has(pkgInAll) && !old.has(pkgInAll|pkgImportsLoaded) {
1736
1737
1738 for _, dep := range pkg.imports {
1739 pld.applyPkgFlags(ld, ctx, dep, pkgInAll)
1740 }
1741 }
1742
1743 if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {
1744 for _, dep := range pkg.imports {
1745 pld.applyPkgFlags(ld, ctx, dep, pkgFromRoot)
1746 }
1747 }
1748 }
1749
1750
1751
1752
1753 func (pld *packageLoader) preloadRootModules(ld *Loader, 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 pld.work.Add(func() {
1759
1760
1761
1762
1763
1764 m, _, _, _, err := importFromModules(ld, ctx, path, pld.requirements, nil, pld.skipImportModFiles)
1765 if err != nil {
1766 if _, ok := errors.AsType[*ImportMissingError](err); ok && pld.ResolveMissingImports {
1767
1768
1769 m, err = queryImport(ld, ctx, path, pld.requirements)
1770 }
1771 if err != nil {
1772
1773
1774 return
1775 }
1776 }
1777 if m.Path == "" {
1778
1779 return
1780 }
1781
1782 v, ok := pld.requirements.rootSelected(ld, 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 <-pld.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(ld, ctx, pld.requirements.direct, pld.requirements, nil, toAdd, pld.AssumeRootsImported)
1811 if err != nil {
1812
1813
1814
1815 pld.error(err)
1816 pld.exitIfErrors(ctx)
1817 return false
1818 }
1819 if slices.Equal(rs.rootModules, pld.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 pld.requirements = rs
1828 return true
1829 }
1830
1831
1832 func (pld *packageLoader) load(ld *Loader, ctx context.Context, pkg *loadPkg) {
1833 var mg *ModuleGraph
1834 if pld.requirements.pruning == unpruned {
1835 var err error
1836 mg, err = pld.requirements.Graph(ld, 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(ld, ctx, pkg.path, pld.requirements, mg, pld.skipImportModFiles)
1852 if ld.MainModules.Tools()[pkg.path] {
1853
1854
1855
1856 pld.applyPkgFlags(ld, ctx, pkg, pkgInAll)
1857 }
1858 if pkg.dir == "" {
1859 return
1860 }
1861 if ld.MainModules.Contains(pkg.mod.Path) {
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871 pld.applyPkgFlags(ld, ctx, pkg, pkgInAll)
1872 }
1873 if pld.AllowPackage != nil {
1874 if err := pld.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, pld.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 = pld.stdVendor(ld, pkg.path, path)
1904 }
1905 pkg.imports = append(pkg.imports, pld.pkg(ld, ctx, path, importFlags))
1906 }
1907 pkg.testImports = testImports
1908
1909 pld.applyPkgFlags(ld, ctx, pkg, pkgImportsLoaded)
1910 }
1911
1912
1913
1914
1915
1916
1917 func (pld *packageLoader) pkgTest(ld *Loader, 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 pld.applyPkgFlags(ld, 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 = pld.stdVendor(ld, test.path, path)
1946 }
1947 test.imports = append(test.imports, pld.pkg(ld, ctx, path, importFlags))
1948 }
1949 pkg.testImports = nil
1950 pld.applyPkgFlags(ld, ctx, test, pkgImportsLoaded)
1951 } else {
1952 pld.applyPkgFlags(ld, ctx, test, testFlags)
1953 }
1954
1955 return test
1956 }
1957
1958
1959
1960 func (pld *packageLoader) stdVendor(ld *Loader, 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 !pld.VendorModulesInGOROOTSrc || !ld.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 !pld.VendorModulesInGOROOTSrc || !ld.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 (pld *packageLoader) computePatternAll() (all []string) {
2002 for _, pkg := range pld.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 (pld *packageLoader) checkMultiplePaths(ld *Loader) {
2023 if cached := pld.requirements.graph.Load(); cached != nil {
2024 if mg := cached.mg; mg != nil {
2025
2026
2027
2028 mg.checkPathsOnce.Do(func() {
2029 checkMultiplePathsUncached(ld, pld, mg.BuildList())
2030 })
2031 return
2032 }
2033 }
2034 checkMultiplePathsUncached(ld, pld, pld.requirements.rootModules)
2035 }
2036
2037 func checkMultiplePathsUncached(ld *Loader, pld *packageLoader, mods []module.Version) {
2038 firstPath := map[module.Version]string{}
2039 for _, mod := range mods {
2040 src := resolveReplacement(ld, mod)
2041 if prev, ok := firstPath[src]; !ok {
2042 firstPath[src] = mod.Path
2043 } else if prev != mod.Path {
2044 pld.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 (pld *packageLoader) checkTidyCompatibility(ld *Loader, ctx context.Context, rs *Requirements, compatVersion string) {
2052 goVersion := rs.GoVersion(ld)
2053 suggestUpgrade := false
2054 suggestEFlag := false
2055 suggestFixes := func() {
2056 if pld.AllowErrors {
2057
2058
2059 return
2060 }
2061
2062
2063
2064
2065
2066 fmt.Fprintln(os.Stderr)
2067
2068 goFlag := ""
2069 if goVersion != ld.MainModules.GoVersion(ld) {
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(ld, ctx)
2099 if err != nil {
2100 pld.error(fmt.Errorf("error loading go %s module graph: %w", compatVersion, err))
2101 pld.switchIfErrors(ctx)
2102 suggestFixes()
2103 pld.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 pld.pkgs {
2128 if pkg.mod.Path == "" && pkg.err == nil {
2129
2130
2131 continue
2132 }
2133
2134 pkg := pkg
2135 pld.work.Add(func() {
2136 mod, _, _, _, err := importFromModules(ld, ctx, pkg.path, rs, mg, pld.skipImportModFiles)
2137 if mod != pkg.mod {
2138 mismatches := <-mismatchMu
2139 mismatches[pkg] = mismatch{mod: mod, err: err}
2140 mismatchMu <- mismatches
2141 }
2142 })
2143 }
2144 <-pld.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 pld.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://go.dev/issue.", m.Path, goVersion, m.Version, compatVersion, v)
2163 }
2164 }
2165 return
2166 }
2167
2168
2169
2170 for _, pkg := range pld.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 pld.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 pld.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 pld.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 pld.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 pld.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 pld.switchIfErrors(ctx)
2262 suggestFixes()
2263 pld.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 (pld *packageLoader) buildStacks() {
2312 if len(pld.pkgs) > 0 {
2313 panic("buildStacks")
2314 }
2315 for _, pkg := range pld.roots {
2316 pkg.stack = pkg
2317 pld.pkgs = append(pld.pkgs, pkg)
2318 }
2319 for i := 0; i < len(pld.pkgs); i++ {
2320 pkg := pld.pkgs[i]
2321 for _, next := range pkg.imports {
2322 if next.stack == nil {
2323 next.stack = pkg
2324 pld.pkgs = append(pld.pkgs, next)
2325 }
2326 }
2327 if next := pkg.test; next != nil && next.stack == nil {
2328 next.stack = pkg
2329 pld.pkgs = append(pld.pkgs, next)
2330 }
2331 }
2332 for _, pkg := range pld.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 (ld *Loader) Why(path string) string {
2395 pkg, ok := ld.pkgLoader.pkgCache.Get(path)
2396 if !ok {
2397 return ""
2398 }
2399 return pkg.why()
2400 }
2401
2402
2403
2404
2405 func (ld *Loader) WhyDepth(path string) int {
2406 n := 0
2407 pkg, _ := ld.pkgLoader.pkgCache.Get(path)
2408 for p := pkg; p != nil; p = p.stack {
2409 n++
2410 }
2411 return n
2412 }
2413
View as plain text