// goredo -- djb's redo implementation on pure Go // Copyright (C) 2020-2024 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" "os" "path" ) type DotNodes struct { from string to string } func dotWalker(data map[DotNodes]bool, tgt *Tgt) (map[DotNodes]bool, error) { raw, err := os.ReadFile(tgt.dep) if err != nil { return nil, ErrLine(err) } _, raw, err = depHeadParse(raw) if err != nil { return nil, ErrLine(err) } var typ byte var name string var dep *Tgt var chunk []byte tgtH, _ := pathSplit(tgt.a) for len(raw) > 0 { typ, chunk, raw, err = chunkRead(raw) if err != nil { return nil, ErrLine(err) } switch typ { case DepTypeIfcreate: data[DotNodes{tgt.rel, NewTgt(path.Join(tgtH, string(chunk))).rel}] = true case DepTypeIfchange, DepTypeIfchangeNonex: if typ == DepTypeIfchangeNonex { name = string(chunk) } else { name = string(chunk[InodeLen+HashLen:]) } dep = NewTgt(path.Join(tgtH, name)) if dep.a == tgt.a { continue } data[DotNodes{tgt.rel, dep.rel}] = false if isSrc(dep) { continue } data, err = dotWalker(data, dep) if err != nil { return nil, err } } } return data, nil } func dotPrint(tgts []*Tgt) 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 }