terraform/depgraph2/graph.go

71 lines
1.4 KiB
Go
Raw Normal View History

package depgraph
import (
"bytes"
"fmt"
"sort"
)
// Graph is used to represent a dependency graph.
type Graph struct {
Nodes []Node
}
// Node is an element of the graph that has other dependencies.
type Node interface {
Deps() []Node
}
// NamedNode is an optional interface implementation of a Node that
// can have a name. If this is implemented, this will be used for various
// output.
type NamedNode interface {
Node
Name() string
}
func (g *Graph) String() string {
var buf bytes.Buffer
// Build the list of node names and a mapping so that we can more
// easily alphabetize the output to remain deterministic.
names := make([]string, 0, len(g.Nodes))
mapping := make(map[string]Node, len(g.Nodes))
for _, n := range g.Nodes {
name := nodeName(n)
names = append(names, name)
mapping[name] = n
}
sort.Strings(names)
// Write each node in order...
for _, name := range names {
n := mapping[name]
buf.WriteString(fmt.Sprintf("%s\n", name))
// Alphabetize dependencies
depsRaw := n.Deps()
deps := make([]string, 0, len(depsRaw))
for _, d := range depsRaw {
deps = append(deps, nodeName(d))
}
sort.Strings(deps)
// Write dependencies
for _, d := range deps {
buf.WriteString(fmt.Sprintf(" %s\n", d))
}
}
return buf.String()
}
func nodeName(n Node) string {
switch v := n.(type) {
case NamedNode:
return v.Name()
default:
return fmt.Sprintf("%s", v)
}
}