aboutsummaryrefslogtreecommitdiffstats
path: root/assets/mailsync.sh
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-07 19:17:59 +0200
committerDanilo M. <danix@danix.xyz>2026-08-07 19:17:59 +0200
commit01194fa2c48019f1dcbdfefac94f8fd5f8e38122 (patch)
treee833545eaa42c44f1cb984bd52fbf7bb66d36102 /assets/mailsync.sh
parent6bbaa1d796d3d7828c3fa6b82c7031f8aaae84bf (diff)
downloadqtmaildir-01194fa2c48019f1dcbdfefac94f8fd5f8e38122.tar.gz
qtmaildir-01194fa2c48019f1dcbdfefac94f8fd5f8e38122.zip
feat(sync): sync only the accounts with unsynced edits
A sync ran mbsync -a regardless of what changed, so tagging mail in one account fetched all of them. The account set was not a parameter anywhere on the path: MailSync::start() took no arguments and the script hardcoded -a, so nothing between a tag edit and mbsync carried which account changed. Track which accounts have edits and pass their mbsync channels through to the script, which now takes channel names and falls back to -a when given none. An empty set means all accounts, per the request: a sync with nothing pending is a fetch, and narrowing that to wherever the last edit landed would quietly stop collecting mail everywhere else. The channel is a new optional per-account key rather than the section key. The two names genuinely diverge, because a QSettings section key may carry dots that the channel does not, and mbsync treats an unknown channel as fatal rather than skipping it, so key-as-channel would fail those accounts' syncs outright rather than degrade. It defaults to the key, so accounts whose two names already agree need no config change. The edited-account set is deliberately not netted the way the pending-edit map is: that map tracks the index, where a tag removed and re-added leaves nothing outstanding, while this tracks the mail store, where both writes have already renamed files that mbsync still has to propagate. It is also snapshotted before flushHeldEdits(), which inserts into it synchronously rather than on a queued reply, so a successful sync cannot clear accounts whose edits it never carried. Closes item 49. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'assets/mailsync.sh')
-rwxr-xr-xassets/mailsync.sh20
1 files changed, 19 insertions, 1 deletions
diff --git a/assets/mailsync.sh b/assets/mailsync.sh
index 0e52ddd..ea81fa5 100755
--- a/assets/mailsync.sh
+++ b/assets/mailsync.sh
@@ -27,6 +27,14 @@
# The script owns the log, so the caller must NOT redirect into it as well. A
# crontab line ending "> mailsync.log 2>&1" writes every line a second time,
# because tee has already put it there. Just call the script.
+#
+# Usage: mailsync.sh [channel ...]
+#
+# With no arguments it syncs every channel, which is what a cron timer wants
+# and what every existing caller already does. Given channel names it syncs
+# only those, which is how qtmaildir syncs just the accounts it edited. The
+# names are mbsync CHANNEL names from ~/.mbsyncrc, which are not necessarily
+# the account names qtmaildir shows: see the `channel` key in qtmaildir.conf.
# Defensive: don't rely on cron/systemd/whatever invokes this to have
# set these correctly. Explicit beats inferred, especially after the
@@ -80,7 +88,17 @@ START_TS="$(date -Iseconds)"
# which is both the progress and the account name the status bar shows.
# This is not a buffering problem and stdbuf does not help: the output
# streams fine, there simply is none to stream.
- mbsync -V -a 2>&1 | while IFS= read -r line; do
+ # "$@" when channels were named, -a otherwise. Quoted and passed as
+ # separate words, never flattened into a string: a channel name is an
+ # argument, and mbsync takes an unknown one as a fatal error rather than
+ # skipping it, which would fail the whole run.
+ #
+ # -a is NOT equivalent to naming every channel and cannot be dropped: with
+ # no arguments at all mbsync syncs nothing and exits, which would look like
+ # a clean sync that moved no mail.
+ [ "$#" -gt 0 ] || set -- -a
+
+ mbsync -V "$@" 2>&1 | while IFS= read -r line; do
echo "$(date '+%H:%M:%S') $line"
done
echo "${PIPESTATUS[0]}" > "$STATUS_DIR/mbsync"