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 "encoding/json" 12 "io" 13 "os" 14 "sort" 15 "strings" 16 "text/template" 17 18 "cmd/go/internal/base" 19 "cmd/go/internal/cache" 20 "cmd/go/internal/cfg" 21 "cmd/go/internal/load" 22 "cmd/go/internal/modload" 23 "cmd/go/internal/str" 24 "cmd/go/internal/work" 25) 26 27var CmdList = &base.Command{ 28 // Note: -f -json -m are listed explicitly because they are the most common list flags. 29 // Do not send CLs removing them because they're covered by [list flags]. 30 UsageLine: "go list [-f format] [-json] [-m] [list flags] [build flags] [packages]", 31 Short: "list packages or modules", 32 Long: ` 33List lists the named packages, one per line. 34The most commonly-used flags are -f and -json, which control the form 35of the output printed for each package. Other list flags, documented below, 36control more specific details. 37 38The default output shows the package import path: 39 40 bytes 41 encoding/json 42 github.com/gorilla/mux 43 golang.org/x/net/html 44 45The -f flag specifies an alternate format for the list, using the 46syntax of package template. The default output is equivalent 47to -f '{{.ImportPath}}'. The struct being passed to the template is: 48 49 type Package struct { 50 Dir string // directory containing package sources 51 ImportPath string // import path of package in dir 52 ImportComment string // path in import comment on package statement 53 Name string // package name 54 Doc string // package documentation string 55 Target string // install path 56 Shlib string // the shared library that contains this package (only set when -linkshared) 57 Goroot bool // is this package in the Go root? 58 Standard bool // is this package part of the standard Go library? 59 Stale bool // would 'go install' do anything for this package? 60 StaleReason string // explanation for Stale==true 61 Root string // Go root or Go path dir containing this package 62 ConflictDir string // this directory shadows Dir in $GOPATH 63 BinaryOnly bool // binary-only package (no longer supported) 64 ForTest string // package is only for use in named test 65 Export string // file containing export data (when using -export) 66 Module *Module // info about package's containing module, if any (can be nil) 67 Match []string // command-line patterns matching this package 68 DepOnly bool // package is only a dependency, not explicitly listed 69 70 // Source files 71 GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) 72 CgoFiles []string // .go source files that import "C" 73 CompiledGoFiles []string // .go files presented to compiler (when using -compiled) 74 IgnoredGoFiles []string // .go source files ignored due to build constraints 75 CFiles []string // .c source files 76 CXXFiles []string // .cc, .cxx and .cpp source files 77 MFiles []string // .m source files 78 HFiles []string // .h, .hh, .hpp and .hxx source files 79 FFiles []string // .f, .F, .for and .f90 Fortran source files 80 SFiles []string // .s source files 81 SwigFiles []string // .swig files 82 SwigCXXFiles []string // .swigcxx files 83 SysoFiles []string // .syso object files to add to archive 84 TestGoFiles []string // _test.go files in package 85 XTestGoFiles []string // _test.go files outside package 86 87 // Cgo directives 88 CgoCFLAGS []string // cgo: flags for C compiler 89 CgoCPPFLAGS []string // cgo: flags for C preprocessor 90 CgoCXXFLAGS []string // cgo: flags for C++ compiler 91 CgoFFLAGS []string // cgo: flags for Fortran compiler 92 CgoLDFLAGS []string // cgo: flags for linker 93 CgoPkgConfig []string // cgo: pkg-config names 94 95 // Dependency information 96 Imports []string // import paths used by this package 97 ImportMap map[string]string // map from source import to ImportPath (identity entries omitted) 98 Deps []string // all (recursively) imported dependencies 99 TestImports []string // imports from TestGoFiles 100 XTestImports []string // imports from XTestGoFiles 101 102 // Error information 103 Incomplete bool // this package or a dependency has an error 104 Error *PackageError // error loading package 105 DepsErrors []*PackageError // errors loading dependencies 106 } 107 108Packages stored in vendor directories report an ImportPath that includes the 109path to the vendor directory (for example, "d/vendor/p" instead of "p"), 110so that the ImportPath uniquely identifies a given copy of a package. 111The Imports, Deps, TestImports, and XTestImports lists also contain these 112expanded import paths. See golang.org/s/go15vendor for more about vendoring. 113 114The error information, if any, is 115 116 type PackageError struct { 117 ImportStack []string // shortest path from package named on command line to this one 118 Pos string // position of error (if present, file:line:col) 119 Err string // the error itself 120 } 121 122The module information is a Module struct, defined in the discussion 123of list -m below. 124 125The template function "join" calls strings.Join. 126 127The template function "context" returns the build context, defined as: 128 129 type Context struct { 130 GOARCH string // target architecture 131 GOOS string // target operating system 132 GOROOT string // Go root 133 GOPATH string // Go path 134 CgoEnabled bool // whether cgo can be used 135 UseAllFiles bool // use files regardless of +build lines, file names 136 Compiler string // compiler to assume when computing target paths 137 BuildTags []string // build constraints to match in +build lines 138 ReleaseTags []string // releases the current release is compatible with 139 InstallSuffix string // suffix to use in the name of the install dir 140 } 141 142For more information about the meaning of these fields see the documentation 143for the go/build package's Context type. 144 145The -json flag causes the package data to be printed in JSON format 146instead of using the template format. 147 148The -compiled flag causes list to set CompiledGoFiles to the Go source 149files presented to the compiler. Typically this means that it repeats 150the files listed in GoFiles and then also adds the Go code generated 151by processing CgoFiles and SwigFiles. The Imports list contains the 152union of all imports from both GoFiles and CompiledGoFiles. 153 154The -deps flag causes list to iterate over not just the named packages 155but also all their dependencies. It visits them in a depth-first post-order 156traversal, so that a package is listed only after all its dependencies. 157Packages not explicitly listed on the command line will have the DepOnly 158field set to true. 159 160The -e flag changes the handling of erroneous packages, those that 161cannot be found or are malformed. By default, the list command 162prints an error to standard error for each erroneous package and 163omits the packages from consideration during the usual printing. 164With the -e flag, the list command never prints errors to standard 165error and instead processes the erroneous packages with the usual 166printing. Erroneous packages will have a non-empty ImportPath and 167a non-nil Error field; other information may or may not be missing 168(zeroed). 169 170The -export flag causes list to set the Export field to the name of a 171file containing up-to-date export information for the given package. 172 173The -find flag causes list to identify the named packages but not 174resolve their dependencies: the Imports and Deps lists will be empty. 175 176The -test flag causes list to report not only the named packages 177but also their test binaries (for packages with tests), to convey to 178source code analysis tools exactly how test binaries are constructed. 179The reported import path for a test binary is the import path of 180the package followed by a ".test" suffix, as in "math/rand.test". 181When building a test, it is sometimes necessary to rebuild certain 182dependencies specially for that test (most commonly the tested 183package itself). The reported import path of a package recompiled 184for a particular test binary is followed by a space and the name of 185the test binary in brackets, as in "math/rand [math/rand.test]" 186or "regexp [sort.test]". The ForTest field is also set to the name 187of the package being tested ("math/rand" or "sort" in the previous 188examples). 189 190The Dir, Target, Shlib, Root, ConflictDir, and Export file paths 191are all absolute paths. 192 193By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir 194(that is, paths relative to Dir, not absolute paths). 195The generated files added when using the -compiled and -test flags 196are absolute paths referring to cached copies of generated Go source files. 197Although they are Go source files, the paths may not end in ".go". 198 199The -m flag causes list to list modules instead of packages. 200 201When listing modules, the -f flag still specifies a format template 202applied to a Go struct, but now a Module struct: 203 204 type Module struct { 205 Path string // module path 206 Version string // module version 207 Versions []string // available module versions (with -versions) 208 Replace *Module // replaced by this module 209 Time *time.Time // time version was created 210 Update *Module // available update, if any (with -u) 211 Main bool // is this the main module? 212 Indirect bool // is this module only an indirect dependency of main module? 213 Dir string // directory holding files for this module, if any 214 GoMod string // path to go.mod file used when loading this module, if any 215 GoVersion string // go version used in module 216 Error *ModuleError // error loading module 217 } 218 219 type ModuleError struct { 220 Err string // the error itself 221 } 222 223The file GoMod refers to may be outside the module directory if the 224module is in the module cache or if the -modfile flag is used. 225 226The default output is to print the module path and then 227information about the version and replacement if any. 228For example, 'go list -m all' might print: 229 230 my/main/module 231 golang.org/x/text v0.3.0 => /tmp/text 232 rsc.io/pdf v0.1.1 233 234The Module struct has a String method that formats this 235line of output, so that the default format is equivalent 236to -f '{{.String}}'. 237 238Note that when a module has been replaced, its Replace field 239describes the replacement module, and its Dir field is set to 240the replacement's source code, if present. (That is, if Replace 241is non-nil, then Dir is set to Replace.Dir, with no access to 242the replaced source code.) 243 244The -u flag adds information about available upgrades. 245When the latest version of a given module is newer than 246the current one, list -u sets the Module's Update field 247to information about the newer module. 248The Module's String method indicates an available upgrade by 249formatting the newer version in brackets after the current version. 250For example, 'go list -m -u all' might print: 251 252 my/main/module 253 golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text 254 rsc.io/pdf v0.1.1 [v0.1.2] 255 256(For tools, 'go list -m -u -json all' may be more convenient to parse.) 257 258The -versions flag causes list to set the Module's Versions field 259to a list of all known versions of that module, ordered according 260to semantic versioning, earliest to latest. The flag also changes 261the default output format to display the module path followed by the 262space-separated version list. 263 264The arguments to list -m are interpreted as a list of modules, not packages. 265The main module is the module containing the current directory. 266The active modules are the main module and its dependencies. 267With no arguments, list -m shows the main module. 268With arguments, list -m shows the modules specified by the arguments. 269Any of the active modules can be specified by its module path. 270The special pattern "all" specifies all the active modules, first the main 271module and then dependencies sorted by module path. 272A pattern containing "..." specifies the active modules whose 273module paths match the pattern. 274A query of the form path@version specifies the result of that query, 275which is not limited to active modules. 276See 'go help modules' for more about module queries. 277 278The template function "module" takes a single string argument 279that must be a module path or query and returns the specified 280module as a Module struct. If an error occurs, the result will 281be a Module struct with a non-nil Error field. 282 283For more about build flags, see 'go help build'. 284 285For more about specifying packages, see 'go help packages'. 286 287For more about modules, see 'go help modules'. 288 `, 289} 290 291func init() { 292 CmdList.Run = runList // break init cycle 293 work.AddBuildFlags(CmdList, work.DefaultBuildFlags) 294} 295 296var ( 297 listCompiled = CmdList.Flag.Bool("compiled", false, "") 298 listDeps = CmdList.Flag.Bool("deps", false, "") 299 listE = CmdList.Flag.Bool("e", false, "") 300 listExport = CmdList.Flag.Bool("export", false, "") 301 listFmt = CmdList.Flag.String("f", "", "") 302 listFind = CmdList.Flag.Bool("find", false, "") 303 listJson = CmdList.Flag.Bool("json", false, "") 304 listM = CmdList.Flag.Bool("m", false, "") 305 listU = CmdList.Flag.Bool("u", false, "") 306 listTest = CmdList.Flag.Bool("test", false, "") 307 listVersions = CmdList.Flag.Bool("versions", false, "") 308) 309 310var nl = []byte{'\n'} 311 312func runList(cmd *base.Command, args []string) { 313 modload.LoadTests = *listTest 314 work.BuildInit() 315 out := newTrackingWriter(os.Stdout) 316 defer out.w.Flush() 317 318 if *listFmt == "" { 319 if *listM { 320 *listFmt = "{{.String}}" 321 if *listVersions { 322 *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}` 323 } 324 } else { 325 *listFmt = "{{.ImportPath}}" 326 } 327 } 328 329 var do func(interface{}) 330 if *listJson { 331 do = func(x interface{}) { 332 b, err := json.MarshalIndent(x, "", "\t") 333 if err != nil { 334 out.Flush() 335 base.Fatalf("%s", err) 336 } 337 out.Write(b) 338 out.Write(nl) 339 } 340 } else { 341 var cachedCtxt *Context 342 context := func() *Context { 343 if cachedCtxt == nil { 344 cachedCtxt = newContext(&cfg.BuildContext) 345 } 346 return cachedCtxt 347 } 348 fm := template.FuncMap{ 349 "join": strings.Join, 350 "context": context, 351 "module": modload.ModuleInfo, 352 } 353 tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt) 354 if err != nil { 355 base.Fatalf("%s", err) 356 } 357 do = func(x interface{}) { 358 if err := tmpl.Execute(out, x); err != nil { 359 out.Flush() 360 base.Fatalf("%s", err) 361 } 362 if out.NeedNL() { 363 out.Write(nl) 364 } 365 } 366 } 367 368 if *listM { 369 // Module mode. 370 if *listCompiled { 371 base.Fatalf("go list -compiled cannot be used with -m") 372 } 373 if *listDeps { 374 // TODO(rsc): Could make this mean something with -m. 375 base.Fatalf("go list -deps cannot be used with -m") 376 } 377 if *listExport { 378 base.Fatalf("go list -export cannot be used with -m") 379 } 380 if *listFind { 381 base.Fatalf("go list -find cannot be used with -m") 382 } 383 if *listTest { 384 base.Fatalf("go list -test cannot be used with -m") 385 } 386 387 if modload.Init(); !modload.Enabled() { 388 base.Fatalf("go list -m: not using modules") 389 } 390 391 modload.InitMod() // Parses go.mod and sets cfg.BuildMod. 392 if cfg.BuildMod == "vendor" { 393 const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)" 394 395 if *listVersions { 396 base.Fatalf(actionDisabledFormat, "determine available versions") 397 } 398 if *listU { 399 base.Fatalf(actionDisabledFormat, "determine available upgrades") 400 } 401 402 for _, arg := range args { 403 // In vendor mode, the module graph is incomplete: it contains only the 404 // explicit module dependencies and the modules that supply packages in 405 // the import graph. Reject queries that imply more information than that. 406 if arg == "all" { 407 base.Fatalf(actionDisabledFormat, "compute 'all'") 408 } 409 if strings.Contains(arg, "...") { 410 base.Fatalf(actionDisabledFormat, "match module patterns") 411 } 412 } 413 } 414 415 modload.LoadBuildList() 416 417 mods := modload.ListModules(args, *listU, *listVersions) 418 if !*listE { 419 for _, m := range mods { 420 if m.Error != nil { 421 base.Errorf("go list -m: %v", m.Error.Err) 422 } 423 } 424 base.ExitIfErrors() 425 } 426 for _, m := range mods { 427 do(m) 428 } 429 return 430 } 431 432 // Package mode (not -m). 433 if *listU { 434 base.Fatalf("go list -u can only be used with -m") 435 } 436 if *listVersions { 437 base.Fatalf("go list -versions can only be used with -m") 438 } 439 440 // These pairings make no sense. 441 if *listFind && *listDeps { 442 base.Fatalf("go list -deps cannot be used with -find") 443 } 444 if *listFind && *listTest { 445 base.Fatalf("go list -test cannot be used with -find") 446 } 447 448 load.IgnoreImports = *listFind 449 var pkgs []*load.Package 450 if *listE { 451 pkgs = load.PackagesAndErrors(args) 452 } else { 453 pkgs = load.Packages(args) 454 } 455 456 if cache.Default() == nil { 457 // These flags return file names pointing into the build cache, 458 // so the build cache must exist. 459 if *listCompiled { 460 base.Fatalf("go list -compiled requires build cache") 461 } 462 if *listExport { 463 base.Fatalf("go list -export requires build cache") 464 } 465 if *listTest { 466 base.Fatalf("go list -test requires build cache") 467 } 468 } 469 470 if *listTest { 471 c := cache.Default() 472 // Add test binaries to packages to be listed. 473 for _, p := range pkgs { 474 if p.Error != nil { 475 continue 476 } 477 if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 { 478 var pmain, ptest, pxtest *load.Package 479 var err error 480 if *listE { 481 pmain, ptest, pxtest = load.TestPackagesAndErrors(p, nil) 482 } else { 483 pmain, ptest, pxtest, err = load.TestPackagesFor(p, nil) 484 if err != nil { 485 base.Errorf("can't load test package: %s", err) 486 } 487 } 488 if pmain != nil { 489 pkgs = append(pkgs, pmain) 490 data := *pmain.Internal.TestmainGo 491 h := cache.NewHash("testmain") 492 h.Write([]byte("testmain\n")) 493 h.Write(data) 494 out, _, err := c.Put(h.Sum(), bytes.NewReader(data)) 495 if err != nil { 496 base.Fatalf("%s", err) 497 } 498 pmain.GoFiles[0] = c.OutputFile(out) 499 } 500 if ptest != nil && ptest != p { 501 pkgs = append(pkgs, ptest) 502 } 503 if pxtest != nil { 504 pkgs = append(pkgs, pxtest) 505 } 506 } 507 } 508 } 509 510 // Remember which packages are named on the command line. 511 cmdline := make(map[*load.Package]bool) 512 for _, p := range pkgs { 513 cmdline[p] = true 514 } 515 516 if *listDeps { 517 // Note: This changes the order of the listed packages 518 // from "as written on the command line" to 519 // "a depth-first post-order traversal". 520 // (The dependency exploration order for a given node 521 // is alphabetical, same as listed in .Deps.) 522 // Note that -deps is applied after -test, 523 // so that you only get descriptions of tests for the things named 524 // explicitly on the command line, not for all dependencies. 525 pkgs = load.PackageList(pkgs) 526 } 527 528 // Do we need to run a build to gather information? 529 needStale := *listJson || strings.Contains(*listFmt, ".Stale") 530 if needStale || *listExport || *listCompiled { 531 var b work.Builder 532 b.Init() 533 b.IsCmdList = true 534 b.NeedExport = *listExport 535 b.NeedCompiledGoFiles = *listCompiled 536 a := &work.Action{} 537 // TODO: Use pkgsFilter? 538 for _, p := range pkgs { 539 if len(p.GoFiles)+len(p.CgoFiles) > 0 { 540 a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p)) 541 } 542 } 543 b.Do(a) 544 } 545 546 for _, p := range pkgs { 547 // Show vendor-expanded paths in listing 548 p.TestImports = p.Resolve(p.TestImports) 549 p.XTestImports = p.Resolve(p.XTestImports) 550 p.DepOnly = !cmdline[p] 551 552 if *listCompiled { 553 p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports) 554 } 555 } 556 557 if *listTest { 558 all := pkgs 559 if !*listDeps { 560 all = load.PackageList(pkgs) 561 } 562 // Update import paths to distinguish the real package p 563 // from p recompiled for q.test. 564 // This must happen only once the build code is done 565 // looking at import paths, because it will get very confused 566 // if it sees these. 567 old := make(map[string]string) 568 for _, p := range all { 569 if p.ForTest != "" { 570 new := p.ImportPath + " [" + p.ForTest + ".test]" 571 old[new] = p.ImportPath 572 p.ImportPath = new 573 } 574 p.DepOnly = !cmdline[p] 575 } 576 // Update import path lists to use new strings. 577 m := make(map[string]string) 578 for _, p := range all { 579 for _, p1 := range p.Internal.Imports { 580 if p1.ForTest != "" { 581 m[old[p1.ImportPath]] = p1.ImportPath 582 } 583 } 584 for i, old := range p.Imports { 585 if new := m[old]; new != "" { 586 p.Imports[i] = new 587 } 588 } 589 for old := range m { 590 delete(m, old) 591 } 592 } 593 // Recompute deps lists using new strings, from the leaves up. 594 for _, p := range all { 595 deps := make(map[string]bool) 596 for _, p1 := range p.Internal.Imports { 597 deps[p1.ImportPath] = true 598 for _, d := range p1.Deps { 599 deps[d] = true 600 } 601 } 602 p.Deps = make([]string, 0, len(deps)) 603 for d := range deps { 604 p.Deps = append(p.Deps, d) 605 } 606 sort.Strings(p.Deps) 607 } 608 } 609 610 // Record non-identity import mappings in p.ImportMap. 611 for _, p := range pkgs { 612 for i, srcPath := range p.Internal.RawImports { 613 path := p.Imports[i] 614 if path != srcPath { 615 if p.ImportMap == nil { 616 p.ImportMap = make(map[string]string) 617 } 618 p.ImportMap[srcPath] = path 619 } 620 } 621 } 622 623 for _, p := range pkgs { 624 do(&p.PackagePublic) 625 } 626} 627 628// TrackingWriter tracks the last byte written on every write so 629// we can avoid printing a newline if one was already written or 630// if there is no output at all. 631type TrackingWriter struct { 632 w *bufio.Writer 633 last byte 634} 635 636func newTrackingWriter(w io.Writer) *TrackingWriter { 637 return &TrackingWriter{ 638 w: bufio.NewWriter(w), 639 last: '\n', 640 } 641} 642 643func (t *TrackingWriter) Write(p []byte) (n int, err error) { 644 n, err = t.w.Write(p) 645 if n > 0 { 646 t.last = p[n-1] 647 } 648 return 649} 650 651func (t *TrackingWriter) Flush() { 652 t.w.Flush() 653} 654 655func (t *TrackingWriter) NeedNL() bool { 656 return t.last != '\n' 657} 658