Austin Clements would like Alan Donovan to review this change.
cmd/digraph: rename graph -> digraph
So we can import the graph package without an annoying name conflict.
diff --git a/cmd/digraph/digraph.go b/cmd/digraph/digraph.go
index f3811fe..3f9c767 100644
--- a/cmd/digraph/digraph.go
+++ b/cmd/digraph/digraph.go
@@ -47,7 +47,7 @@
usage()
}
- if err := digraph(args[0], args[1:]); err != nil {
+ if err := doDigraph(args[0], args[1:]); err != nil {
fmt.Fprintf(os.Stderr, "digraph: %s\n", err)
os.Exit(1)
}
@@ -86,10 +86,10 @@
}
}
-// A graph maps nodes to the non-nil set of their immediate successors.
-type graph map[string]nodeset
+// A digraph maps nodes to the non-nil set of their immediate successors.
+type digraph map[string]nodeset
-func (g graph) addNode(node string) nodeset {
+func (g digraph) addNode(node string) nodeset {
edges := g[node]
if edges == nil {
edges = make(nodeset)
@@ -98,7 +98,7 @@
return edges
}
-func (g graph) addEdges(from string, to ...string) {
+func (g digraph) addEdges(from string, to ...string) {
edges := g.addNode(from)
for _, to := range to {
g.addNode(to)
@@ -106,7 +106,7 @@
}
}
-func (g graph) nodelist() nodelist {
+func (g digraph) nodelist() nodelist {
nodes := make(nodeset)
for node := range g {
nodes[node] = true
@@ -114,7 +114,7 @@
return nodes.sort()
}
-func (g graph) reachableFrom(roots nodeset) nodeset {
+func (g digraph) reachableFrom(roots nodeset) nodeset {
seen := make(nodeset)
var visit func(node string)
visit = func(node string) {
@@ -131,8 +131,8 @@
return seen
}
-func (g graph) transpose() graph {
- rev := make(graph)
+func (g digraph) transpose() digraph {
+ rev := make(digraph)
for node, edges := range g {
rev.addNode(node)
for succ := range edges {
@@ -142,7 +142,7 @@
return rev
}
-func (g graph) sccs() []nodeset {
+func (g digraph) sccs() []nodeset {
// Kosaraju's algorithm---Tarjan is overkill here.
// Forward pass.
@@ -192,7 +192,7 @@
return sccs
}
-func (g graph) allpaths(from, to string) error {
+func (g digraph) allpaths(from, to string) error {
// We intersect the forward closure of 'from' with
// the reverse closure of 'to'. This is not the most
// efficient implementation, but it's the clearest,
@@ -224,7 +224,7 @@
return nil
}
-func (g graph) somepath(from, to string) error {
+func (g digraph) somepath(from, to string) error {
// Search breadth-first so that we return a minimal path.
// A path is a linked list whose head is a candidate "to" node
@@ -265,7 +265,7 @@
return fmt.Errorf("no path from %q to %q", from, to)
}
-func (g graph) toDot(w *bytes.Buffer) {
+func (g digraph) toDot(w *bytes.Buffer) {
fmt.Fprintln(w, "digraph {")
for _, src := range g.nodelist() {
for _, dst := range g[src].sort() {
@@ -279,8 +279,8 @@
fmt.Fprintln(w, "}")
}
-func parse(rd io.Reader) (graph, error) {
- g := make(graph)
+func parse(rd io.Reader) (digraph, error) {
+ g := make(digraph)
var linenum int
// We avoid bufio.Scanner as it imposes a (configurable) limit
@@ -314,7 +314,7 @@
var stdin io.Reader = os.Stdin
var stdout io.Writer = os.Stdout
-func digraph(cmd string, args []string) error {
+func doDigraph(cmd string, args []string) error {
// Parse the input graph.
g, err := parse(stdin)
if err != nil {
diff --git a/cmd/digraph/digraph_test.go b/cmd/digraph/digraph_test.go
index d244615..74e61ee 100644
--- a/cmd/digraph/digraph_test.go
+++ b/cmd/digraph/digraph_test.go
@@ -53,7 +53,7 @@
t.Run(test.name, func(t *testing.T) {
stdin = strings.NewReader(test.input)
stdout = new(bytes.Buffer)
- if err := digraph(test.cmd, test.args); err != nil {
+ if err := doDigraph(test.cmd, test.args); err != nil {
t.Fatal(err)
}
@@ -187,7 +187,7 @@
t.Run(test.name, func(t *testing.T) {
stdin = strings.NewReader(test.in)
stdout = new(bytes.Buffer)
- if err := digraph("allpaths", []string{"A", test.to}); err != nil {
+ if err := doDigraph("allpaths", []string{"A", test.to}); err != nil {
t.Fatal(err)
}
@@ -242,7 +242,7 @@
t.Run(test.name, func(t *testing.T) {
stdin = strings.NewReader(test.in)
stdout = new(bytes.Buffer)
- if err := digraph("somepath", []string{"A", test.to}); err != nil {
+ if err := doDigraph("somepath", []string{"A", test.to}); err != nil {
t.Fatal(err)
}
@@ -372,7 +372,7 @@
t.Run(test.name, func(t *testing.T) {
stdin = strings.NewReader(test.in)
stdout = new(bytes.Buffer)
- if err := digraph("focus", []string{test.focus}); err != nil {
+ if err := doDigraph("focus", []string{test.focus}); err != nil {
t.Fatal(err)
}
got := stdout.(fmt.Stringer).String()
@@ -397,7 +397,7 @@
defer func(in io.Reader, out io.Writer) { stdin, stdout = in, out }(stdin, stdout)
stdin = strings.NewReader(in)
stdout = new(bytes.Buffer)
- if err := digraph("to", []string{"dot"}); err != nil {
+ if err := doDigraph("to", []string{"dot"}); err != nil {
t.Fatal(err)
}
got := stdout.(fmt.Stringer).String()
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Starting from this commit, I mostly wanted to validate my new graph package by making sure cmd/digraph could be rewritten to use it. I don't have a strong feeling on whether it's worth the churn, but it's also not bad.
For the record, to do the algorithm ports, I used the following Gemini CLI prompt, followed by manual review and fairly minor cleanup:
I want to reimplement ./cmd/digraph to use the new ./internal/graph package. For each graph algorithm implemented in digraph as a method on its digraph type: 1. reimplement that algorithm in the graph package following the implementation strategy from digraph but operating on the graph.Graph interface, 2. modify digraph to use the graph package's version of the algorithm, 3. check that the digraph and graph tests pass, and 4. commit that algorithm as its own git commit for ease of review. Put each algorithm in its own source file in the graph package. Please copy over any relevant comments from the digraph implementation, particularly those about implementation strategy. The digraph algorithms are all done on string-identified nodes, so where it would be more efficient to use compactly numbered nodes, you can use graph.Compact in the algorithm (see graph.Postorder for an example of this), but this is not required. The output of the digraph command must remain determinsitic, but it doesn't have to stay in the same order it currently emits, so it's okay to do less sorting as long as the outcome is deterministic. You can use the tests in cmd/digraph to check your work, though you may need to update the order of output if that changes.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |