aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-04 12:04:31 +0200
committerDanilo M. <danix@danix.xyz>2026-08-04 12:54:59 +0200
commit74d1da2755ff8e1a47bda676fab7b84e910ef738 (patch)
treee32bcf4a5d752c64255ae779666a504385434813 /README.md
parent1f25f2b10d995dd0978d5846e175c9094b69f53f (diff)
downloadqtmaildir-74d1da2755ff8e1a47bda676fab7b84e910ef738.tar.gz
qtmaildir-74d1da2755ff8e1a47bda676fab7b84e910ef738.zip
feat(sync): bring mailsync.sh here, print to stdout, exit truthfully
The reference sync script lived in the companion mailctl project, which documents that it never calls it: sync and organization are separate there on purpose. qtmaildir is the only thing that runs it programmatically, and two of its behaviours were live bugs here, so it belongs in this repo where the constraints on it are. It printed nothing a caller could see. Everything was redirected to $LOGFILE, so MailSync captured an empty stream and the sync log pane stayed blank, a known limitation carried since 0.1.0. It now writes to both through tee: cron keeps its log, and the pane has something to show. It also ended in an unconditional exit 0, discarding statuses it had already computed. qtmaildir believes that exit code: a failed mbsync reported success, cleared the unsynced-changes count, and would have allowed a sync-on-exit to quit over a sync that never happened, which is exactly the case the exit prompt exists to prevent. It now exits with mbsync's status, or notmuch's when mbsync succeeded. The statuses move through files rather than shell variables because the run block is piped into tee, which puts it in a subshell where an assignment does not survive. Verified against stub mbsync and notmuch binaries in a fake HOME, so no mail or database was touched: output reaches stdout, the log still gets every line, and a failing mbsync or notmuch produces its own exit code rather than zero. Both properties are now recorded in CLAUDE.md, since they exist for this application's sake and an edit that looks like a cleanup would remove them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'README.md')
-rw-r--r--README.md25
1 files changed, 25 insertions, 0 deletions
diff --git a/README.md b/README.md
index ec4c22a..a726a24 100644
--- a/README.md
+++ b/README.md
@@ -137,6 +137,7 @@ identity.
[sync]
; Optional. Omit and the Sync button disables itself with a tooltip.
+; assets/mailsync.sh is the reference implementation; see "The sync command".
; command = /home/you/bin/mailsync.sh
; Section names use a dot, not a slash: QSettings treats "/" as its own
@@ -269,6 +270,30 @@ set is valid.
Every change goes on the undo stack, so `Ctrl+Z` reverses a mistyped tag.
+## The sync command
+
+qtmaildir does not fetch mail. `[sync] command` names a script it runs as a
+subprocess, and `assets/mailsync.sh` is the reference implementation: `mbsync -a`
+followed by `notmuch new`, under a `flock` so a cron timer and a click here
+cannot run two `mbsync` processes over one Maildir.
+
+```bash
+ln -s "$PWD/assets/mailsync.sh" ~/bin/mailsync.sh
+```
+
+A symlink rather than a copy, so the same script serves cron and the running
+application and there is only one of it to edit.
+
+Two things any replacement has to get right, both learned the hard way:
+
+- **Print to stdout as well as any log file.** qtmaildir shows what the command
+ prints. A script that redirects its own output to a log leaves the sync pane
+ empty, which is what the previous version of this one did.
+- **Exit non-zero when the sync failed.** qtmaildir believes the exit status:
+ it reports success, clears the unsynced-changes count, and will quit on it
+ during a sync-on-exit. The previous version ended in an unconditional
+ `exit 0`, so a failed `mbsync` was indistinguishable from a clean run.
+
## Unsynced changes
Tagging changes the notmuch index at once, but the mail store only learns about