/head: changeset 33

Updated.
This commit is contained in:
jgoerzen 2002-06-21 06:29:12 +01:00
parent f441c907dd
commit 62e840158c
6 changed files with 135 additions and 32 deletions

View File

@ -18,7 +18,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from imapsync import imaplib, imaputil, imapserver, repository, folder from imapsync import imaplib, imaputil, imapserver, repository, folder
import re, getpass, os, os.path import re, os, os.path, imapsync
from ConfigParser import ConfigParser from ConfigParser import ConfigParser
config = ConfigParser() config = ConfigParser()
@ -34,9 +34,10 @@ accounts = accounts.split(",")
server = None server = None
remoterepos = None remoterepos = None
localrepos = None localrepos = None
ui = imapsync.ui.TTY.TTYUI()
for accountname in accounts: for accountname in accounts:
print "Processing account " + accountname ui.acct(accountname)
accountmetadata = os.path.join(metadatadir, accountname) accountmetadata = os.path.join(metadatadir, accountname)
if not os.path.exists(accountmetadata): if not os.path.exists(accountmetadata):
os.mkdir(accountmetadata, 0700) os.mkdir(accountmetadata, 0700)
@ -49,7 +50,7 @@ for accountname in accounts:
if config.has_option(accountname, "remotepass"): if config.has_option(accountname, "remotepass"):
password = config.get(accountname, "remotepass") password = config.get(accountname, "remotepass")
else: else:
password = getpass.getpass("Password for %s: " % accountname) password = ui.getpass(accountname, host, port, user)
ssl = config.getboolean(accountname, "ssl") ssl = config.getboolean(accountname, "ssl")
# Connect to the remote server. # Connect to the remote server.
@ -62,42 +63,40 @@ for accountname in accounts:
# Connect to the local cache. # Connect to the local cache.
statusrepos = repository.LocalStatus.LocalStatusRepository(accountmetadata) statusrepos = repository.LocalStatus.LocalStatusRepository(accountmetadata)
ui.syncfolders(remoterepos, localrepos)
print "Synchronizing folder list..."
remoterepos.syncfoldersto(localrepos) remoterepos.syncfoldersto(localrepos)
print "Done."
for remotefolder in remoterepos.getfolders(): for remotefolder in remoterepos.getfolders():
print "*** SYNCHRONIZING FOLDER %s" % remotefolder.getname()
# Load local folder. # Load local folder.
localfolder = localrepos.getfolder(remotefolder.getname()) localfolder = localrepos.getfolder(remotefolder.getname())
if not localfolder.isuidvalidityok(remotefolder): if not localfolder.isuidvalidityok(remotefolder):
print 'UID validity is a problem for this folder; skipping.' ui.validityproblem(remotefolder)
continue continue
print "Reading local message list...", ui.syncingfolder(remoterepos, remotefolder, localrepos, localfolder)
ui.loadmessagelist(localrepos, localfolder)
localfolder.cachemessagelist() localfolder.cachemessagelist()
print len(localfolder.getmessagelist().keys()), "messages." ui.messagelistloaded(localrepos, localfolder, len(localfolder.getmessagelist().keys()))
# Load remote folder. # Load remote folder.
print "Reading remote message list...", ui.loadmessagelist(remoterepos, remotefolder)
remotefolder.cachemessagelist() remotefolder.cachemessagelist()
print len(remotefolder.getmessagelist().keys()), "messages." ui.messagelistloaded(remoterepos, remotefolder,
len(remotefolder.getmessagelist().keys()))
# Load status folder. # Load status folder.
statusfolder = statusrepos.getfolder(remotefolder.getname()) statusfolder = statusrepos.getfolder(remotefolder.getname())
statusfolder.cachemessagelist() statusfolder.cachemessagelist()
if statusfolder.isnewfolder(): if not statusfolder.isnewfolder():
print "Local status folder is new; ignoring." ui.syncingmessages(localrepos, localfolder, remoterepos, remotefolder)
else:
print "Synchronizing local changes."
localfolder.syncmessagesto(statusfolder, [remotefolder, statusfolder]) localfolder.syncmessagesto(statusfolder, [remotefolder, statusfolder])
# Synchronize remote changes. # Synchronize remote changes.
print "Synchronizing remote to local..." ui.syncingmessages(remoterepos, remotefolder, localrepos, localfolder)
remotefolder.syncmessagesto(localfolder) remotefolder.syncmessagesto(localfolder)
# Make sure the status folder is up-to-date. # Make sure the status folder is up-to-date.
print "Updating local status cache..." ui.syncingmessages(localrepos, localfolder, statusrepos, statusfolder)
localfolder.syncmessagesto(statusfolder) localfolder.syncmessagesto(statusfolder)
statusfolder.save() statusfolder.save()

