X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=dot.go;fp=dot.go;h=d59bc408a02d3c772a500bce5a98f3ecce44c9ce;hb=67e92d5a298516292bbbee1f7714708cdc0766f8;hp=0000000000000000000000000000000000000000;hpb=634ee31ae35a2eaac517e0ffa1b7caede4b27ac5;p=goredo.git diff --git a/dot.go b/dot.go new file mode 100644 index 0000000..d59bc40 --- /dev/null +++ b/dot.go @@ -0,0 +1,94 @@ +/* +goredo -- redo implementation on pure Go +Copyright (C) 2020 Sergey Matveev + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +// Dependency DOT graph generation + +package main + +import ( + "fmt" + "io" + "os" + "path" + + "go.cypherpunks.ru/recfile" +) + +type DotNodes struct { + from string + to string +} + +func dotWalker(data map[DotNodes]bool, tgtOrig string) (map[DotNodes]bool, error) { + cwd, tgt := cwdAndTgt(tgtOrig) + depPath := path.Join(cwd, RedoDir, tgt+DepSuffix) + fdDep, err := os.Open(depPath) + if err != nil { + return nil, err + } + defer fdDep.Close() + var dep string + r := recfile.NewReader(fdDep) + for { + m, err := r.NextMap() + if err != nil { + if err == io.EOF { + break + } + return nil, err + } + switch m["Type"] { + case DepTypeIfcreate: + data[DotNodes{tgtOrig, cwdMustRel(cwd, m["Target"])}] = true + case DepTypeIfchange: + dep = m["Target"] + data[DotNodes{tgtOrig, cwdMustRel(cwd, dep)}] = false + if isSrc(cwd, dep) || dep == tgt { + continue + } + data, err = dotWalker(data, cwdMustRel(cwd, dep)) + if err != nil { + return nil, err + } + } + } + return data, nil +} + +func dotPrint(tgts []string) error { + data := map[DotNodes]bool{} + var err error + for _, tgt := range tgts { + data, err = dotWalker(data, tgt) + if err != nil { + return err + } + } + fmt.Println(`digraph d { + rankdir=LR + ranksep=2 + splines=false // splines=ortho + node[shape=rectangle]`) + for nodes, nonexistent := range data { + fmt.Printf("\n\t\"%s\" -> \"%s\"", nodes.from, nodes.to) + if nonexistent { + fmt.Print(" [style=dotted]") + } + } + fmt.Println("\n}") + return nil +}