1// Copyright 2011 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package list implements the “go list” command. 6package list 7 8import ( 9 "bufio" 10 "bytes" 11 "context" 12 "encoding/json" 13 "errors" 14 "fmt" 15 "io" 16 "os" 17 "reflect" 18 "runtime" 19 "sort" 20 "strconv" 21 "strings" 22 "sync" 23 "text/template" 24 25 "golang.org/x/sync/semaphore" 26 27 "cmd/go/internal/base" 28 "cmd/go/internal/cache" 29 "cmd/go/internal/cfg" 30 "cmd/go/internal/load" 31 "cmd/go/internal/modinfo" 32 "cmd/go/internal/modload" 33 "cmd/go/internal/str" 34 "cmd/go/internal/work" 35) 36 37var CmdList = &base.Command{ 38 // Note: -f -json -m are listed explicitly because they are the most common list flags. 39 // Do not send CLs removing them because they're covered by [list flags]. 40 UsageLine: "go list [-f format] [-json] [-m] [list flags] [build flags] [packages]", 41 Short: "list packages or modules", 42 Long: ` 43List lists the named packages, one per line. 44The most commonly-used flags are -f and -json, which control the form 45of the output printed for each package. Other list flags, documented below, 46control more specific details. 47 48The default output shows the package import path: 49 50 bytes 51 encoding/json 52 github.com/gorilla/mux 53 golang.org/x/net/html 54 55The -f flag specifies an alternate format for the list, using the 56syntax of package template. The default output is equivalent 57to -f '{{.ImportPath}}'. The struct being passed to the template is: 58 59 type Package struct { 60 Dir string // directory containing package sources 61 ImportPath string // import path of package in dir 62 ImportComment string // path in import comment on package statement 63 Name string // package name 64 Doc string // package documentation string 65 Target string // install path 66 Shlib string // the shared library that contains this package (only set when -linkshared) 67 Goroot bool // is this package in the Go root? 68 Standard bool // is this package part of the standard Go library? 69 Stale bool // would 'go install' do anything for this package? 70 StaleReason string // explanation for Stale==true 71 Root string // Go root or Go path dir containing this package 72 ConflictDir string // this directory shadows Dir in $GOPATH 73 BinaryOnly bool // binary-only package (no longer supported) 74 ForTest string // package is only for use in named test 75 Export string // file containing export data (when using -export) 76 BuildID string // build ID of the compiled package (when using -export) 77 Module *Module // info about package's containing module, if any (can be nil) 78 Match []string // command-line patterns matching this package 79 DepOnly bool // package is only a dependency, not explicitly listed 80 DefaultGODEBUG string // default GODEBUG setting, for main packages 81 82 // Source files 83 GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) 84 CgoFiles []string // .go source files that import "C" 85 CompiledGoFiles []string // .go files presented to compiler (when using -compiled) 86 IgnoredGoFiles []string // .go source files ignored due to build constraints 87 IgnoredOtherFiles []string // non-.go source files ignored due to build constraints 88 CFiles []string // .c source files 89 CXXFiles []string // .cc, .cxx and .cpp source files 90 MFiles []string // .m source files 91 HFiles []string // .h, .hh, .hpp and .hxx source files 92 FFiles []string // .f, .F, .for and .f90 Fortran source files 93 SFiles []string // .s source files 94 SwigFiles []string // .swig files 95 SwigCXXFiles []string // .swigcxx files 96 SysoFiles []string // .syso object files to add to archive 97 TestGoFiles []string // _test.go files in package 98 XTestGoFiles []string // _test.go files outside package 99 100 // Embedded files 101 EmbedPatterns []string // //go:embed patterns 102 EmbedFiles []string // files matched by EmbedPatterns 103 TestEmbedPatterns []string // //go:embed patterns in TestGoFiles 104 TestEmbedFiles []string // files matched by TestEmbedPatterns 105 XTestEmbedPatterns []string // //go:embed patterns in XTestGoFiles 106 XTestEmbedFiles []string // files matched by XTestEmbedPatterns 107 108 // Cgo directives 109 CgoCFLAGS []string // cgo: flags for C compiler 110 CgoCPPFLAGS []string // cgo: flags for C preprocessor 111 CgoCXXFLAGS []string // cgo: flags for C++ compiler 112 CgoFFLAGS []string // cgo: flags for Fortran compiler 113 CgoLDFLAGS []string // cgo: flags for linker 114 CgoPkgConfig []string // cgo: pkg-config names 115 116 // Dependency information 117 Imports []string // import paths used by this package 118 ImportMap map[string]string // map from source import to ImportPath (identity entries omitted) 119 Deps []string // all (recursively) imported dependencies 120 TestImports []string // imports from TestGoFiles 121 XTestImports []string // imports from XTestGoFiles 122 123 // Error information 124 Incomplete bool // this package or a dependency has an error 125 Error *PackageError // error loading package 126 DepsErrors []*PackageError // errors loading dependencies 127 } 128 129Packages stored in vendor directories report an ImportPath that includes the 130path to the vendor directory (for example, "d/vendor/p" instead of "p"), 131so that the ImportPath uniquely identifies a given copy of a package. 132The Imports, Deps, TestImports, and XTestImports lists also contain these 133expanded import paths. See golang.org/s/go15vendor for more about vendoring. 134 135The error information, if any, is 136 137 type PackageError struct { 138 ImportStack []string // shortest path from package named on command line to this one 139 Pos string // position of error (if present, file:line:col) 140 Err string // the error itself 141 } 142 143The module information is a Module struct, defined in the discussion 144of list -m below. 145 146The template function "join" calls strings.Join. 147 148The template function "context" returns the build context, defined as: 149 150 type Context struct { 151 GOARCH string // target architecture 152 GOOS string // target operating system 153 GOROOT string // Go root 154 GOPATH string // Go path 155 CgoEnabled bool // whether cgo can be used 156 UseAllFiles bool // use files regardless of //go:build lines, file names 157 Compiler string // compiler to assume when computing target paths 158 BuildTags []string // build constraints to match in //go:build lines 159 ToolTags []string // toolchain-specific build constraints 160 ReleaseTags []string // releases the current release is compatible with 161 InstallSuffix string // suffix to use in the name of the install dir 162 } 163 164For more information about the meaning of these fields see the documentation 165for the go/build package's Context type. 166 167The -json flag causes the package data to be printed in JSON format 168instead of using the template format. The JSON flag can optionally be 169provided with a set of comma-separated required field names to be output. 170If so, those required fields will always appear in JSON output, but 171others may be omitted to save work in computing the JSON struct. 172 173The -compiled flag causes list to set CompiledGoFiles to the Go source 174files presented to the compiler. Typically this means that it repeats 175the files listed in GoFiles and then also adds the Go code generated 176by processing CgoFiles and SwigFiles. The Imports list contains the 177union of all imports from both GoFiles and CompiledGoFiles. 178 179The -deps flag causes list to iterate over not just the named packages 180but also all their dependencies. It visits them in a depth-first post-order 181traversal, so that a package is listed only after all its dependencies. 182Packages not explicitly listed on the command line will have the DepOnly 183field set to true. 184 185The -e flag changes the handling of erroneous packages, those that 186cannot be found or are malformed. By default, the list command 187prints an error to standard error for each erroneous package and 188omits the packages from consideration during the usual printing. 189With the -e flag, the list command never prints errors to standard 190error and instead processes the erroneous packages with the usual 191printing. Erroneous packages will have a non-empty ImportPath and 192a non-nil Error field; other information may or may not be missing 193(zeroed). 194 195The -export flag causes list to set the Export field to the name of a 196file containing up-to-date export information for the given package, 197and the BuildID field to the build ID of the compiled package. 198 199The -find flag causes list to identify the named packages but not 200resolve their dependencies: the Imports and Deps lists will be empty. 201With the -find flag, the -deps, -test and -export commands cannot be 202used. 203 204The -test flag causes list to report not only the named packages 205but also their test binaries (for packages with tests), to convey to 206source code analysis tools exactly how test binaries are constructed. 207The reported import path for a test binary is the import path of 208the package followed by a ".test" suffix, as in "math/rand.test". 209When building a test, it is sometimes necessary to rebuild certain 210dependencies specially for that test (most commonly the tested 211package itself). The reported import path of a package recompiled 212for a particular test binary is followed by a space and the name of 213the test binary in brackets, as in "math/rand [math/rand.test]" 214or "regexp [sort.test]". The ForTest field is also set to the name 215of the package being tested ("math/rand" or "sort" in the previous 216examples). 217 218The Dir, Target, Shlib, Root, ConflictDir, and Export file paths 219are all absolute paths. 220 221By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir 222(that is, paths relative to Dir, not absolute paths). 223The generated files added when using the -compiled and -test flags 224are absolute paths referring to cached copies of generated Go source files. 225Although they are Go source files, the paths may not end in ".go". 226 227The -m flag causes list to list modules instead of packages. 228 229When listing modules, the -f flag still specifies a format template 230applied to a Go struct, but now a Module struct: 231 232 type Module struct { 233 Path string // module path 234 Query string // version query corresponding to this version 235 Version string // module version 236 Versions []string // available module versions 237 Replace *Module // replaced by this module 238 Time *time.Time // time version was created 239 Update *Module // available update (with -u) 240 Main bool // is this the main module? 241 Indirect bool // module is only indirectly needed by main module 242 Dir string // directory holding local copy of files, if any 243 GoMod string // path to go.mod file describing module, if any 244 GoVersion string // go version used in module 245 Retracted []string // retraction information, if any (with -retracted or -u) 246 Deprecated string // deprecation message, if any (with -u) 247 Error *ModuleError // error loading module 248 Sum string // checksum for path, version (as in go.sum) 249 GoModSum string // checksum for go.mod (as in go.sum) 250 Origin any // provenance of module 251 Reuse bool // reuse of old module info is safe 252 } 253 254 type ModuleError struct { 255 Err string // the error itself 256 } 257 258The file GoMod refers to may be outside the module directory if the 259module is in the module cache or if the -modfile flag is used. 260 261The default output is to print the module path and then 262information about the version and replacement if any. 263For example, 'go list -m all' might print: 264 265 my/main/module 266 golang.org/x/text v0.3.0 => /tmp/text 267 rsc.io/pdf v0.1.1 268 269The Module struct has a String method that formats this 270line of output, so that the default format is equivalent 271to -f '{{.String}}'. 272 273Note that when a module has been replaced, its Replace field 274describes the replacement module, and its Dir field is set to 275the replacement's source code, if present. (That is, if Replace 276is non-nil, then Dir is set to Replace.Dir, with no access to 277the replaced source code.) 278 279The -u flag adds information about available upgrades. 280When the latest version of a given module is newer than 281the current one, list -u sets the Module's Update field 282to information about the newer module. list -u will also set 283the module's Retracted field if the current version is retracted. 284The Module's String method indicates an available upgrade by 285formatting the newer version in brackets after the current version. 286If a version is retracted, the string "(retracted)" will follow it. 287For example, 'go list -m -u all' might print: 288 289 my/main/module 290 golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text 291 rsc.io/pdf v0.1.1 (retracted) [v0.1.2] 292 293(For tools, 'go list -m -u -json all' may be more convenient to parse.) 294 295The -versions flag causes list to set the Module's Versions field 296to a list of all known versions of that module, ordered according 297to semantic versioning, earliest to latest. The flag also changes 298the default output format to display the module path followed by the 299space-separated version list. 300 301The -retracted flag causes list to report information about retracted 302module versions. When -retracted is used with -f or -json, the Retracted 303field will be set to a string explaining why the version was retracted. 304The string is taken from comments on the retract directive in the 305module's go.mod file. When -retracted is used with -versions, retracted 306versions are listed together with unretracted versions. The -retracted 307flag may be used with or without -m. 308 309The arguments to list -m are interpreted as a list of modules, not packages. 310The main module is the module containing the current directory. 311The active modules are the main module and its dependencies. 312With no arguments, list -m shows the main module. 313With arguments, list -m shows the modules specified by the arguments. 314Any of the active modules can be specified by its module path. 315The special pattern "all" specifies all the active modules, first the main 316module and then dependencies sorted by module path. 317A pattern containing "..." specifies the active modules whose 318module paths match the pattern. 319A query of the form path@version specifies the result of that query, 320which is not limited to active modules. 321See 'go help modules' for more about module queries. 322 323The template function "module" takes a single string argument 324that must be a module path or query and returns the specified 325module as a Module struct. If an error occurs, the result will 326be a Module struct with a non-nil Error field. 327 328When using -m, the -reuse=old.json flag accepts the name of file containing 329the JSON output of a previous 'go list -m -json' invocation with the 330same set of modifier flags (such as -u, -retracted, and -versions). 331The go command may use this file to determine that a module is unchanged 332since the previous invocation and avoid redownloading information about it. 333Modules that are not redownloaded will be marked in the new output by 334setting the Reuse field to true. Normally the module cache provides this 335kind of reuse automatically; the -reuse flag can be useful on systems that 336do not preserve the module cache. 337 338For more about build flags, see 'go help build'. 339 340For more about specifying packages, see 'go help packages'. 341 342For more about modules, see https://golang.org/ref/mod. 343 `, 344} 345 346func init() { 347 CmdList.Run = runList // break init cycle 348 work.AddBuildFlags(CmdList, work.DefaultBuildFlags) 349 if cfg.Experiment != nil && cfg.Experiment.CoverageRedesign { 350 work.AddCoverFlags(CmdList, nil) 351 } 352 CmdList.Flag.Var(&listJsonFields, "json", "") 353} 354 355var ( 356 listCompiled = CmdList.Flag.Bool("compiled", false, "") 357 listDeps = CmdList.Flag.Bool("deps", false, "") 358 listE = CmdList.Flag.Bool("e", false, "") 359 listExport = CmdList.Flag.Bool("export", false, "") 360 listFmt = CmdList.Flag.String("f", "", "") 361 listFind = CmdList.Flag.Bool("find", false, "") 362 listJson bool 363 listJsonFields jsonFlag // If not empty, only output these fields. 364 listM = CmdList.Flag.Bool("m", false, "") 365 listRetracted = CmdList.Flag.Bool("retracted", false, "") 366 listReuse = CmdList.Flag.String("reuse", "", "") 367 listTest = CmdList.Flag.Bool("test", false, "") 368 listU = CmdList.Flag.Bool("u", false, "") 369 listVersions = CmdList.Flag.Bool("versions", false, "") 370) 371 372// A StringsFlag is a command-line flag that interprets its argument 373// as a space-separated list of possibly-quoted strings. 374type jsonFlag map[string]bool 375 376func (v *jsonFlag) Set(s string) error { 377 if v, err := strconv.ParseBool(s); err == nil { 378 listJson = v 379 return nil 380 } 381 listJson = true 382 if *v == nil { 383 *v = make(map[string]bool) 384 } 385 for _, f := range strings.Split(s, ",") { 386 (*v)[f] = true 387 } 388 return nil 389} 390 391func (v *jsonFlag) String() string { 392 var fields []string 393 for f := range *v { 394 fields = append(fields, f) 395 } 396 sort.Strings(fields) 397 return strings.Join(fields, ",") 398} 399 400func (v *jsonFlag) IsBoolFlag() bool { 401 return true 402} 403 404func (v *jsonFlag) needAll() bool { 405 return len(*v) == 0 406} 407 408func (v *jsonFlag) needAny(fields ...string) bool { 409 if v.needAll() { 410 return true 411 } 412 for _, f := range fields { 413 if (*v)[f] { 414 return true 415 } 416 } 417 return false 418} 419 420var nl = []byte{'\n'} 421 422func runList(ctx context.Context, cmd *base.Command, args []string) { 423 modload.InitWorkfile() 424 425 if *listFmt != "" && listJson { 426 base.Fatalf("go list -f cannot be used with -json") 427 } 428 if *listReuse != "" && !*listM { 429 base.Fatalf("go list -reuse cannot be used without -m") 430 } 431 if *listReuse != "" && modload.HasModRoot() { 432 base.Fatalf("go list -reuse cannot be used inside a module") 433 } 434 435 work.BuildInit() 436 out := newTrackingWriter(os.Stdout) 437 defer out.w.Flush() 438 439 if *listFmt == "" { 440 if *listM { 441 *listFmt = "{{.String}}" 442 if *listVersions { 443 *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}{{if .Deprecated}} (deprecated){{end}}` 444 } 445 } else { 446 *listFmt = "{{.ImportPath}}" 447 } 448 } 449 450 var do func(x any) 451 if listJson { 452 do = func(x any) { 453 if !listJsonFields.needAll() { 454 // Set x to a copy of itself with all non-requested fields cleared. 455 v := reflect.New(reflect.TypeOf(x).Elem()).Elem() // do is always called with a non-nil pointer. 456 v.Set(reflect.ValueOf(x).Elem()) 457 for i := 0; i < v.NumField(); i++ { 458 if !listJsonFields.needAny(v.Type().Field(i).Name) { 459 v.Field(i).SetZero() 460 } 461 } 462 x = v.Interface() 463 } 464 b, err := json.MarshalIndent(x, "", "\t") 465 if err != nil { 466 out.Flush() 467 base.Fatalf("%s", err) 468 } 469 out.Write(b) 470 out.Write(nl) 471 } 472 } else { 473 var cachedCtxt *Context 474 context := func() *Context { 475 if cachedCtxt == nil { 476 cachedCtxt = newContext(&cfg.BuildContext) 477 } 478 return cachedCtxt 479 } 480 fm := template.FuncMap{ 481 "join": strings.Join, 482 "context": context, 483 "module": func(path string) *modinfo.ModulePublic { return modload.ModuleInfo(ctx, path) }, 484 } 485 tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt) 486 if err != nil { 487 base.Fatalf("%s", err) 488 } 489 do = func(x any) { 490 if err := tmpl.Execute(out, x); err != nil { 491 out.Flush() 492 base.Fatalf("%s", err) 493 } 494 if out.NeedNL() { 495 out.Write(nl) 496 } 497 } 498 } 499 500 modload.Init() 501 if *listRetracted { 502 if cfg.BuildMod == "vendor" { 503 base.Fatalf("go list -retracted cannot be used when vendoring is enabled") 504 } 505 if !modload.Enabled() { 506 base.Fatalf("go list -retracted can only be used in module-aware mode") 507 } 508 } 509 510 if *listM { 511 // Module mode. 512 if *listCompiled { 513 base.Fatalf("go list -compiled cannot be used with -m") 514 } 515 if *listDeps { 516 // TODO(rsc): Could make this mean something with -m. 517 base.Fatalf("go list -deps cannot be used with -m") 518 } 519 if *listExport { 520 base.Fatalf("go list -export cannot be used with -m") 521 } 522 if *listFind { 523 base.Fatalf("go list -find cannot be used with -m") 524 } 525 if *listTest { 526 base.Fatalf("go list -test cannot be used with -m") 527 } 528 529 if modload.Init(); !modload.Enabled() { 530 base.Fatalf("go: list -m cannot be used with GO111MODULE=off") 531 } 532 533 modload.LoadModFile(ctx) // Sets cfg.BuildMod as a side-effect. 534 if cfg.BuildMod == "vendor" { 535 const actionDisabledFormat = "go: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)" 536 537 if *listVersions { 538 base.Fatalf(actionDisabledFormat, "determine available versions") 539 } 540 if *listU { 541 base.Fatalf(actionDisabledFormat, "determine available upgrades") 542 } 543 544 for _, arg := range args { 545 // In vendor mode, the module graph is incomplete: it contains only the 546 // explicit module dependencies and the modules that supply packages in 547 // the import graph. Reject queries that imply more information than that. 548 if arg == "all" { 549 base.Fatalf(actionDisabledFormat, "compute 'all'") 550 } 551 if strings.Contains(arg, "...") { 552 base.Fatalf(actionDisabledFormat, "match module patterns") 553 } 554 } 555 } 556 557 var mode modload.ListMode 558 if *listU { 559 mode |= modload.ListU | modload.ListRetracted | modload.ListDeprecated 560 } 561 if *listRetracted { 562 mode |= modload.ListRetracted 563 } 564 if *listVersions { 565 mode |= modload.ListVersions 566 if *listRetracted { 567 mode |= modload.ListRetractedVersions 568 } 569 } 570 if *listReuse != "" && len(args) == 0 { 571 base.Fatalf("go: list -m -reuse only has an effect with module@version arguments") 572 } 573 mods, err := modload.ListModules(ctx, args, mode, *listReuse) 574 if !*listE { 575 for _, m := range mods { 576 if m.Error != nil { 577 base.Error(errors.New(m.Error.Err)) 578 } 579 } 580 if err != nil { 581 base.Error(err) 582 } 583 base.ExitIfErrors() 584 } 585 for _, m := range mods { 586 do(m) 587 } 588 return 589 } 590 591 // Package mode (not -m). 592 if *listU { 593 base.Fatalf("go list -u can only be used with -m") 594 } 595 if *listVersions { 596 base.Fatalf("go list -versions can only be used with -m") 597 } 598 599 // These pairings make no sense. 600 if *listFind && *listDeps { 601 base.Fatalf("go list -deps cannot be used with -find") 602 } 603 if *listFind && *listTest { 604 base.Fatalf("go list -test cannot be used with -find") 605 } 606 if *listFind && *listExport { 607 base.Fatalf("go list -export cannot be used with -find") 608 } 609 610 pkgOpts := load.PackageOpts{ 611 IgnoreImports: *listFind, 612 ModResolveTests: *listTest, 613 AutoVCS: true, 614 SuppressBuildInfo: !*listExport && !listJsonFields.needAny("Stale", "StaleReason"), 615 SuppressEmbedFiles: !*listExport && !listJsonFields.needAny("EmbedFiles", "TestEmbedFiles", "XTestEmbedFiles"), 616 } 617 pkgs := load.PackagesAndErrors(ctx, pkgOpts, args) 618 if !*listE { 619 w := 0 620 for _, pkg := range pkgs { 621 if pkg.Error != nil { 622 base.Errorf("%v", pkg.Error) 623 continue 624 } 625 pkgs[w] = pkg 626 w++ 627 } 628 pkgs = pkgs[:w] 629 base.ExitIfErrors() 630 } 631 632 if *listTest { 633 c := cache.Default() 634 // Add test binaries to packages to be listed. 635 636 var wg sync.WaitGroup 637 sema := semaphore.NewWeighted(int64(runtime.GOMAXPROCS(0))) 638 type testPackageSet struct { 639 p, pmain, ptest, pxtest *load.Package 640 } 641 var testPackages []testPackageSet 642 for _, p := range pkgs { 643 if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 { 644 var pmain, ptest, pxtest *load.Package 645 var err error 646 if *listE { 647 sema.Acquire(ctx, 1) 648 wg.Add(1) 649 done := func() { 650 sema.Release(1) 651 wg.Done() 652 } 653 pmain, ptest, pxtest = load.TestPackagesAndErrors(ctx, done, pkgOpts, p, nil) 654 } else { 655 pmain, ptest, pxtest, err = load.TestPackagesFor(ctx, pkgOpts, p, nil) 656 if err != nil { 657 base.Fatalf("go: can't load test package: %s", err) 658 } 659 } 660 testPackages = append(testPackages, testPackageSet{p, pmain, ptest, pxtest}) 661 } 662 } 663 wg.Wait() 664 for _, pkgset := range testPackages { 665 p, pmain, ptest, pxtest := pkgset.p, pkgset.pmain, pkgset.ptest, pkgset.pxtest 666 if pmain != nil { 667 pkgs = append(pkgs, pmain) 668 data := *pmain.Internal.TestmainGo 669 sema.Acquire(ctx, 1) 670 wg.Add(1) 671 go func() { 672 h := cache.NewHash("testmain") 673 h.Write([]byte("testmain\n")) 674 h.Write(data) 675 out, _, err := c.Put(h.Sum(), bytes.NewReader(data)) 676 if err != nil { 677 base.Fatalf("%s", err) 678 } 679 pmain.GoFiles[0] = c.OutputFile(out) 680 sema.Release(1) 681 wg.Done() 682 }() 683 684 } 685 if ptest != nil && ptest != p { 686 pkgs = append(pkgs, ptest) 687 } 688 if pxtest != nil { 689 pkgs = append(pkgs, pxtest) 690 } 691 } 692 693 wg.Wait() 694 } 695 696 // Remember which packages are named on the command line. 697 cmdline := make(map[*load.Package]bool) 698 for _, p := range pkgs { 699 cmdline[p] = true 700 } 701 702 if *listDeps { 703 // Note: This changes the order of the listed packages 704 // from "as written on the command line" to 705 // "a depth-first post-order traversal". 706 // (The dependency exploration order for a given node 707 // is alphabetical, same as listed in .Deps.) 708 // Note that -deps is applied after -test, 709 // so that you only get descriptions of tests for the things named 710 // explicitly on the command line, not for all dependencies. 711 pkgs = loadPackageList(pkgs) 712 } 713 714 // Do we need to run a build to gather information? 715 needStale := (listJson && listJsonFields.needAny("Stale", "StaleReason")) || strings.Contains(*listFmt, ".Stale") 716 if needStale || *listExport || *listCompiled { 717 b := work.NewBuilder("") 718 if *listE { 719 b.AllowErrors = true 720 } 721 defer func() { 722 if err := b.Close(); err != nil { 723 base.Fatal(err) 724 } 725 }() 726 727 b.IsCmdList = true 728 b.NeedExport = *listExport 729 b.NeedCompiledGoFiles = *listCompiled 730 if cfg.Experiment.CoverageRedesign && cfg.BuildCover { 731 load.PrepareForCoverageBuild(pkgs) 732 } 733 a := &work.Action{} 734 // TODO: Use pkgsFilter? 735 for _, p := range pkgs { 736 if len(p.GoFiles)+len(p.CgoFiles) > 0 { 737 a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p)) 738 } 739 } 740 b.Do(ctx, a) 741 } 742 743 for _, p := range pkgs { 744 // Show vendor-expanded paths in listing 745 p.TestImports = p.Resolve(p.TestImports) 746 p.XTestImports = p.Resolve(p.XTestImports) 747 p.DepOnly = !cmdline[p] 748 749 if *listCompiled { 750 p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports) 751 } 752 } 753 754 if *listTest || (cfg.BuildPGO == "auto" && len(cmdline) > 1) { 755 all := pkgs 756 if !*listDeps { 757 all = loadPackageList(pkgs) 758 } 759 // Update import paths to distinguish the real package p 760 // from p recompiled for q.test, or to distinguish between 761 // p compiled with different PGO profiles. 762 // This must happen only once the build code is done 763 // looking at import paths, because it will get very confused 764 // if it sees these. 765 old := make(map[string]string) 766 for _, p := range all { 767 if p.ForTest != "" || p.Internal.ForMain != "" { 768 new := p.Desc() 769 old[new] = p.ImportPath 770 p.ImportPath = new 771 } 772 p.DepOnly = !cmdline[p] 773 } 774 // Update import path lists to use new strings. 775 m := make(map[string]string) 776 for _, p := range all { 777 for _, p1 := range p.Internal.Imports { 778 if p1.ForTest != "" || p1.Internal.ForMain != "" { 779 m[old[p1.ImportPath]] = p1.ImportPath 780 } 781 } 782 for i, old := range p.Imports { 783 if new := m[old]; new != "" { 784 p.Imports[i] = new 785 } 786 } 787 clear(m) 788 } 789 } 790 791 if listJsonFields.needAny("Deps", "DepsErrors") { 792 all := pkgs 793 // Make sure we iterate through packages in a postorder traversal, 794 // which load.PackageList guarantees. If *listDeps, then all is 795 // already in PackageList order. Otherwise, calling load.PackageList 796 // provides the guarantee. In the case of an import cycle, the last package 797 // visited in the cycle, importing the first encountered package in the cycle, 798 // is visited first. The cycle import error will be bubbled up in the traversal 799 // order up to the first package in the cycle, covering all the packages 800 // in the cycle. 801 if !*listDeps { 802 all = load.PackageList(pkgs) 803 } 804 if listJsonFields.needAny("Deps") { 805 for _, p := range all { 806 collectDeps(p) 807 } 808 } 809 if listJsonFields.needAny("DepsErrors") { 810 for _, p := range all { 811 collectDepsErrors(p) 812 } 813 } 814 } 815 816 // TODO(golang.org/issue/40676): This mechanism could be extended to support 817 // -u without -m. 818 if *listRetracted { 819 // Load retractions for modules that provide packages that will be printed. 820 // TODO(golang.org/issue/40775): Packages from the same module refer to 821 // distinct ModulePublic instance. It would be nice if they could all point 822 // to the same instance. This would require additional global state in 823 // modload.loaded, so that should be refactored first. For now, we update 824 // all instances. 825 modToArg := make(map[*modinfo.ModulePublic]string) 826 argToMods := make(map[string][]*modinfo.ModulePublic) 827 var args []string 828 addModule := func(mod *modinfo.ModulePublic) { 829 if mod.Version == "" { 830 return 831 } 832 arg := fmt.Sprintf("%s@%s", mod.Path, mod.Version) 833 if argToMods[arg] == nil { 834 args = append(args, arg) 835 } 836 argToMods[arg] = append(argToMods[arg], mod) 837 modToArg[mod] = arg 838 } 839 for _, p := range pkgs { 840 if p.Module == nil { 841 continue 842 } 843 addModule(p.Module) 844 if p.Module.Replace != nil { 845 addModule(p.Module.Replace) 846 } 847 } 848 849 if len(args) > 0 { 850 var mode modload.ListMode 851 if *listRetracted { 852 mode |= modload.ListRetracted 853 } 854 rmods, err := modload.ListModules(ctx, args, mode, *listReuse) 855 if err != nil && !*listE { 856 base.Error(err) 857 } 858 for i, arg := range args { 859 rmod := rmods[i] 860 for _, mod := range argToMods[arg] { 861 mod.Retracted = rmod.Retracted 862 if rmod.Error != nil && mod.Error == nil { 863 mod.Error = rmod.Error 864 } 865 } 866 } 867 } 868 } 869 870 // Record non-identity import mappings in p.ImportMap. 871 for _, p := range pkgs { 872 nRaw := len(p.Internal.RawImports) 873 for i, path := range p.Imports { 874 var srcPath string 875 if i < nRaw { 876 srcPath = p.Internal.RawImports[i] 877 } else { 878 // This path is not within the raw imports, so it must be an import 879 // found only within CompiledGoFiles. Those paths are found in 880 // CompiledImports. 881 srcPath = p.Internal.CompiledImports[i-nRaw] 882 } 883 884 if path != srcPath { 885 if p.ImportMap == nil { 886 p.ImportMap = make(map[string]string) 887 } 888 p.ImportMap[srcPath] = path 889 } 890 } 891 } 892 893 for _, p := range pkgs { 894 do(&p.PackagePublic) 895 } 896} 897 898// loadPackageList is like load.PackageList, but prints error messages and exits 899// with nonzero status if listE is not set and any package in the expanded list 900// has errors. 901func loadPackageList(roots []*load.Package) []*load.Package { 902 pkgs := load.PackageList(roots) 903 904 if !*listE { 905 for _, pkg := range pkgs { 906 if pkg.Error != nil { 907 base.Errorf("%v", pkg.Error) 908 } 909 } 910 } 911 912 return pkgs 913} 914 915// collectDeps populates p.Deps by iterating over p.Internal.Imports. 916// collectDeps must be called on all of p's Imports before being called on p. 917func collectDeps(p *load.Package) { 918 deps := make(map[string]bool) 919 920 for _, p := range p.Internal.Imports { 921 deps[p.ImportPath] = true 922 for _, q := range p.Deps { 923 deps[q] = true 924 } 925 } 926 927 p.Deps = make([]string, 0, len(deps)) 928 for dep := range deps { 929 p.Deps = append(p.Deps, dep) 930 } 931 sort.Strings(p.Deps) 932} 933 934// collectDeps populates p.DepsErrors by iterating over p.Internal.Imports. 935// collectDepsErrors must be called on all of p's Imports before being called on p. 936func collectDepsErrors(p *load.Package) { 937 depsErrors := make(map[*load.PackageError]bool) 938 939 for _, p := range p.Internal.Imports { 940 if p.Error != nil { 941 depsErrors[p.Error] = true 942 } 943 for _, q := range p.DepsErrors { 944 depsErrors[q] = true 945 } 946 } 947 948 p.DepsErrors = make([]*load.PackageError, 0, len(depsErrors)) 949 for deperr := range depsErrors { 950 p.DepsErrors = append(p.DepsErrors, deperr) 951 } 952 // Sort packages by the package on the top of the stack, which should be 953 // the package the error was produced for. Each package can have at most 954 // one error set on it. 955 sort.Slice(p.DepsErrors, func(i, j int) bool { 956 stki, stkj := p.DepsErrors[i].ImportStack, p.DepsErrors[j].ImportStack 957 // Some packages are missing import stacks. To ensure deterministic 958 // sort order compare two errors that are missing import stacks by 959 // their errors' error texts. 960 if len(stki) == 0 { 961 if len(stkj) != 0 { 962 return true 963 } 964 965 return p.DepsErrors[i].Err.Error() < p.DepsErrors[j].Err.Error() 966 } else if len(stkj) == 0 { 967 return false 968 } 969 pathi, pathj := stki[len(stki)-1], stkj[len(stkj)-1] 970 return pathi < pathj 971 }) 972} 973 974// TrackingWriter tracks the last byte written on every write so 975// we can avoid printing a newline if one was already written or 976// if there is no output at all. 977type TrackingWriter struct { 978 w *bufio.Writer 979 last byte 980} 981 982func newTrackingWriter(w io.Writer) *TrackingWriter { 983 return &TrackingWriter{ 984 w: bufio.NewWriter(w), 985 last: '\n', 986 } 987} 988 989func (t *TrackingWriter) Write(p []byte) (n int, err error) { 990 n, err = t.w.Write(p) 991 if n > 0 { 992 t.last = p[n-1] 993 } 994 return 995} 996 997func (t *TrackingWriter) Flush() { 998 t.w.Flush() 999} 1000 1001func (t *TrackingWriter) NeedNL() bool { 1002 return t.last != '\n' 1003} 1004