package main import ( "crypto/sha256" "fmt" "io" "io/fs" "log" "os" "path/filepath" flags "github.com/jessevdk/go-flags" ) const VERSION string = "v0.1.0" var opts struct { Version bool `short:"v" long:"version" description:"Displays version info and exits"` Files []string `short:"f" long:"file" description:"File(s) to listen to (watch)" value-name:"FILE"` Condition string `short:"w" long:"when" description:"If multiple files are specified, choose if any file or all files specified are needed to trigger COMMAND" default:"any" choice:"any" choice:"all"` Checksum bool `short:"c" long:"checksum" description:"Use checksum to determine when file(s) are changed instead of writes/modification time"` Interval string `short:"i" long:"interval" description:"Use this time interval (ex. 5m30s, 1s) between filesystem checks instead of using kernel events"` } func validateFiles(files []string) error { if len(files) <= 0 { fmt.Println("listen: at least one file (-f) is required") return flags.ErrCommandRequired } for _, file := range files { info, err := os.Stat(file) if err != nil { fmt.Printf("listen: %s\n", err) return err } if info.IsDir() { fmt.Printf("listen: %s: not a file\n", file) return fs.ErrInvalid } _, err = os.Open(file) if err != nil { fmt.Printf("listen: %s\n", err) return err } } return nil } func main() { parser := flags.NewParser(&opts, flags.Default) parser.Usage = "[OPTIONS] -- [COMMAND]" remaining, err := parser.Parse() if err == nil { if opts.Version { fmt.Printf("listen %s\n", VERSION) } else if err := validateFiles(opts.Files); err == nil { var filesMap map[string]bool = make(map[string]bool) var cksumMap map[string][]byte = make(map[string][]byte) success := true for _, file := range opts.Files { hasher := sha256.New() f, err := os.Open(file) if err != nil { success = false break } if _, err := io.Copy(hasher, f); err != nil { log.Fatal(err) } abs, err := filepath.Abs(file) if err == nil { filesMap[abs] = false cksumMap[abs] = hasher.Sum(nil) } else { success = false break } } if success { l := Listen{filesMap, cksumMap, opts.Condition, opts.Checksum, opts.Interval, remaining} l.Run() } } } }