Hi Sven, I am suspicious of one particular patch here. I think this is the only code path involved that has been modified recently.
Can you try applying this to the OfflineIMAP tree with patch -p1 -R and see if it helps things for you? I haven't seen this myself so your assistance tracking it down will be helpful. Thanks, - John
Tue Jun 12 17:42:15 CDT 2007 Asheesh Laroia <[EMAIL PROTECTED]> * only-write-once-to-cur-or-new.patch I have tested this and Dovecot no longer beats offlineimap to the punch. (-: I achieved that by keeping the renames in tmp/ until it finally does one last rename in new/ or cur/. diff -rN -u old-offlineimap/offlineimap/folder/Maildir.py new-offlineimap/offlineimap/folder/Maildir.py --- old-offlineimap/offlineimap/folder/Maildir.py 2007-07-17 14:16:20.812752215 -0500 +++ new-offlineimap/offlineimap/folder/Maildir.py 2007-07-17 14:16:20.816752617 -0500 @@ -130,6 +130,8 @@ return st.st_mtime def savemessage(self, uid, content, flags, rtime): + # This function only ever saves to tmp/, + # but it calls savemessageflags() to actually save to cur/ or new/. ui = UIBase.getglobalui() ui.debug('maildir', 'savemessage: called to write with flags %s and content %s' % \ (repr(flags), repr(content))) @@ -140,12 +142,9 @@ # We already have it. self.savemessageflags(uid, flags) return uid - if 'S' in flags: - # If a message has been seen, it goes into the cur - # directory. CR debian#152482, [complete.org #4] - newdir = os.path.join(self.getfullname(), 'cur') - else: - newdir = os.path.join(self.getfullname(), 'new') + + # Otherwise, save the message in tmp/ and then call savemessageflags() + # to give it a permanent home. tmpdir = os.path.join(self.getfullname(), 'tmp') messagename = None attempts = 0 @@ -179,20 +178,21 @@ os.utime(os.path.join(tmpdir,tmpmessagename), (rtime,rtime)) ui.debug('maildir', 'savemessage: moving from %s to %s' % \ (tmpmessagename, messagename)) - os.link(os.path.join(tmpdir, tmpmessagename), - os.path.join(newdir, messagename)) - os.unlink(os.path.join(tmpdir, tmpmessagename)) + if tmpmessagename != messagename: # then rename it + os.link(os.path.join(tmpdir, tmpmessagename), + os.path.join(tmpdir, messagename)) + os.unlink(os.path.join(tmpdir, tmpmessagename)) try: # fsync the directory (safer semantics in Linux) - fd = os.open(newdir, os.O_RDONLY) + fd = os.open(tmpdir, os.O_RDONLY) os.fsync(fd) os.close(fd) except: pass self.messagelist[uid] = {'uid': uid, 'flags': [], - 'filename': os.path.join(newdir, messagename)} + 'filename': os.path.join(tmpdir, messagename)} self.savemessageflags(uid, flags) ui.debug('maildir', 'savemessage: returning uid %d' % uid) return uid @@ -203,6 +203,7 @@ def savemessageflags(self, uid, flags): oldfilename = self.messagelist[uid]['filename'] newpath, newname = os.path.split(oldfilename) + tmpdir = os.path.join(self.getfullname(), 'tmp') if 'S' in flags: # If a message has been seen, it goes into the cur # directory. CR debian#152482, [complete.org #4] @@ -225,6 +226,10 @@ self.messagelist[uid]['flags'] = flags self.messagelist[uid]['filename'] = newfilename + # By now, the message had better not be in tmp/ land! + final_dir, final_name = os.path.split(self.messagelist[uid]['filename']) + assert final_dir != tmpdir + def deletemessage(self, uid): if not uid in self.messagelist: return