aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--worker/maildir/worker.go81
-rw-r--r--worker/worker.go6
4 files changed, 76 insertions, 14 deletions
diff --git a/go.mod b/go.mod
index 2fb4ac8..74ad22d 100644
--- a/go.mod
+++ b/go.mod
@@ -14,6 +14,7 @@ require (
github.com/emersion/go-message v0.10.4
github.com/emersion/go-sasl v0.0.0-20190704090222-36b50694675c
github.com/emersion/go-smtp v0.11.1
+ github.com/fsnotify/fsnotify v1.4.7
github.com/gdamore/tcell v1.1.2
github.com/go-ini/ini v1.42.0
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
diff --git a/go.sum b/go.sum
index 31f0d5e..79628de 100644
--- a/go.sum
+++ b/go.sum
@@ -39,6 +39,8 @@ github.com/emersion/go-smtp v0.11.1 h1:2IBWhU2zjrfOOmZal3qRxVsfYnf0rN+ccImZrjnMT
github.com/emersion/go-smtp v0.11.1/go.mod h1:CfUbM5NgspbOMHFEgCdoK2PVrKt48HAPtL8hnahwfYg=
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg=
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/go-ini/ini v1.42.0 h1:TWr1wGj35+UiWHlBA8er89seFXxzwFn11spilrrj+38=
diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go
index a5416cc..1e68a2e 100644
--- a/worker/maildir/worker.go
+++ b/worker/maildir/worker.go
@@ -8,6 +8,7 @@ import (
"path/filepath"
"github.com/emersion/go-maildir"
+ "github.com/fsnotify/fsnotify"
"git.sr.ht/~sircmpwn/aerc/models"
"git.sr.ht/~sircmpwn/aerc/worker/types"
@@ -20,31 +21,68 @@ type Worker struct {
c *Container
selected *maildir.Dir
worker *types.Worker
+ watcher *fsnotify.Watcher
}
// NewWorker creates a new maildir worker with the provided worker.
-func NewWorker(worker *types.Worker) *Worker {
- return &Worker{worker: worker}
+func NewWorker(worker *types.Worker) (*Worker, error) {
+ watch, err := fsnotify.NewWatcher()
+ if err != nil {
+ return nil, fmt.Errorf("could not create file system watcher: %v", err)
+ }
+ return &Worker{worker: worker, watcher: watch}, nil
}
// Run starts the worker's message handling loop.
func (w *Worker) Run() {
for {
- action := <-w.worker.Actions
- msg := w.worker.ProcessAction(action)
- if err := w.handleMessage(msg); err == errUnsupported {
- w.worker.PostMessage(&types.Unsupported{
- Message: types.RespondTo(msg),
- }, nil)
- } else if err != nil {
- w.worker.PostMessage(&types.Error{
- Message: types.RespondTo(msg),
- Error: err,
- }, nil)
+ select {
+ case action := <-w.worker.Actions:
+ w.handleAction(action)
+ case ev := <-w.watcher.Events:
+ w.handleFSEvent(ev)
}
}
}
+func (w *Worker) handleAction(action types.WorkerMessage) {
+ msg := w.worker.ProcessAction(action)
+ if err := w.handleMessage(msg); err == errUnsupported {
+ w.worker.PostMessage(&types.Unsupported{
+ Message: types.RespondTo(msg),
+ }, nil)
+ } else if err != nil {
+ w.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+}
+
+func (w *Worker) handleFSEvent(ev fsnotify.Event) {
+ // we only care about files being created
+ if ev.Op != fsnotify.Create {
+ return
+ }
+ // if there's not a selected directory to rescan, ignore
+ if w.selected == nil {
+ return
+ }
+ _, err := w.selected.Unseen()
+ if err != nil {
+ w.worker.Logger.Printf("could not move new to cur : %v", err)
+ return
+ }
+ uids, err := w.c.UIDs(*w.selected)
+ if err != nil {
+ w.worker.Logger.Printf("could not scan UIDs: %v", err)
+ return
+ }
+ w.worker.PostMessage(&types.DirectoryContents{
+ Uids: uids,
+ }, nil)
+}
+
func (w *Worker) done(msg types.WorkerMessage) {
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
}
@@ -139,11 +177,28 @@ func (w *Worker) handleListDirectories(msg *types.ListDirectories) error {
func (w *Worker) handleOpenDirectory(msg *types.OpenDirectory) error {
defer w.done(msg)
w.worker.Logger.Printf("opening %s", msg.Directory)
+
+ // remove existing watch path
+ if w.selected != nil {
+ prevDir := filepath.Join(string(*w.selected), "new")
+ if err := w.watcher.Remove(prevDir); err != nil {
+ return fmt.Errorf("could not unwatch previous directory: %v", err)
+ }
+ }
+
+ // open the directory
dir, err := w.c.OpenDirectory(msg.Directory)
if err != nil {
return err
}
w.selected = &dir
+
+ // add watch path
+ newDir := filepath.Join(string(*w.selected), "new")
+ if err := w.watcher.Add(newDir); err != nil {
+ return fmt.Errorf("could not add watch to directory: %v", err)
+ }
+
// TODO: why does this need to be sent twice??
info := &types.DirectoryInfo{
Info: &models.DirectoryInfo{
diff --git a/worker/worker.go b/worker/worker.go
index dd14a23..a37927e 100644
--- a/worker/worker.go
+++ b/worker/worker.go
@@ -29,7 +29,11 @@ func NewWorker(source string, logger *log.Logger) (*types.Worker, error) {
case "imaps":
worker.Backend = imap.NewIMAPWorker(worker)
case "maildir":
- worker.Backend = maildir.NewWorker(worker)
+ if w, err := maildir.NewWorker(worker); err != nil {
+ return nil, fmt.Errorf("could not create maildir worker: %v", err)
+ } else {
+ worker.Backend = w
+ }
default:
return nil, fmt.Errorf("Unknown backend %s", u.Scheme)
}