@@ -12,6 +12,7 @@ import (
1212 "io/ioutil"
1313 "os"
1414 "path"
15+ pathpkg "path"
1516 "path/filepath"
1617 "sort"
1718 "strings"
@@ -90,7 +91,9 @@ func ImportPaths(patterns []string) []*search.Match {
9091 // the exact version of a particular module increases during
9192 // the loader iterations.
9293 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 {
9497 dir := pkg
9598 if ! filepath .IsAbs (dir ) {
9699 dir = filepath .Join (cwd , pkg )
@@ -108,6 +111,16 @@ func ImportPaths(patterns []string) []*search.Match {
108111 if strings .HasPrefix (suffix , "/vendor/" ) {
109112 // TODO getmode vendor check
110113 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+ }
111124 } else {
112125 pkg = Target .Path + suffix
113126 }
@@ -129,10 +142,10 @@ func ImportPaths(patterns []string) []*search.Match {
129142 // After loader is done iterating, we still need to return the
130143 // path, so that "go list -e" produces valid output.
131144 if iterating {
132- pkg = ""
145+ continue
133146 }
134147 }
135- m .Pkgs [ j ] = pkg
148+ m .Pkgs = append ( m . Pkgs , pkg )
136149 }
137150
138151 case strings .Contains (m .Pattern , "..." ):
@@ -163,9 +176,7 @@ func ImportPaths(patterns []string) []*search.Match {
163176 updateMatches (true )
164177 for _ , m := range matches {
165178 for _ , pkg := range m .Pkgs {
166- if pkg != "" {
167- roots = append (roots , pkg )
168- }
179+ roots = append (roots , pkg )
169180 }
170181 }
171182 return roots
@@ -394,13 +405,17 @@ func ModuleUsedDirectly(path string) bool {
394405}
395406
396407// 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 .
398409// Lookup requires that one of the Load functions in this package has already
399410// 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 ) {
401412 if path == "" {
402413 panic ("Lookup called with empty package path" )
403414 }
415+
416+ if parentIsStd {
417+ path = loaded .stdVendor (parentPath , path )
418+ }
404419 pkg , ok := loaded .pkgCache .Get (path ).(* loadPkg )
405420 if ! ok {
406421 // The loader should have found all the relevant paths.
@@ -434,10 +449,11 @@ func Lookup(path string) (dir, realPath string, err error) {
434449// TODO(rsc): It might be nice to make the loader take and return
435450// a buildList rather than hard-coding use of the global.
436451type 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
441457
442458 // reset on each iteration
443459 roots []* loadPkg
@@ -457,6 +473,17 @@ func newLoader() *loader {
457473 ld := new (loader )
458474 ld .tags = imports .Tags ()
459475 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+
460487 return ld
461488}
462489
@@ -631,7 +658,11 @@ func (ld *loader) doPkg(item interface{}) {
631658 }
632659 }
633660
661+ inStd := (search .IsStandardImportPath (pkg .path ) && search .InDir (pkg .dir , cfg .GOROOTsrc ) != "" )
634662 for _ , path := range imports {
663+ if inStd {
664+ path = ld .stdVendor (pkg .path , path )
665+ }
635666 pkg .imports = append (pkg .imports , ld .pkg (path , false ))
636667 }
637668
@@ -642,6 +673,30 @@ func (ld *loader) doPkg(item interface{}) {
642673 }
643674}
644675
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+
645700// computePatternAll returns the list of packages matching pattern "all",
646701// starting with a list of the import paths for the packages in the main module.
647702func (ld * loader ) computePatternAll (paths []string ) []string {
@@ -932,6 +987,20 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
932987 return vendorList , nil
933988 }
934989
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+
9351004 origPath := mod .Path
9361005 if repl := Replacement (mod ); repl .Path != "" {
9371006 if repl .Version == "" {
0 commit comments