View File

@ -0,0 +1 @@
import ui, folder, repository

View File

@ -119,8 +119,6 @@ class BaseFolder:
if applyto == None: if applyto == None:
applyto = [dest] applyto = [dest]
print "Pass 1"
# Pass 1 -- Look for messages in self with a negative uid. # Pass 1 -- Look for messages in self with a negative uid.
# These are messages in Maildirs that were not added by us. # These are messages in Maildirs that were not added by us.
# Try to add them to the dests, and once that succeeds, get the # Try to add them to the dests, and once that succeeds, get the
@ -130,7 +128,7 @@ class BaseFolder:
for uid in self.getmessagelist().keys(): for uid in self.getmessagelist().keys():
if uid >= 0: if uid >= 0:
continue continue
print "Uploading new message %d" % uid __main__.ui.copyingmessage(uid, self, applyto)
successobject = None successobject = None
successuid = None successuid = None
message = self.getmessage(uid) message = self.getmessage(uid)
@ -153,8 +151,6 @@ class BaseFolder:
# Did not find any server to take this message. Ignore. # Did not find any server to take this message. Ignore.
pass pass
print "Pass 2"
# Pass 2 -- Look for messages present in self but not in dest. # Pass 2 -- Look for messages present in self but not in dest.
# If any, add them to dest. # If any, add them to dest.
@ -162,7 +158,7 @@ class BaseFolder:
if uid < 0: # Ignore messages that pass 1 missed. if uid < 0: # Ignore messages that pass 1 missed.
continue continue
if not uid in dest.getmessagelist(): if not uid in dest.getmessagelist():
print "Uploading new message %d" % uid __main__.ui.copyingmessage(uid, self, applyto)
message = self.getmessage(uid) message = self.getmessage(uid)
flags = self.getmessageflags(uid) flags = self.getmessageflags(uid)
for object in applyto: for object in applyto:
@ -173,8 +169,6 @@ class BaseFolder:
self.deletemessage(uid) self.deletemessage(uid)
uid = newuid uid = newuid
print "Pass 3"
# Pass 3 -- Look for message present in dest but not in self. # Pass 3 -- Look for message present in dest but not in self.
# If any, delete them. # If any, delete them.
@ -182,7 +176,7 @@ class BaseFolder:
if uid < 0: if uid < 0:
continue continue
if not uid in self.getmessagelist(): if not uid in self.getmessagelist():
print "Deleting message %d" % uid __main__.ui.deletingmessage(uid, applyto)
for object in applyto: for object in applyto:
object.deletemessage(uid) object.deletemessage(uid)
@ -190,8 +184,6 @@ class BaseFolder:
# (except for potential negative uids that couldn't be placed # (except for potential negative uids that couldn't be placed
# anywhere) # anywhere)
print "Pass 4"
# Pass 4 -- Look for any flag identity issues -- set dest messages # Pass 4 -- Look for any flag identity issues -- set dest messages
# to have the same flags that we have here. # to have the same flags that we have here.
@ -203,13 +195,13 @@ class BaseFolder:
addflags = [x for x in selfflags if x not in destflags] addflags = [x for x in selfflags if x not in destflags]
if len(addflags): if len(addflags):
print "Adding flags to %d" % uid, addflags __main__.ui.addingflags(uid, addflags, applyto)
for object in applyto: for object in applyto:
object.addmessageflags(uid, addflags) object.addmessageflags(uid, addflags)
delflags = [x for x in destflags if x not in selfflags] delflags = [x for x in destflags if x not in selfflags]
if len(delflags): if len(delflags):
print "Deleting flags from %d" % uid, delflags __main__.ui.deletingflags(uid, delflags, applyto)
for object in applyto: for object in applyto:
object.deletemessageflags(uid, delflags) object.deletemessageflags(uid, delflags)

