mirror of
https://git.sr.ht/~rjarry/aerc
synced 2026-03-02 18:23:33 +01:00
worker/lib: implement an fswatcher interface
Implement an FSWatcher interface. The interface is used to abstract away file system watchers, which have implementation specific backends. The initial interface has one implementation: inotify for linux. Subsequent commits will add a macOS watcher. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: Ben Lee-Cohen <ben@lee-cohen.com> Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
committed by
Robin Jarry
parent
182424d279
commit
a0935a3de0
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||
)
|
||||
@@ -25,3 +26,18 @@ func GetHandlerForScheme(scheme string, worker *types.Worker) (types.Backend, er
|
||||
}
|
||||
return backend, nil
|
||||
}
|
||||
|
||||
type WatcherFactoryFunc func() (types.FSWatcher, error)
|
||||
|
||||
var watcherFactories map[string]WatcherFactoryFunc = make(map[string]WatcherFactoryFunc)
|
||||
|
||||
func RegisterWatcherFactory(os string, fn WatcherFactoryFunc) {
|
||||
watcherFactories[os] = fn
|
||||
}
|
||||
|
||||
func NewWatcher() (types.FSWatcher, error) {
|
||||
if fn, ok := watcherFactories[runtime.GOOS]; ok {
|
||||
return fn()
|
||||
}
|
||||
return nil, fmt.Errorf("Unsupported OS: %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
73
worker/lib/watchers/linux/linux.go
Normal file
73
worker/lib/watchers/linux/linux.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package linux
|
||||
|
||||
import (
|
||||
"git.sr.ht/~rjarry/aerc/log"
|
||||
"git.sr.ht/~rjarry/aerc/worker/handlers"
|
||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
func init() {
|
||||
handlers.RegisterWatcherFactory("linux", newInotifyWatcher)
|
||||
}
|
||||
|
||||
type inotifyWatcher struct {
|
||||
w *fsnotify.Watcher
|
||||
ch chan *types.FSEvent
|
||||
}
|
||||
|
||||
func newInotifyWatcher() (types.FSWatcher, error) {
|
||||
watcher := &inotifyWatcher{
|
||||
ch: make(chan *types.FSEvent),
|
||||
}
|
||||
w, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
watcher.w = w
|
||||
|
||||
go watcher.watch()
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (w *inotifyWatcher) watch() {
|
||||
defer log.PanicHandler()
|
||||
for ev := range w.w.Events {
|
||||
// we only care about files being created, removed or renamed
|
||||
switch ev.Op {
|
||||
case fsnotify.Create:
|
||||
w.ch <- &types.FSEvent{
|
||||
Operation: types.FSCreate,
|
||||
Path: ev.Name,
|
||||
}
|
||||
case fsnotify.Remove:
|
||||
w.ch <- &types.FSEvent{
|
||||
Operation: types.FSRemove,
|
||||
Path: ev.Name,
|
||||
}
|
||||
case fsnotify.Rename:
|
||||
w.ch <- &types.FSEvent{
|
||||
Operation: types.FSRename,
|
||||
Path: ev.Name,
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *inotifyWatcher) Configure(root string) error {
|
||||
return w.w.Add(root)
|
||||
}
|
||||
|
||||
func (w *inotifyWatcher) Events() chan *types.FSEvent {
|
||||
return w.ch
|
||||
}
|
||||
|
||||
func (w *inotifyWatcher) Add(p string) error {
|
||||
return w.w.Add(p)
|
||||
}
|
||||
|
||||
func (w *inotifyWatcher) Remove(p string) error {
|
||||
return w.w.Remove(p)
|
||||
}
|
||||
24
worker/types/watcher.go
Normal file
24
worker/types/watcher.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package types
|
||||
|
||||
// FSWatcher is a file system watcher
|
||||
type FSWatcher interface {
|
||||
Configure(string) error
|
||||
Events() chan *FSEvent
|
||||
// Adds a directory or file to the watcher
|
||||
Add(string) error
|
||||
// Removes a directory or file from the watcher
|
||||
Remove(string) error
|
||||
}
|
||||
|
||||
type FSOperation int
|
||||
|
||||
const (
|
||||
FSCreate FSOperation = iota
|
||||
FSRemove
|
||||
FSRename
|
||||
)
|
||||
|
||||
type FSEvent struct {
|
||||
Operation FSOperation
|
||||
Path string
|
||||
}
|
||||
Reference in New Issue
Block a user