aboutsummaryrefslogtreecommitdiffstats
path: root/src/messageview.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-25 11:33:16 +0200
committerDanilo M. <danix@danix.xyz>2026-08-25 11:33:16 +0200
commit0c98e07afc848b5563263945c94076125e265f79 (patch)
tree6a2cfef0d3f0ebafa9dd657299715773f3127f19 /src/messageview.cpp
parentbfc5f78758f527f969204b61ad2317470a454e59 (diff)
downloadqtmaildir-0c98e07afc848b5563263945c94076125e265f79.tar.gz
qtmaildir-0c98e07afc848b5563263945c94076125e265f79.zip
fix(delete): recover when a sync renamed the file underneath a move
Item 162. mbsync uploads a file and renames it to record the server UID (`<name>,U=<uid>:2,<flags>`), and notmuch keeps the pre-`U=` name until that sync's `notmuch new` runs. moveMessages() renamed a path that no longer existed, reported "Cannot move <file> to <folder>", and skipped the message: Delete silently did nothing while blaming the destination folder for a timing problem. Before renaming, check whether the recorded path still exists. If it does not, reindex that one Maildir directory and re-read the message's filenames by id, taking the one that is on disk. Recovery is by MESSAGE ID rather than by scanning the folder, because two files can carry the same id and scanning could move the wrong one. reindexFolder() indexes a single directory and is deliberately not a `notmuch new`, which would walk the whole Maildir and run the post-new hook that tags real mail. Bounded to one reindex and one retry, so a file that is genuinely gone still reports rather than becoming a silent no-op. The second test pins that half. Holding the move while a sync runs was the other candidate and is not the fix: sendMove() already refuses on the write lock (items 97 and 106), but aSyncHoldsTheWriteLock() tracks notmuch's lock, while this window sits between mbsync's rename and that sync's `notmuch new`. mbsync renames without touching that lock, so the damaging window is open when there is nothing to observe. That refusal is left alone; it does its own job. The ordinary fixture layout cannot see this, since nothing renames a file underneath the index. The test renames without reindexing, which is exactly the window mbsync opens, and guards that the database still names the old path so it cannot pass against a fixture that quietly reindexed. Mutation-checked: disabling the recovery reproduces the original error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UUQS6n3cmsFrsjCNmwNtf8
Diffstat (limited to 'src/messageview.cpp')
0 files changed, 0 insertions, 0 deletions