View File

@ -0,0 +1,11 @@
import UIBase
from getpass import getpass
class TTYUI(UIBase.UIBase):
def _msg(s, msg):
print msg
def getpass(s, accountname, host, port, user):
return getpass("%s: Password required for %s on %s" %
(accountname, user, host))

View File

@ -0,0 +1,99 @@
# UI base class
# Copyright (C) 2002 John Goerzen
# <jgoerzen@complete.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from imapsync import repository
class UIBase:
################################################## UTILS
def _msg(s, msg):
"""Generic tool called when no other works."""
raise NotImplementedException
def warn(s, msg):
s._msg("WARNING: " + msg)
def getnicename(s, object):
return str(object.__class__).split('.')[-1]
################################################## INPUT
def getpass(s, accountname, host, port, user):
raise NotImplementedException
################################################## MESSAGES
def init_banner(s):
"Display the copyright banner."
s._msg("""imapsync
Copyright (C) 2002 John Goerzen. All rights reserved.
This software comes with NO WARRANTY: see the file COPYING for details.""")
def acct(s, accountname):
s._msg("Processing account %s" % accountname)
def syncfolders(s, srcrepos, destrepos):
s._msg("Copying folder structure from %s to %s" % \
(s.getnicename(srcrepos), s.getnicename(destrepos)))
############################## Folder syncing
def syncingfolder(s, srcrepos, srcfolder, destrepos, destfolder):
"""Called when a folder sync operation is started."""
s._msg("Syncing %s[%s] -> %s[%s]" % (srcrepos, srcfolder,
destrepos, destfolder))
def validityproblem(s, folder):
s.warn("UID validity problem for folder %s; skipping it" % \
folder.getname())
def loadmessagelist(s, repos, folder):
s._msg("Loading message list for %s[%s]" % (s.getnicename(repos),
s.getnicename(folder)))
def messagelistloaded(s, repos, folder, count):
s._msg("Message list for %s[%s] loaded: %d messages" % \
(s.getnicename(repos), s.getnicename(folder), count))
############################## Message syncing
def syncingmessages(s, sr, sf, dr, df):
s._msg("Syncing messages %s[%s] -> %s[%s]" % (s.getnicename(sr),
s.getnicename(sf),
s.getnicename(dr),
s.getnicename(df)))
def copyingmessage(s, uid, src, destlist):
ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ')
s._msg("Copy message %d %s[%s] -> %s" % (uid, s.getnicename(src),
src.getname(), ds))
def deletingmessage(s, uid, destlist):
ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ')
s._msg("Deleting message %d in %s" % (uid, ds))
def addingflags(s, uid, flags, destlist):
ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ')
s._msg("Adding flags %s to message %d on %s" % \
(flags.join(", "), uid, ds))
def deletingflags(s, uid, flags, destlist):
ds = ["%s[%s]" % (s.getnicename(x), x.getname()) for x in destlist].join(', ')
s._msg("Deleting flags %s to message %d on %s" % \
(flags.join(", "), uid, ds))

View File

@ -0,0 +1 @@
import TTY