]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: add graphviz output to graph command
authorGiovanni Bajo <rasky@develer.com>
Fri, 3 Aug 2018 00:08:43 +0000 (02:08 +0200)
committerGiovanni Bajo <rasky@develer.com>
Mon, 20 Aug 2018 18:14:55 +0000 (18:14 +0000)
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: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/go/internal/modcmd/graph.go

index 5825c6d8ca8e0b5478e8db2337278dd1f0811a96..b123454d60988ec3f06b3fdc1a816006b3bb0bfe 100644 (file)
@@ -18,15 +18,25 @@ import (
 )
 
 var cmdGraph = &base.Command{
-       UsageLine: "go mod graph",
+       UsageLine: "go mod graph [-dot]",
        Short:     "print module requirement graph",
        Long: `
 Graph prints the module requirement graph (with replacements applied)
 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
 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) {
@@ -51,10 +61,21 @@ func runGraph(cmd *base.Command, args []string) {
        work.Add(modload.Target)
        work.Do(1, func(item interface{}) {
                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)
                for _, r := range list {
                        work.Add(r)
-                       out = append(out, format(m)+" "+format(r)+"\n")
+                       if *graphDot {
+                               out = append(out, "\""+m.Path+"\" -> \""+r.Path+"\"\n")
+                       } else {
+                               out = append(out, format(m)+" "+format(r)+"\n")
+                       }
                }
                if m == modload.Target {
                        deps = len(out)
@@ -66,8 +87,14 @@ func runGraph(cmd *base.Command, args []string) {
        })
 
        w := bufio.NewWriter(os.Stdout)
+       if *graphDot {
+               w.WriteString("digraph deps {\nrankdir=LR\n")
+       }
        for _, line := range out {
                w.WriteString(line)
        }
+       if *graphDot {
+               w.WriteString("}\n")
+       }
        w.Flush()
 }