90 lines
1.5 KiB
Go
90 lines
1.5 KiB
Go
package fswatcher
|
|
|
|
import (
|
|
"math"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
)
|
|
|
|
// DefaultDelay to avoid unnecessary handler calls
|
|
const DefaultDelay = 100 * time.Millisecond
|
|
|
|
// Watcher of file system changes
|
|
type Watcher struct {
|
|
watcher *fsnotify.Watcher
|
|
delay time.Duration
|
|
files []string
|
|
mu sync.Mutex
|
|
t map[string]*time.Timer
|
|
}
|
|
|
|
// Creates FS Watcher
|
|
func New(files []string, delay time.Duration) (*Watcher, error) {
|
|
if delay <= 0 {
|
|
delay = DefaultDelay
|
|
}
|
|
watcher, err := fsnotify.NewWatcher()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, file := range files {
|
|
err = watcher.Add(filepath.Dir(file))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
fswatcher := &Watcher{
|
|
watcher: watcher,
|
|
delay: delay,
|
|
files: files,
|
|
t: make(map[string]*time.Timer),
|
|
}
|
|
|
|
return fswatcher, nil
|
|
}
|
|
|
|
func (w *Watcher) watch(handler func(e fsnotify.Event)) {
|
|
for e := range w.watcher.Events {
|
|
handler(e)
|
|
}
|
|
}
|
|
|
|
// Start watcher
|
|
func (w *Watcher) Start(handler func(e fsnotify.Event)) {
|
|
w.watch(func(e fsnotify.Event) {
|
|
var found bool
|
|
for _, f := range w.files {
|
|
if f == e.Name {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
return
|
|
}
|
|
w.mu.Lock()
|
|
t, ok := w.t[e.Name]
|
|
w.mu.Unlock()
|
|
if !ok {
|
|
t = time.AfterFunc(math.MaxInt64, func() {
|
|
handler(e)
|
|
})
|
|
t.Stop()
|
|
|
|
w.mu.Lock()
|
|
w.t[e.Name] = t
|
|
w.mu.Unlock()
|
|
}
|
|
t.Reset(w.delay)
|
|
})
|
|
}
|
|
|
|
// Stop watcher
|
|
func (w *Watcher) Stop() error {
|
|
return w.watcher.Close()
|
|
}
|