@@ -12,6 +12,7 @@ import (
12
12
"io/ioutil"
13
13
"os"
14
14
"path"
15
+ pathpkg "path"
15
16
"path/filepath"
16
17
"sort"
17
18
"strings"
@@ -90,7 +91,9 @@ func ImportPaths(patterns []string) []*search.Match {
90
91
// the exact version of a particular module increases during
91
92
// the loader iterations.
92
93
m .Pkgs = str .StringList (fsDirs [i ])
93
- for j , pkg := range m .Pkgs {
94
+ pkgs := m .Pkgs
95
+ m .Pkgs = m .Pkgs [:0 ]
96
+ for _ , pkg := range pkgs {
94
97
dir := pkg
95
98
if ! filepath .IsAbs (dir ) {
96
99
dir = filepath .Join (cwd , pkg )
@@ -108,6 +111,16 @@ func ImportPaths(patterns []string) []*search.Match {
108
111
if strings .HasPrefix (suffix , "/vendor/" ) {
109
112
// TODO getmode vendor check
110
113
pkg = strings .TrimPrefix (suffix , "/vendor/" )
114
+ } else if Target .Path == "std" {
115
+ // Don't add the prefix "std/" to packages in the "std" module.
116
+ // It's the one module path that isn't a prefix of its packages.
117
+ pkg = strings .TrimPrefix (suffix , "/" )
118
+ if pkg == "builtin" {
119
+ // "builtin" is a pseudo-package with a real source file.
120
+ // It's not included in "std", so it shouldn't be included in
121
+ // "./..." within module "std" either.
122
+ continue
123
+ }
111
124
} else {
112
125
pkg = Target .Path + suffix
113
126
}
@@ -129,10 +142,10 @@ func ImportPaths(patterns []string) []*search.Match {
129
142
// After loader is done iterating, we still need to return the
130
143
// path, so that "go list -e" produces valid output.
131
144
if iterating {
132
- pkg = ""
145
+ continue
133
146
}
134
147
}
135
- m .Pkgs [ j ] = pkg
148
+ m .Pkgs = append ( m . Pkgs , pkg )
136
149
}
137
150
138
151
case strings .Contains (m .Pattern , "..." ):
@@ -163,9 +176,7 @@ func ImportPaths(patterns []string) []*search.Match {
163
176
updateMatches (true )
164
177
for _ , m := range matches {
165
178
for _ , pkg := range m .Pkgs {
166
- if pkg != "" {
167
- roots = append (roots , pkg )
168
- }
179
+ roots = append (roots , pkg )
169
180
}
170
181
}
171
182
return roots
@@ -394,13 +405,17 @@ func ModuleUsedDirectly(path string) bool {
394
405
}
395
406
396
407
// Lookup returns the source directory, import path, and any loading error for
397
- // the package at path.
408
+ // the package at path as imported from the package in parentDir .
398
409
// Lookup requires that one of the Load functions in this package has already
399
410
// been called.
400
- func Lookup (path string ) (dir , realPath string , err error ) {
411
+ func Lookup (parentPath string , parentIsStd bool , path string ) (dir , realPath string , err error ) {
401
412
if path == "" {
402
413
panic ("Lookup called with empty package path" )
403
414
}
415
+
416
+ if parentIsStd {
417
+ path = loaded .stdVendor (parentPath , path )
418
+ }
404
419
pkg , ok := loaded .pkgCache .Get (path ).(* loadPkg )
405
420
if ! ok {
406
421
// The loader should have found all the relevant paths.
@@ -434,10 +449,11 @@ func Lookup(path string) (dir, realPath string, err error) {
434
449
// TODO(rsc): It might be nice to make the loader take and return
435
450
// a buildList rather than hard-coding use of the global.
436
451
type loader struct {
437
- tags map [string ]bool // tags for scanDir
438
- testRoots bool // include tests for roots
439
- isALL bool // created with LoadALL
440
- testAll bool // include tests for all packages
452
+ tags map [string ]bool // tags for scanDir
453
+ testRoots bool // include tests for roots
454
+ isALL bool // created with LoadALL
455
+ testAll bool // include tests for all packages
456
+ forceStdVendor bool // if true, load standard-library dependencies from the vendor subtree
441
457
442
458
// reset on each iteration
443
459
roots []* loadPkg
@@ -457,6 +473,17 @@ func newLoader() *loader {
457
473
ld := new (loader )
458
474
ld .tags = imports .Tags ()
459
475
ld .testRoots = LoadTests
476
+
477
+ switch Target .Path {
478
+ case "std" , "cmd" :
479
+ // Inside the "std" and "cmd" modules, we prefer to use the vendor directory
480
+ // unless the command explicitly changes the module graph.
481
+ // TODO(golang.org/issue/30240): Remove this special case.
482
+ if cfg .CmdName != "get" && ! strings .HasPrefix (cfg .CmdName , "mod " ) {
483
+ ld .forceStdVendor = true
484
+ }
485
+ }
486
+
460
487
return ld
461
488
}
462
489
@@ -631,7 +658,11 @@ func (ld *loader) doPkg(item interface{}) {
631
658
}
632
659
}
633
660
661
+ inStd := (search .IsStandardImportPath (pkg .path ) && search .InDir (pkg .dir , cfg .GOROOTsrc ) != "" )
634
662
for _ , path := range imports {
663
+ if inStd {
664
+ path = ld .stdVendor (pkg .path , path )
665
+ }
635
666
pkg .imports = append (pkg .imports , ld .pkg (path , false ))
636
667
}
637
668
@@ -642,6 +673,30 @@ func (ld *loader) doPkg(item interface{}) {
642
673
}
643
674
}
644
675
676
+ // stdVendor returns the canonical import path for the package with the given
677
+ // path when imported from the standard-library package at parentPath.
678
+ func (ld * loader ) stdVendor (parentPath , path string ) string {
679
+ if search .IsStandardImportPath (path ) {
680
+ return path
681
+ }
682
+
683
+ if str .HasPathPrefix (parentPath , "cmd" ) && (Target .Path != "cmd" || ld .forceStdVendor ) {
684
+ vendorPath := pathpkg .Join ("cmd" , "vendor" , path )
685
+ if _ , err := os .Stat (filepath .Join (cfg .GOROOTsrc , filepath .FromSlash (vendorPath ))); err == nil {
686
+ return vendorPath
687
+ }
688
+ }
689
+ if Target .Path != "std" || ld .forceStdVendor {
690
+ vendorPath := pathpkg .Join ("vendor" , path )
691
+ if _ , err := os .Stat (filepath .Join (cfg .GOROOTsrc , filepath .FromSlash (vendorPath ))); err == nil {
692
+ return vendorPath
693
+ }
694
+ }
695
+
696
+ // Not vendored: resolve from modules.
697
+ return path
698
+ }
699
+
645
700
// computePatternAll returns the list of packages matching pattern "all",
646
701
// starting with a list of the import paths for the packages in the main module.
647
702
func (ld * loader ) computePatternAll (paths []string ) []string {
@@ -932,6 +987,20 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
932
987
return vendorList , nil
933
988
}
934
989
990
+ switch Target .Path {
991
+ case "std" , "cmd" :
992
+ // When inside "std" or "cmd", only fetch and read go.mod files if we're
993
+ // explicitly running a command that can change the module graph. If we have
994
+ // to resolve a new dependency, we might pick the wrong version, but 'go mod
995
+ // tidy' will fix it — and new standard-library dependencies should be rare
996
+ // anyway.
997
+ //
998
+ // TODO(golang.org/issue/30240): Drop this special-case.
999
+ if cfg .CmdName != "get" && ! strings .HasPrefix (cfg .CmdName , "mod " ) {
1000
+ return nil , nil
1001
+ }
1002
+ }
1003
+
935
1004
origPath := mod .Path
936
1005
if repl := Replacement (mod ); repl .Path != "" {
937
1006
if repl .Version == "" {
0 commit comments