github.com/decomp/exp@v0.0.0-20210624183419-6d058f5e1da6/cmd/dot2png/main.go (about) 1 // The dot2png tool converts DOT files to PNG images. 2 // 3 // Usage: 4 // 5 // dot2png FILE.dot... 6 // 7 // Flags: 8 // 9 // -f force overwrite existing images 10 package main 11 12 import ( 13 "flag" 14 "fmt" 15 "log" 16 "os" 17 "os/exec" 18 19 "github.com/mewkiz/pkg/errutil" 20 "github.com/mewkiz/pkg/pathutil" 21 ) 22 23 func usage() { 24 const use = ` 25 Usage: dot2png FILE.dot... 26 Convert DOT files to PNG images. 27 28 Flags: 29 ` 30 fmt.Fprintln(os.Stderr, use[1:]) 31 flag.PrintDefaults() 32 } 33 34 func main() { 35 // Parse command line options. 36 var ( 37 // force specifies whether to force overwrite existing images. 38 force bool 39 ) 40 flag.BoolVar(&force, "f", false, "force overwrite existing images") 41 flag.Usage = usage 42 flag.Parse() 43 44 // Convert DOT files to PNG images. 45 for _, dotPath := range flag.Args() { 46 if err := convert(dotPath, force); err != nil { 47 log.Fatal(err) 48 } 49 } 50 } 51 52 // convert converts the provided DOT file to a PNG image. 53 func convert(dotPath string, force bool) error { 54 pngPath := pathutil.TrimExt(dotPath) + ".png" 55 56 // Skip existing files unless the "-f" flag is set. 57 if !force { 58 dotStat, err := os.Stat(dotPath) 59 if err != nil { 60 return errutil.Err(err) 61 } 62 pngStat, err := os.Stat(pngPath) 63 if err != nil { 64 if !os.IsNotExist(err) { 65 return errutil.Err(err) 66 } 67 } else { 68 dotMod, pngMod := dotStat.ModTime(), pngStat.ModTime() 69 if dotMod.Before(pngMod) { 70 // PNG file is newer than DOT file, ignore. 71 return nil 72 } 73 } 74 } 75 76 // Convert the DOT file to a PNG image. 77 cmd := exec.Command("dot", "-Tpng", "-o", pngPath, dotPath) 78 cmd.Stdout = os.Stdout 79 cmd.Stderr = os.Stderr 80 log.Printf("Creating: %q", pngPath) 81 if err := cmd.Run(); err != nil { 82 return errutil.Err(err) 83 } 84 85 return nil 86 }