Synchronize newly created folders both ways

This involves several changes at different places:

- syncfoldersto() takes statusfolder as an argument, and returns the
  list of new folders and the list of folders that should be ingnored,
  typically those that were deleted. Warns the user about folders that
  are present only on one side and are not synced.

- syncfoldersto() is called both ways, and on folder creation
  forgetfolders() is used to rebuild the list and take the new creation
  into account. Probably not the most efficient, since it involves
  talking to the IMAP server again, but it will rarely be used anyway.

- Locally created folders are treated separately in the synchronization,
  namely the local messages are uploaded and then the normal sync still
  occurs. If the same folder is created on both sides and contains
  messages on both sides, a two-way sync occurs.
This commit is contained in:
Vincent Beffara 2007-09-02 01:43:15 +01:00
parent ac7c5a47ef
commit b925fd1296
3 changed files with 39 additions and 4 deletions

View File

@ -145,10 +145,19 @@ class AccountSynchronizationMixin:
localrepos = self.localrepos
statusrepos = self.statusrepos
self.ui.syncfolders(remoterepos, localrepos)
remoterepos.syncfoldersto(localrepos)
(remoteignored,remotenew) = remoterepos.syncfoldersto(localrepos,statusrepos)
if len(remotenew):
localrepos.forgetfolders()
(localignored,localnew) = localrepos.syncfoldersto(remoterepos,statusrepos)
if len(localnew):
remoterepos.forgetfolders()
folderthreads = []
for remotefolder in remoterepos.getfolders():
if remotefolder.getvisiblename() in remoteignored:
continue
thread = InstanceLimitedThread(\
instancename = 'FOLDER_' + self.remoterepos.getname(),
target = syncfolder,
@ -233,6 +242,14 @@ def syncfolder(accountname, remoterepos, remotefolder, localrepos,
#
if ((statusfolder.isnewfolder()) and
(len(localfolder.getmessagelist()) > 0) and
(len(remotefolder.getmessagelist()) == 0)):
# This is a locally created folder. Copy its contents to the
# remote folder, and to the StatusFolder.
localfolder.syncmessagesto(statusfolder, [remotefolder, statusfolder])
if not statusfolder.isnewfolder():
# Delete local copies of remote messages. This way,
# if a message's flag is modified locally but it has been

View File

@ -17,6 +17,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from offlineimap import CustomConfig
from offlineimap.ui import UIBase
import os.path
def LoadRepository(name, account, reqtype):
@ -123,7 +124,7 @@ class BaseRepository(CustomConfig.ConfigHelperMixin):
def getfolder(self, foldername):
raise NotImplementedError
def syncfoldersto(self, dest):
def syncfoldersto(self, dest, status):
"""Syncs the folders in this repository to those in dest.
It does NOT sync the contents of those folders."""
src = self
@ -135,6 +136,8 @@ class BaseRepository(CustomConfig.ConfigHelperMixin):
srchash = {}
for folder in srcfolders:
if (folder.getvisiblename()[-2:] == src.getsep() + "."):
continue
srchash[folder.getvisiblename().replace(src.getsep(), dest.getsep())] = \
folder
desthash = {}
@ -145,9 +148,18 @@ class BaseRepository(CustomConfig.ConfigHelperMixin):
# Find new folders.
#
ignoredfolders = []
newfolders = []
for key in srchash.keys():
if not key in desthash:
dest.makefolder(key)
srckey = key.replace(dest.getsep(),src.getsep())
if status.getfolder(key.replace(dest.getsep(),status.getsep())).isnewfolder():
dest.makefolder(key)
newfolders.append(srckey)
else:
UIBase.getglobalui().ignorefolder (key, src, dest)
ignoredfolders.append(srckey)
#
# Find deleted folders.
@ -157,6 +169,8 @@ class BaseRepository(CustomConfig.ConfigHelperMixin):
#for key in desthash.keys():
# if not key in srchash:
# dest.deletefolder(key)
return (ignoredfolders,newfolders)
##### Keepalive

View File

@ -197,7 +197,7 @@ class UIBase:
def syncfolders(s, srcrepos, destrepos):
if s.verbose >= 0:
s._msg("Copying folder structure from %s to %s" % \
s._msg("Copying folder structure between %s and %s" % \
(s.getnicename(srcrepos), s.getnicename(destrepos)))
############################## Folder syncing
@ -218,6 +218,10 @@ class UIBase:
(folder.getname(), folder.getrepository().getname(),
folder.getsaveduidvalidity(), folder.getuidvalidity()))
def ignorefolder(s, foldername, here, there):
s.warn("Folder %s disappeared from %s; skipping it" % \
(foldername, there.getname()))
def loadmessagelist(s, repos, folder):
if s.verbose > 0:
s._msg("Loading message list for %s[%s]" % (s.getnicename(repos),