From 4e89bbfe6e1a95742630191800dfd9cfd76150a0 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Fri, 30 Sep 2011 08:58:08 +0200 Subject: [PATCH] Recache folder list after creating a new folder If we create a new folder we would previously not update our folder list, which led to us skipping the synchronization of those new folders during the initial run (subsequent runs would pick it up). Invalidate the folder cache when we create a folder during folder structure sync. Regetting the whole list from an IMAP server might be slightly suboptimal from a performance point, but it is easy and will lead to consistent results. Hopefully we will not have to create new folders on each new run. Reported-by: Daniel Shahaf Signed-off-by: Sebastian Spaeth --- Changelog.draft.rst | 3 +++ offlineimap/accounts.py | 2 +- offlineimap/repository/Base.py | 13 +++++++++++-- offlineimap/repository/IMAP.py | 4 ++++ offlineimap/repository/Maildir.py | 6 ++++-- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Changelog.draft.rst b/Changelog.draft.rst index 44048b9..5095b2e 100644 --- a/Changelog.draft.rst +++ b/Changelog.draft.rst @@ -26,3 +26,6 @@ Bug Fixes * Syncing multiple accounts in single-threaded mode would fail as we try to "register" a thread as belonging to two accounts which was fatal. Make it non-fatal (it can be legitimate). + +* New folders on the remote would be skipped on the very sync run they + are created and only by synced in subsequent runs. Fixed. diff --git a/offlineimap/accounts.py b/offlineimap/accounts.py index 2f674c9..71f08fe 100644 --- a/offlineimap/accounts.py +++ b/offlineimap/accounts.py @@ -265,7 +265,7 @@ class SyncableAccount(Account): remoterepos = self.remoterepos localrepos = self.localrepos statusrepos = self.statusrepos - # replicate the folderstructure from REMOTE to LOCAL + # replicate the folderstructure between REMOTE to LOCAL if not localrepos.getconfboolean('readonly', False): self.ui.syncfolders(remoterepos, localrepos) remoterepos.syncfoldersto(localrepos, statusrepos) diff --git a/offlineimap/repository/Base.py b/offlineimap/repository/Base.py index 0da307f..972aefb 100644 --- a/offlineimap/repository/Base.py +++ b/offlineimap/repository/Base.py @@ -144,7 +144,8 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin): src_repo = self src_folders = src_repo.getfolders() dst_folders = dst_repo.getfolders() - + # Do we need to refresh the folder list afterwards? + src_haschanged, dst_haschanged = False, False # Create hashes with the names, but convert the source folders # to the dest folder's sep. src_hash = {} @@ -160,6 +161,7 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin): if src_folder.sync_this and not src_name in dst_hash: try: dst_repo.makefolder(src_name) + dst_haschanged = True # Need to refresh list except OfflineImapError, e: self.ui.error(e, exc_info()[2], "Creating folder %s on repository %s" %\ @@ -203,6 +205,7 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin): try: src_repo.makefolder(newsrc_name) + src_haschanged = True # Need to refresh list except OfflineImapError, e: self.ui.error(e, exc_info()[2], "Creating folder %s on repository %s" %\ @@ -211,7 +214,13 @@ class BaseRepository(object, CustomConfig.ConfigHelperMixin): status_repo.makefolder(newsrc_name.replace( src_repo.getsep(), status_repo.getsep())) # Find deleted folders. - # We don't delete folders right now. + # TODO: We don't delete folders right now. + + #Forget old list of cached folders so we get new ones if needed + if src_haschanged: + self.forgetfolders() + if dst_haschanged: + dst_repo.forgetfolders() def startkeepalive(self): """The default implementation will do nothing.""" diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 5ddf5b9..2d2962f 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -311,6 +311,10 @@ class IMAPRepository(BaseRepository): def makefolder(self, foldername): """Create a folder on the IMAP server + This will not update the list cached in :meth:`getfolders`. You + will need to invoke :meth:`forgetfolders` to force new caching + when you are done creating folders yourself. + :param foldername: Full path of the folder to be created.""" #TODO: IMHO this existing commented out code is correct and #should be enabled, but this would change the behavior for diff --git a/offlineimap/repository/Maildir.py b/offlineimap/repository/Maildir.py index 7c3bb1e..ae09486 100644 --- a/offlineimap/repository/Maildir.py +++ b/offlineimap/repository/Maildir.py @@ -72,6 +72,10 @@ class MaildirRepository(BaseRepository): def makefolder(self, foldername): """Create new Maildir folder if necessary + This will not update the list cached in getfolders(). You will + need to invoke :meth:`forgetfolders` to force new caching when + you are done creating folders yourself. + :param foldername: A relative mailbox name. The maildir will be created in self.root+'/'+foldername. All intermediate folder levels will be created if they do not exist yet. 'cur', @@ -108,8 +112,6 @@ class MaildirRepository(BaseRepository): (foldername, subdir)) else: raise - # Invalidate the folder cache - self.folders = None def deletefolder(self, foldername): self.ui.warn("NOT YET IMPLEMENTED: DELETE FOLDER %s" % foldername)