Commit 90e860f1 authored by Russ Cox's avatar Russ Cox

cmd/go: add go list -deps

This gives an easy way to query properties of all the deps
of a set of packages, in a single go list invocation.
Go list has already done the hard work of loading these
packages, so exposing them is more efficient than
requiring a second invocation.

This will be helpful for tools asking cmd/go about build
information.

Change-Id: I90798e386246b24aad92dd13cb9e3788c7d30e91
Reviewed-on: https://go-review.googlesource.com/107776
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBryan C. Mills <bcmills@google.com>
parent 9c9ed9aa
...@@ -579,7 +579,7 @@ ...@@ -579,7 +579,7 @@
// //
// Usage: // Usage:
// //
// go list [-e] [-f format] [-json] [build flags] [packages] // go list [-deps] [-e] [-f format] [-json] [build flags] [packages]
// //
// List lists the packages named by the import paths, one per line. // List lists the packages named by the import paths, one per line.
// //
...@@ -683,6 +683,10 @@ ...@@ -683,6 +683,10 @@
// The -json flag causes the package data to be printed in JSON format // The -json flag causes the package data to be printed in JSON format
// instead of using the template format. // instead of using the template format.
// //
// The -deps flag causes list to iterate over not just the named packages
// but also all their dependencies. It visits them in a depth-first post-order
// traversal, so that a package is listed only after all its dependencies.
//
// The -e flag changes the handling of erroneous packages, those that // The -e flag changes the handling of erroneous packages, those that
// cannot be found or are malformed. By default, the list command // cannot be found or are malformed. By default, the list command
// prints an error to standard error for each erroneous package and // prints an error to standard error for each erroneous package and
...@@ -1688,14 +1692,13 @@ ...@@ -1688,14 +1692,13 @@
// Writes test binary as -c would. // Writes test binary as -c would.
// //
// -memprofile mem.out // -memprofile mem.out
// Write a memory profile to the file after all tests have passed. // Write an allocation profile to the file after all tests have passed.
// Writes test binary as -c would. // Writes test binary as -c would.
// //
// -memprofilerate n // -memprofilerate n
// Enable more precise (and expensive) memory profiles by setting // Enable more precise (and expensive) memory allocation profiles by
// runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'. // setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
// To profile all memory allocations, use -test.memprofilerate=1 // To profile all memory allocations, use -test.memprofilerate=1.
// and pass --alloc_space flag to the pprof tool.
// //
// -mutexprofile mutex.out // -mutexprofile mutex.out
// Write a mutex contention profile to the specified file // Write a mutex contention profile to the specified file
......
...@@ -1902,6 +1902,21 @@ func TestGoListDeps(t *testing.T) { ...@@ -1902,6 +1902,21 @@ func TestGoListDeps(t *testing.T) {
tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n") tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
tg.run("list", "-f", "{{.Deps}}", "p1") tg.run("list", "-f", "{{.Deps}}", "p1")
tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4") tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
tg.run("list", "-deps", "p1")
tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
// Check the list is in dependency order.
tg.run("list", "-deps", "math")
want := "internal/cpu\nunsafe\nmath\n"
out := tg.stdout.String()
if !strings.Contains(out, "internal/cpu") {
// Some systems don't use internal/cpu.
want = "unsafe\nmath\n"
}
if tg.stdout.String() != want {
t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
}
} }
// Issue 4096. Validate the output of unsuccessful go install foo/quxx. // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
......
...@@ -20,7 +20,7 @@ import ( ...@@ -20,7 +20,7 @@ import (
) )
var CmdList = &base.Command{ var CmdList = &base.Command{
UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]", UsageLine: "list [-deps] [-e] [-f format] [-json] [build flags] [packages]",
Short: "list packages", Short: "list packages",
Long: ` Long: `
List lists the packages named by the import paths, one per line. List lists the packages named by the import paths, one per line.
...@@ -125,6 +125,10 @@ for the go/build package's Context type. ...@@ -125,6 +125,10 @@ for the go/build package's Context type.
The -json flag causes the package data to be printed in JSON format The -json flag causes the package data to be printed in JSON format
instead of using the template format. instead of using the template format.
The -deps flag causes list to iterate over not just the named packages
but also all their dependencies. It visits them in a depth-first post-order
traversal, so that a package is listed only after all its dependencies.
The -e flag changes the handling of erroneous packages, those that The -e flag changes the handling of erroneous packages, those that
cannot be found or are malformed. By default, the list command cannot be found or are malformed. By default, the list command
prints an error to standard error for each erroneous package and prints an error to standard error for each erroneous package and
...@@ -146,6 +150,7 @@ func init() { ...@@ -146,6 +150,7 @@ func init() {
work.AddBuildFlags(CmdList) work.AddBuildFlags(CmdList)
} }
var listDeps = CmdList.Flag.Bool("deps", false, "")
var listE = CmdList.Flag.Bool("e", false, "") var listE = CmdList.Flag.Bool("e", false, "")
var listFmt = CmdList.Flag.String("f", "{{.ImportPath}}", "") var listFmt = CmdList.Flag.String("f", "{{.ImportPath}}", "")
var listJson = CmdList.Flag.Bool("json", false, "") var listJson = CmdList.Flag.Bool("json", false, "")
...@@ -201,6 +206,15 @@ func runList(cmd *base.Command, args []string) { ...@@ -201,6 +206,15 @@ func runList(cmd *base.Command, args []string) {
pkgs = load.Packages(args) pkgs = load.Packages(args)
} }
if *listDeps {
// Note: This changes the order of the listed packages
// from "as written on the command line" to
// "a depth-first post-order traversal".
// (The dependency exploration order for a given node
// is alphabetical, same as listed in .Deps.)
pkgs = load.PackageList(pkgs)
}
// Estimate whether staleness information is needed, // Estimate whether staleness information is needed,
// since it's a little bit of work to compute. // since it's a little bit of work to compute.
needStale := *listJson || strings.Contains(*listFmt, ".Stale") needStale := *listJson || strings.Contains(*listFmt, ".Stale")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment