blob: bf2f521f31e2e75c883867982d719edff0b901aa [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Modgraphviz converts “go mod graph” output into Graphviz's DOT language,
// for use with Graphviz visualization and analysis tools like dot, dotty, and sccmap.
//
// Usage:
//
// go mod graph | modgraphviz > graph.dot
// go mod graph | modgraphviz | dot -Tpng -o graph.png
//
// Modgraphviz takes no options or arguments; it reads a graph in the format
// generated by “go mod graph” on standard input and writes DOT language
// on standard output.
//
// See http://www.graphviz.org/doc/info/lang.html for details of the DOT language
// and http://www.graphviz.org/about/ for Graphviz itself.
//
// See also golang.org/x/tools/cmd/digraph for general queries and analysis
// of “go mod graph” output.
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"io"
"log"
"os"
"strings"
)
func usage() {
fmt.Fprintf(os.Stderr, "Usage: go mod graph | modgraphviz | dot -Tpng -o graph.png\n")
os.Exit(2)
}
func main() {
log.SetFlags(0)
log.SetPrefix("modgraphviz: ")
flag.Usage = usage
flag.Parse()
if flag.NArg() != 0 {
usage()
}
graph, err := convert(os.Stdin)
if err != nil {
log.Fatal(err)
}
if _, err := os.Stdout.Write(graph); err != nil {
log.Fatal(err)
}
}
// convert reads “go mod graph” output from r
// and returns the equivalent DOT digraph.
func convert(r io.Reader) ([]byte, error) {
var buf bytes.Buffer
fmt.Fprintf(&buf, "digraph gomodgraph {\n")
scanner := bufio.NewScanner(r)
for scanner.Scan() {
parts := strings.Fields(scanner.Text())
if len(parts) != 2 {
continue
}
fmt.Fprintf(&buf, "\t%q -> %q\n", parts[0], parts[1])
}
if err := scanner.Err(); err != nil {
return nil, err
}
fmt.Fprintf(&buf, "}\n")
return buf.Bytes(), nil
}