@@ -144,7 +144,7 @@ func main() {
144
144
} else {
145
145
stds , err := exec .Command (goCmd (), "list" , "std" ).Output ()
146
146
if err != nil {
147
- log .Fatal ( err )
147
+ log .Fatalf ( "go list std: %v \n %s" , err , stds )
148
148
}
149
149
for _ , pkg := range strings .Fields (string (stds )) {
150
150
if ! internalPkg .MatchString (pkg ) {
@@ -153,10 +153,25 @@ func main() {
153
153
}
154
154
}
155
155
156
+ importDir , importMap := loadImports ()
157
+
158
+ // The code below assumes that the import map can vary
159
+ // by package, so that an import in one package (directory) might mean
160
+ // something different from the same import in another.
161
+ // While this can happen in GOPATH mode with vendoring,
162
+ // it is not possible in the standard library: the one importMap
163
+ // returned by loadImports applies to all packages.
164
+ // Construct a per-directory importMap that resolves to
165
+ // that single map for all packages.
166
+ importMapForDir := make (map [string ]map [string ]string )
167
+ for _ , dir := range importDir {
168
+ importMapForDir [dir ] = importMap
169
+ }
156
170
var featureCtx = make (map [string ]map [string ]bool ) // feature -> context name -> true
157
171
for _ , context := range contexts {
158
172
w := NewWalker (context , filepath .Join (build .Default .GOROOT , "src" ))
159
- w .loadImports (pkgNames , w .context )
173
+ w .importDir = importDir
174
+ w .importMap = importMapForDir
160
175
161
176
for _ , name := range pkgNames {
162
177
// Vendored packages do not contribute to our
@@ -440,58 +455,58 @@ func tagKey(dir string, context *build.Context, tags []string) string {
440
455
return key
441
456
}
442
457
443
- func (w * Walker ) loadImports (paths []string , context * build.Context ) {
444
- if context == nil {
445
- context = & build .Default
446
- }
447
-
448
- var (
449
- tags = context .BuildTags
450
- cgoEnabled = "0"
451
- )
452
- if context .CgoEnabled {
453
- tags = append (tags [:len (tags ):len (tags )], "cgo" )
454
- cgoEnabled = "1"
455
- }
456
-
457
- // TODO(golang.org/issue/29666): Request only the fields that we need.
458
- cmd := exec .Command (goCmd (), "list" , "-e" , "-deps" , "-json" )
459
- if len (tags ) > 0 {
460
- cmd .Args = append (cmd .Args , "-tags" , strings .Join (tags , " " ))
461
- }
462
- cmd .Args = append (cmd .Args , paths ... )
463
-
464
- cmd .Env = append (os .Environ (),
465
- "GOOS=" + context .GOOS ,
466
- "GOARCH=" + context .GOARCH ,
467
- "CGO_ENABLED=" + cgoEnabled ,
468
- )
469
-
470
- stdout := new (bytes.Buffer )
471
- cmd .Stdout = stdout
472
- cmd .Stderr = new (strings.Builder )
473
- err := cmd .Run ()
458
+ // loadImports returns information about the packages in the standard library
459
+ // and the packages they themselves import.
460
+ // importDir maps expanded import path to the directory containing that package.
461
+ // importMap maps source import path to expanded import path.
462
+ // The source import path and expanded import path are identical except for vendored packages.
463
+ // For example, on return:
464
+ //
465
+ // importMap["math"] = "math"
466
+ // importDir["math"] = "<goroot>/src/math"
467
+ //
468
+ // importMap["golang.org/x/net/route"] = "vendor/golang.org/x/net/route"
469
+ // importDir["vendor/golang.org/x/net/route"] = "<goroot>/src/vendor/golang.org/x/net/route"
470
+ //
471
+ // There are a few imports that only appear on certain platforms,
472
+ // including it turns out x/net/route, and we add those explicitly.
473
+ func loadImports () (importDir map [string ]string , importMap map [string ]string ) {
474
+ out , err := exec .Command (goCmd (), "list" , "-e" , "-deps" , "-json" , "std" ).CombinedOutput ()
474
475
if err != nil {
475
- log .Fatalf ("%s failed : %v\n %s" , strings . Join ( cmd . Args , " " ), err , cmd . Stderr )
476
+ log .Fatalf ("loading imports : %v\n %s" , err , out )
476
477
}
477
478
478
- w . importDir = make (map [string ]string )
479
- w . importMap = make (map [ string ] map [string ]string )
480
- dec := json .NewDecoder (stdout )
479
+ importDir = make (map [string ]string )
480
+ importMap = make (map [string ]string )
481
+ dec := json .NewDecoder (bytes . NewReader ( out ) )
481
482
for {
482
483
var pkg struct {
483
484
ImportPath , Dir string
484
485
ImportMap map [string ]string
485
486
}
486
- if err := dec .Decode (& pkg ); err == io .EOF {
487
+ err := dec .Decode (& pkg )
488
+ if err == io .EOF {
487
489
break
488
- } else if err != nil {
489
- log .Fatalf ("%s: invalid output: %v" , strings .Join (cmd .Args , " " ), err )
490
+ }
491
+ if err != nil {
492
+ log .Fatalf ("go list: invalid output: %v" , err )
490
493
}
491
494
492
- w .importDir [pkg .ImportPath ] = pkg .Dir
493
- w .importMap [pkg .Dir ] = pkg .ImportMap
495
+ importDir [pkg .ImportPath ] = pkg .Dir
496
+ for k , v := range pkg .ImportMap {
497
+ importMap [k ] = v
498
+ }
494
499
}
500
+
501
+ // Fixup for vendor packages listed in args above.
502
+ fixup := []string {
503
+ "vendor/golang.org/x/net/route" ,
504
+ }
505
+ for _ , pkg := range fixup {
506
+ importDir [pkg ] = filepath .Join (build .Default .GOROOT , "src" , pkg )
507
+ importMap [strings .TrimPrefix (pkg , "vendor/" )] = pkg
508
+ }
509
+ return
495
510
}
496
511
497
512
// Importing is a sentinel taking the place in Walker.imported
@@ -523,7 +538,7 @@ func (w *Walker) ImportFrom(fromPath, fromDir string, mode types.ImportMode) (*t
523
538
dir = filepath .Join (w .root , filepath .FromSlash (name ))
524
539
}
525
540
if fi , err := os .Stat (dir ); err != nil || ! fi .IsDir () {
526
- log .Fatalf ("no source in tree for import %q: %v" , name , err )
541
+ log .Fatalf ("no source in tree for import %q (from import %s in %s) : %v" , name , fromPath , fromDir , err )
527
542
}
528
543
529
544
context := w .context
0 commit comments