From f20933f51220e1946ccecd16e0ebfda05aa2b5cb Mon Sep 17 00:00:00 2001 From: Julian Pidancet Date: Wed, 26 Oct 2022 22:29:10 +0200 Subject: [PATCH] notmuch: move new maildir files to cur upon opening a folder By default "notmuch new" will index files in place and won't move new files from the new/ directory to cur/ because it assumes that is the job of the email client. During normal operation, once moved by the client, the "notmuch new" command will "fix" the database by detecting file renames. This workflow is a problem because we need to move the new/ files to cur/, otherwise the maildir lib will not work properly, but at the same time we cannot afford the notmuch database to be out of sync with the location of message files on disk, because we rely on it for listing folders, displaying emails, ect... This change uses a trick that request notmuch to synchronize message tags to maildir flags, that will effectively rename new files and cause them to be moved into the cur/ directory. Signed-off-by: Julian Pidancet Acked-by: Robin Jarry Acked-by: Tim Culverhouse --- worker/notmuch/worker.go | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go index d4f0c91..13c9d97 100644 --- a/worker/notmuch/worker.go +++ b/worker/notmuch/worker.go @@ -281,8 +281,12 @@ func (w *worker) handleOpenDirectory(msg *types.OpenDirectory) error { q := "" if w.store != nil { folders, _ := w.store.FolderMap() - if _, ok := folders[msg.Directory]; ok { + dir, ok := folders[msg.Directory] + if ok { q = fmt.Sprintf("folder:%s", strconv.Quote(msg.Directory)) + if err := w.processNewMaildirFiles(string(dir)); err != nil { + return err + } } } if q == "" { @@ -901,3 +905,37 @@ func (w *worker) handleRemoveDirectory(msg *types.RemoveDirectory) error { w.done(msg) return nil } + +// This is a hack that calls MsgModifyTags with an empty list of tags to +// apply on new messages causing notmuch to rename files and effectively +// move them into the cur/ dir. +func (w *worker) processNewMaildirFiles(dir string) error { + f, err := os.Open(filepath.Join(dir, "new")) + if err != nil { + return err + } + defer f.Close() + names, err := f.Readdirnames(0) + if err != nil { + return err + } + + for _, n := range names { + if n[0] == '.' { + continue + } + + key, err := w.db.MsgIDFromFilename(filepath.Join(dir, "new", n)) + if err != nil { + // Message is not yet indexed, leave it alone + continue + } + // Force message to move from new/ to cur/ + err = w.db.MsgModifyTags(key, nil, nil) + if err != nil { + logging.Errorf("MsgModifyTags failed: %v", err) + } + } + + return nil +}