Commit 723479bc authored by Giovanni Bajo's avatar Giovanni Bajo

cmd/go: add graphviz output to graph command

This allows to quickly visual inspect dependencies.

Change-Id: Ice326ec69d7d57720f608b04cdf3ece153b8c5f1
Reviewed-on: https://go-review.googlesource.com/127599
Run-TryBot: Giovanni Bajo <rasky@develer.com>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 18034e6b
...@@ -18,15 +18,25 @@ import ( ...@@ -18,15 +18,25 @@ import (
) )
var cmdGraph = &base.Command{ var cmdGraph = &base.Command{
UsageLine: "go mod graph", UsageLine: "go mod graph [-dot]",
Short: "print module requirement graph", Short: "print module requirement graph",
Long: ` Long: `
Graph prints the module requirement graph (with replacements applied) Graph prints the module requirement graph (with replacements applied)
in text form. Each line in the output has two space-separated fields: a module in text form. Each line in the output has two space-separated fields: a module
and one of its requirements. Each module is identified as a string of the form and one of its requirements. Each module is identified as a string of the form
path@version, except for the main module, which has no @version suffix. path@version, except for the main module, which has no @version suffix.
The -dot flag generates the output in graphviz format that can be used
with a tool like dot to visually render the dependency graph.
`, `,
Run: runGraph, }
var (
graphDot = cmdGraph.Flag.Bool("dot", false, "")
)
func init() {
cmdGraph.Run = runGraph // break init cycle
} }
func runGraph(cmd *base.Command, args []string) { func runGraph(cmd *base.Command, args []string) {
...@@ -51,11 +61,22 @@ func runGraph(cmd *base.Command, args []string) { ...@@ -51,11 +61,22 @@ func runGraph(cmd *base.Command, args []string) {
work.Add(modload.Target) work.Add(modload.Target)
work.Do(1, func(item interface{}) { work.Do(1, func(item interface{}) {
m := item.(module.Version) m := item.(module.Version)
if *graphDot {
if m.Version == "" {
out = append(out, "\""+m.Path+"\" [label=<"+m.Path+">]\n")
} else {
out = append(out, "\""+m.Path+"\" [label=<"+m.Path+"<br/><font point-size=\"9\">"+m.Version+"</font>>]\n")
}
}
list, _ := reqs.Required(m) list, _ := reqs.Required(m)
for _, r := range list { for _, r := range list {
work.Add(r) work.Add(r)
if *graphDot {
out = append(out, "\""+m.Path+"\" -> \""+r.Path+"\"\n")
} else {
out = append(out, format(m)+" "+format(r)+"\n") out = append(out, format(m)+" "+format(r)+"\n")
} }
}
if m == modload.Target { if m == modload.Target {
deps = len(out) deps = len(out)
} }
...@@ -66,8 +87,14 @@ func runGraph(cmd *base.Command, args []string) { ...@@ -66,8 +87,14 @@ func runGraph(cmd *base.Command, args []string) {
}) })
w := bufio.NewWriter(os.Stdout) w := bufio.NewWriter(os.Stdout)
if *graphDot {
w.WriteString("digraph deps {\nrankdir=LR\n")
}
for _, line := range out { for _, line := range out {
w.WriteString(line) w.WriteString(line)
} }
if *graphDot {
w.WriteString("}\n")
}
w.Flush() w.Flush()
} }
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