Merge branch 'next'

Conflicts:
	Changelog.rst
This commit is contained in:
Sebastian Spaeth 2012-01-06 13:24:50 +01:00
commit b569ef551f
7 changed files with 47 additions and 22 deletions

View File

@ -11,7 +11,23 @@ ChangeLog
on releases. And because I'm lazy, it will also be used as a draft for the
releases announces.
=======
OfflineIMAP v6.4.4 (2012-01-06)
===============================
This is a bugfix release, fixing regressions occurring in or since 6.4.0.
* Fix the missing folder error that occured when a new remote folder was
detected (IMAP<->Maildir)
* Possibly fixed bug that prevented us from ever re-reading Maildir
folders, so flag changes and deletions were not detected when running
in a refresh loop. This is a regression that was introduced in about
6.4.0.
* Never mangle maildir file names when using nonstandard Maildir flags
(such as 'a'), note that they will still be deleted as they are not
supported in the sync to an IMAP server.
OfflineIMAP v6.4.3 (2012-01-04)
===============================

View File

@ -1,7 +1,7 @@
__all__ = ['OfflineImap']
__productname__ = 'OfflineIMAP'
__version__ = "6.4.3"
__version__ = "6.4.4"
__copyright__ = "Copyright 2002-2012 John Goerzen & contributors"
__author__ = "John Goerzen"
__author_email__= "john@complete.org"

View File

@ -289,10 +289,10 @@ class SyncableAccount(Account):
localrepos.getfolders()
statusrepos.getfolders()
remoterepos.sync_folder_structure(localrepos, statusrepos)
# replicate the folderstructure between REMOTE to LOCAL
if not localrepos.getconfboolean('readonly', False):
self.ui.syncfolders(remoterepos, localrepos)
remoterepos.syncfoldersto(localrepos, statusrepos)
# iterate through all folders on the remote repo and sync
for remotefolder in remoterepos.getfolders():

View File

@ -64,13 +64,13 @@ class MaildirFolder(BaseFolder):
self.root = root
self.sep = sep
self.messagelist = None
# check if we should use a different infosep to support Win file systems
self.wincompatible = self.config.getdefaultboolean(
"Account "+self.accountname, "maildir-windows-compatible", False)
self.infosep = '!' if self.wincompatible else ':'
"""infosep is the separator between maildir name and flag appendix"""
self.flagmatchre = re.compile(self.infosep + '.*2,([A-Z]+)')
self.flagmatchre = re.compile('(%s2,)(\w*)' % self.infosep)
#self.ui is set in BaseFolder.init()
# Cache the full folder path, as we use getfullname() very often
self._fullname = os.path.join(self.getroot(), self.getname())
@ -162,7 +162,7 @@ class MaildirFolder(BaseFolder):
#identify flags in the path name
flagmatch = self.flagmatchre.search(messagename)
if flagmatch:
flags = set(flagmatch.group(1))
flags = set(flagmatch.group(2))
else:
flags = set()
# 'filename' is 'dirannex/filename', e.g. cur/123,U=1,FMD5=1:2,S
@ -185,7 +185,7 @@ class MaildirFolder(BaseFolder):
def cachemessagelist(self):
if self.messagelist is None:
self.messagelist = self._scanfolder()
def getmessagelist(self):
return self.messagelist
@ -259,7 +259,7 @@ class MaildirFolder(BaseFolder):
self.savemessageflags(uid, flags)
self.ui.debug('maildir', 'savemessage: returning uid %d' % uid)
return uid
def getmessageflags(self, uid):
return self.messagelist[uid]['flags']
@ -274,15 +274,14 @@ class MaildirFolder(BaseFolder):
else:
dir_prefix = 'new'
infostr = self.infosep
infomatch = re.search('(' + self.infosep + '.*)$', newname)
if infomatch: # If the info string is present..
infostr = infomatch.group(1)
newname = newname.split(self.infosep)[0] # Strip off the info string.
infostr = re.sub('2,[A-Z]*', '', infostr)
infostr += '2,' + ''.join(sorted(flags))
# Strip off existing infostring (preserving small letter flags, that
# dovecot uses)
infomatch = self.flagmatchre.search(newname)
if infomatch:
newname = newname[:-len(infomatch.group())] #strip off
infostr = '%s2,%s' % (self.infosep, ''.join(sorted(flags)))
newname += infostr
newfilename = os.path.join(dir_prefix, newname)
if (newfilename != oldfilename):
try:
@ -292,7 +291,7 @@ class MaildirFolder(BaseFolder):
raise OfflineImapError("Can't rename file '%s' to '%s': %s" % (
oldfilename, newfilename, e[1]),
OfflineImapError.ERROR.FOLDER)
self.messagelist[uid]['flags'] = flags
self.messagelist[uid]['filename'] = newfilename

View File

@ -132,8 +132,8 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin):
def getfolder(self, foldername):
raise NotImplementedError
def syncfoldersto(self, dst_repo, status_repo):
def sync_folder_structure(self, dst_repo, status_repo):
"""Syncs the folders in this repository to those in dest.
It does NOT sync the contents of those folders. nametrans rules
@ -158,6 +158,9 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin):
# Find new folders on src_repo.
for src_name, src_folder in src_hash.iteritems():
# Don't create on dst_repo, if it is readonly
if dst_repo.getconfboolean('readonly', False):
break
if src_folder.sync_this and not src_name in dst_hash:
try:
dst_repo.makefolder(src_name)
@ -171,6 +174,10 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin):
status_repo.getsep()))
# Find new folders on dst_repo.
for dst_name, dst_folder in dst_hash.iteritems():
if self.getconfboolean('readonly', False):
# Don't create missing folder on readonly repo.
break
if dst_folder.sync_this and not dst_name in src_hash:
# nametrans sanity check!
# Does nametrans back&forth lead to identical names?
@ -202,7 +209,6 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin):
src_repo, newdst_name),
OfflineImapError.ERROR.REPO)
# end sanity check, actually create the folder
try:
src_repo.makefolder(newsrc_name)
src_haschanged = True # Need to refresh list

View File

@ -190,4 +190,8 @@ class MaildirRepository(BaseRepository):
if self.folders == None:
self.folders = self._getfolders_scandir(self.root)
return self.folders
def forgetfolders(self):
"""Forgets the cached list of folders, if any. Useful to run
after a sync run."""
self.folders = None

View File

@ -285,7 +285,7 @@ class UIBase(object):
"""Output that we finished syncing an account (in which time)"""
sec = time.time() - self.acct_startimes[account]
del self.acct_startimes[account]
self._msg("*** Finished account '%s' in %d:%02d" %
self.logger.info("*** Finished account '%s' in %d:%02d" %
(account, sec // 60, sec % 60))
def syncfolders(self, src_repo, dst_repo):