summaryrefslogtreecommitdiff
path: root/pkg/hooks/monitor.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/hooks/monitor.go')
-rw-r--r--pkg/hooks/monitor.go73
1 files changed, 73 insertions, 0 deletions
diff --git a/pkg/hooks/monitor.go b/pkg/hooks/monitor.go
new file mode 100644
index 000000000..ba5e0f246
--- /dev/null
+++ b/pkg/hooks/monitor.go
@@ -0,0 +1,73 @@
+package hooks
+
+import (
+ "context"
+ "path/filepath"
+
+ "github.com/fsnotify/fsnotify"
+ "github.com/sirupsen/logrus"
+)
+
+// Monitor dynamically monitors hook directories for additions,
+// updates, and removals.
+//
+// This function write two empty structs to the sync channel: the
+// first is written after the watchers are established and the second
+// when this function exits. The expected usage is:
+//
+// ctx, cancel := context.WithCancel(context.Background())
+// sync := make(chan error, 2)
+// go m.Monitor(ctx, sync)
+// err := <-sync // block until writers are established
+// if err != nil {
+// return err // failed to establish watchers
+// }
+// // do stuff
+// cancel()
+// err = <-sync // block until monitor finishes
+func (m *Manager) Monitor(ctx context.Context, sync chan<- error) {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ sync <- err
+ return
+ }
+ defer watcher.Close()
+
+ for _, dir := range m.directories {
+ err = watcher.Add(dir)
+ if err != nil {
+ logrus.Errorf("failed to watch %q for hooks", dir)
+ sync <- err
+ return
+ }
+ logrus.Debugf("monitoring %q for hooks", dir)
+ }
+
+ sync <- nil
+
+ for {
+ select {
+ case event := <-watcher.Events:
+ if event.Op&fsnotify.Remove == fsnotify.Remove {
+ ok := m.remove(filepath.Base(event.Name))
+ if ok {
+ logrus.Debugf("removed hook %s", event.Name)
+ }
+ }
+ if event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Write == fsnotify.Write {
+ err = m.add(event.Name)
+ if err == nil {
+ logrus.Debugf("added hook %s", event.Name)
+ } else if err != ErrNoJSONSuffix {
+ logrus.Errorf("failed to add hook %s: %v", event.Name, err)
+ }
+ }
+ case <-ctx.Done():
+ err = ctx.Err()
+ logrus.Debugf("hook monitoring canceled: %v", err)
+ sync <- err
+ close(sync)
+ return
+ }
+ }
+}