package internal import ( "context" "errors" "fmt" "github.com/fsnotify/fsnotify" "github.com/sirupsen/logrus" ) var ( errEventsClosedChan = errors.New("events is closed") errErrorsClosedChan = errors.New("errors is closed") errNotWriteOp = errors.New("is not Write") ) type Watcher struct { logger *logrus.Logger fswatcher *fsnotify.Watcher deploy ExecFunc } func NewWatcher(logger *logrus.Logger, notifier NotifyIface, deploy ExecFunc) (*Watcher, error) { wt, err := notifier.NewWatcher() if err != nil { return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err) } return &Watcher{ logger: logger, fswatcher: wt, deploy: deploy, }, nil } func (w *Watcher) Monitor(path string) error { return w.fswatcher.Add(path) } // Start listening for events. func (w *Watcher) Listen(ctx context.Context, errChan chan<- error, scriptPath string, args ...string) { for { select { case <-ctx.Done(): errChan <- fmt.Errorf("context cancelled: %w", ctx.Err()) return case event, ok := <-w.fswatcher.Events: if err := ctx.Err(); err != nil { errChan <- fmt.Errorf("context cancelled: %w", ctx.Err()) return } if !ok { errChan <- errEventsClosedChan return } if !event.Has(fsnotify.Write) { errChan <- fmt.Errorf("%w: %s", errNotWriteOp, event.Name) continue } w.logger.Debugf("event: %s | op: %s \n", event.Name, event.Op) if err := w.deploy(scriptPath, args...); err != nil { w.logger.Debugf("deploy: %s\n", err) errChan <- err continue } case err, ok := <-w.fswatcher.Errors: if err := ctx.Err(); err != nil { errChan <- fmt.Errorf("context cancelled: %w", ctx.Err()) return } if !ok { //log.Println(errErrorsClosedChan) errChan <- errErrorsClosedChan return } w.logger.Debugf("<-errors: %s\n", err) errChan <- err } } } func (w *Watcher) Close() error { return w.fswatcher.Close() }