main.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | package main import ( "context" "flag" "log" "os" "os/signal" "strings" "sync" "syscall" "time" "github.com/fsnotify/fsnotify" "alin.ovh/erl/command" "alin.ovh/erl/state" "alin.ovh/erl/watcher" ) var ( Exec = flag.String("exec", "", "command to execute on file change") ) func Start(ctx context.Context, w watcher.Watcher, sm *state.StateMachine) { var wg sync.WaitGroup wg.Add(1) go func(events <-chan watcher.Event, errors <-chan error) { defer wg.Done() sm.SendEvent(state.Start) for { select { case <-ctx.Done(): sm.SendEvent(state.Signal) return case event, ok := <-events: if !ok { return } // skip if _only_ chmod if event.Op == fsnotify.Chmod { continue } log.Printf("event: %s %s\n", event.Name, event.Op.String()) if event.Op.Has(fsnotify.Create) { stat, err := os.Stat(event.Name) if err != nil { log.Printf("Error getting file info: %v\n", err) continue } if stat.IsDir() { err = w.AddRecursive(event.Name) if err != nil { log.Printf("Error adding directory to watcher: %v\n", err) } } } if event.Op.Has(fsnotify.Remove) { for _, dir := range w.WatchList() { if strings.HasPrefix(dir, event.Name) { err := w.Remove(dir) if err != nil { log.Printf("Error removing directory from watcher: %v\n", err) } } } } sm.SendEvent(state.Restart) time.Sleep(100 * time.Millisecond) case err, ok := <-errors: if !ok { return } log.Printf("Error: %v\n", err) } } }(w.Monitor()) err := w.AddRecursive(".") if err != nil { log.Fatalf("failed to add directory to watcher: %v", err) } <-ctx.Done() log.Println("shutting down") sm.SendEvent(state.Signal) wg.Wait() } func main() { log.SetFlags(log.Lmsgprefix) flag.Parse() program := *Exec if program == "" { log.Fatal("no command provided") } watcher, err := watcher.New() if err != nil { log.Fatal(err) } defer watcher.Close() ctx, cancel := signal.NotifyContext( context.Background(), os.Interrupt, syscall.SIGHUP, syscall.SIGTERM, ) defer cancel() cmd := command.New(program, flag.Args(), command.Options{}) sm := state.New(cmd, log.New(os.Stderr, "state: ", log.Lmsgprefix)) Start(ctx, watcher, sm) } |