accounts.py: Use ui.error when raising exceptions
Rather than using ui.warn, use ui.error() which outputs Exceptions to the error log, saving them to a stack, so we get notified again at the end of the sync run. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de> Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
f937a86571
commit
b47bc44783
@ -13,6 +13,10 @@ others.
|
|||||||
New Features
|
New Features
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
* When a message upload/download fails, we do not abort the whole folder
|
||||||
|
synchronization, but only skip that message, informing the user at the
|
||||||
|
end of the sync run.
|
||||||
|
|
||||||
Changes
|
Changes
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ from offlineimap.threadutil import InstanceLimitedThread
|
|||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from threading import Event
|
from threading import Event
|
||||||
import os
|
import os
|
||||||
|
from sys import exc_info
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
def getaccountlist(customconfig):
|
def getaccountlist(customconfig):
|
||||||
@ -178,16 +179,16 @@ class SyncableAccount(Account):
|
|||||||
except (KeyboardInterrupt, SystemExit):
|
except (KeyboardInterrupt, SystemExit):
|
||||||
raise
|
raise
|
||||||
except OfflineImapError, e:
|
except OfflineImapError, e:
|
||||||
self.ui.warn(e.reason)
|
|
||||||
# Stop looping and bubble up Exception if needed.
|
# Stop looping and bubble up Exception if needed.
|
||||||
if e.severity >= OfflineImapError.ERROR.REPO:
|
if e.severity >= OfflineImapError.ERROR.REPO:
|
||||||
if looping:
|
if looping:
|
||||||
looping -= 1
|
looping -= 1
|
||||||
if e.severity >= OfflineImapError.ERROR.CRITICAL:
|
if e.severity >= OfflineImapError.ERROR.CRITICAL:
|
||||||
raise
|
raise
|
||||||
except:
|
self.ui.error(e, exc_info()[2])
|
||||||
self.ui.warn("Error occured attempting to sync account "\
|
except Exception, e:
|
||||||
"'%s':\n%s"% (self, traceback.format_exc()))
|
self.ui.error(e, msg = "While attempting to sync "
|
||||||
|
"account %s:\n %s"% (self, traceback.format_exc()))
|
||||||
else:
|
else:
|
||||||
# after success sync, reset the looping counter to 3
|
# after success sync, reset the looping counter to 3
|
||||||
if self.refreshperiod:
|
if self.refreshperiod:
|
||||||
@ -276,8 +277,10 @@ class SyncableAccount(Account):
|
|||||||
r = p.communicate()
|
r = p.communicate()
|
||||||
self.ui.callhook("Hook stdout: %s\nHook stderr:%s\n" % r)
|
self.ui.callhook("Hook stdout: %s\nHook stderr:%s\n" % r)
|
||||||
self.ui.callhook("Hook return code: %d" % p.returncode)
|
self.ui.callhook("Hook return code: %d" % p.returncode)
|
||||||
except:
|
except (KeyboardInterrupt, SystemExit):
|
||||||
self.ui.warn("Exception occured while calling hook")
|
raise
|
||||||
|
except Exception, e:
|
||||||
|
self.ui.error(e, exc_info()[2], msg = "Calling hook")
|
||||||
|
|
||||||
|
|
||||||
def syncfolder(accountname, remoterepos, remotefolder, localrepos,
|
def syncfolder(accountname, remoterepos, remotefolder, localrepos,
|
||||||
@ -366,9 +369,9 @@ def syncfolder(accountname, remoterepos, remotefolder, localrepos,
|
|||||||
if e.severity > OfflineImapError.ERROR.FOLDER:
|
if e.severity > OfflineImapError.ERROR.FOLDER:
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
ui.warn("Aborting folder sync '%s' [acc: '%s']\nReason was: %s" %\
|
ui.error(e, exc_info()[2], msg = "Aborting folder sync '%s' "
|
||||||
(localfolder.name, accountname, e.reason))
|
"[acc: '%s']" % (localfolder, accountname))
|
||||||
except:
|
except Exception, e:
|
||||||
ui.warn("ERROR in syncfolder for %s folder %s: %s" % \
|
ui.error(e, msg = "ERROR in syncfolder for %s folder %s: %s" % \
|
||||||
(accountname,remotefolder.getvisiblename(),
|
(accountname,remotefolder.getvisiblename(),
|
||||||
traceback.format_exc()))
|
traceback.format_exc()))
|
||||||
|
@ -19,6 +19,7 @@ from offlineimap import threadutil
|
|||||||
from offlineimap.ui import getglobalui
|
from offlineimap.ui import getglobalui
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
from sys import exc_info
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
class BaseFolder(object):
|
class BaseFolder(object):
|
||||||
@ -229,62 +230,55 @@ class BaseFolder(object):
|
|||||||
# synced to the status cache. This is only a problem with
|
# synced to the status cache. This is only a problem with
|
||||||
# self.getmessage(). So, don't call self.getmessage unless
|
# self.getmessage(). So, don't call self.getmessage unless
|
||||||
# really needed.
|
# really needed.
|
||||||
try:
|
if register: # output that we start a new thread
|
||||||
if register: # output that we start a new thread
|
self.ui.registerthread(self.getaccountname())
|
||||||
self.ui.registerthread(self.getaccountname())
|
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
flags = self.getmessageflags(uid)
|
flags = self.getmessageflags(uid)
|
||||||
rtime = self.getmessagetime(uid)
|
rtime = self.getmessagetime(uid)
|
||||||
|
|
||||||
if uid > 0 and dstfolder.uidexists(uid):
|
if uid > 0 and dstfolder.uidexists(uid):
|
||||||
# dst has message with that UID already, only update status
|
# dst has message with that UID already, only update status
|
||||||
statusfolder.savemessage(uid, None, flags, rtime)
|
statusfolder.savemessage(uid, None, flags, rtime)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.ui.copyingmessage(uid, self, [dstfolder])
|
self.ui.copyingmessage(uid, self, [dstfolder])
|
||||||
# If any of the destinations actually stores the message body,
|
# If any of the destinations actually stores the message body,
|
||||||
# load it up.
|
# load it up.
|
||||||
if dstfolder.storesmessages():
|
if dstfolder.storesmessages():
|
||||||
|
message = self.getmessage(uid)
|
||||||
message = self.getmessage(uid)
|
#Succeeded? -> IMAP actually assigned a UID. If newid
|
||||||
#Succeeded? -> IMAP actually assigned a UID. If newid
|
#remained negative, no server was willing to assign us an
|
||||||
#remained negative, no server was willing to assign us an
|
#UID. If newid is 0, saving succeeded, but we could not
|
||||||
#UID. If newid is 0, saving succeeded, but we could not
|
#retrieve the new UID. Ignore message in this case.
|
||||||
#retrieve the new UID. Ignore message in this case.
|
newuid = dstfolder.savemessage(uid, message, flags, rtime)
|
||||||
newuid = dstfolder.savemessage(uid, message, flags, rtime)
|
if newuid > 0:
|
||||||
if newuid > 0:
|
if newuid != uid:
|
||||||
if newuid != uid:
|
# Got new UID, change the local uid.
|
||||||
# Got new UID, change the local uid.
|
#TODO: Maildir could do this with a rename rather than
|
||||||
#TODO: Maildir could do this with a rename rather than
|
#load/save/del operation, IMPLEMENT a changeuid()
|
||||||
#load/save/del operation, IMPLEMENT a changeuid()
|
#function or so.
|
||||||
#function or so.
|
self.savemessage(newuid, message, flags, rtime)
|
||||||
self.savemessage(newuid, message, flags, rtime)
|
|
||||||
self.deletemessage(uid)
|
|
||||||
uid = newuid
|
|
||||||
# Save uploaded status in the statusfolder
|
|
||||||
statusfolder.savemessage(uid, message, flags, rtime)
|
|
||||||
elif newuid == 0:
|
|
||||||
# Message was stored to dstfolder, but we can't find it's UID
|
|
||||||
# This means we can't link current message to the one created
|
|
||||||
# in IMAP. So we just delete local message and on next run
|
|
||||||
# we'll sync it back
|
|
||||||
# XXX This could cause infinite loop on syncing between two
|
|
||||||
# IMAP servers ...
|
|
||||||
self.deletemessage(uid)
|
self.deletemessage(uid)
|
||||||
else:
|
uid = newuid
|
||||||
raise UserWarning("Trying to save msg (uid %d) on folder "
|
# Save uploaded status in the statusfolder
|
||||||
"%s returned invalid uid %d" % \
|
statusfolder.savemessage(uid, message, flags, rtime)
|
||||||
(uid,
|
|
||||||
dstfolder.getvisiblename(),
|
elif newuid == 0:
|
||||||
newuid))
|
# Message was stored to dstfolder, but we can't find it's UID
|
||||||
except (KeyboardInterrupt):
|
# This means we can't link current message to the one created
|
||||||
raise
|
# in IMAP. So we just delete local message and on next run
|
||||||
except:
|
# we'll sync it back
|
||||||
self.ui.warn("ERROR attempting to copy message " + str(uid) \
|
# XXX This could cause infinite loop on syncing between two
|
||||||
+ " for account " + self.getaccountname() + ":" \
|
# IMAP servers ...
|
||||||
+ traceback.format_exc())
|
self.deletemessage(uid)
|
||||||
raise
|
else:
|
||||||
|
raise OfflineImapError("Trying to save msg (uid %d) on folder "
|
||||||
|
"%s returned invalid uid %d" % \
|
||||||
|
(uid,
|
||||||
|
dstfolder.getvisiblename(),
|
||||||
|
newuid),
|
||||||
|
OfflineImapError.ERROR.MESSAGE)
|
||||||
|
|
||||||
def syncmessagesto_copy(self, dstfolder, statusfolder):
|
def syncmessagesto_copy(self, dstfolder, statusfolder):
|
||||||
"""Pass1: Copy locally existing messages not on the other side
|
"""Pass1: Copy locally existing messages not on the other side
|
||||||
@ -303,20 +297,30 @@ class BaseFolder(object):
|
|||||||
statusfolder.uidexists(uid),
|
statusfolder.uidexists(uid),
|
||||||
self.getmessageuidlist())
|
self.getmessageuidlist())
|
||||||
for uid in copylist:
|
for uid in copylist:
|
||||||
if self.suggeststhreads():
|
try:
|
||||||
self.waitforthread()
|
if self.suggeststhreads():
|
||||||
thread = threadutil.InstanceLimitedThread(\
|
self.waitforthread()
|
||||||
self.getcopyinstancelimit(),
|
thread = threadutil.InstanceLimitedThread(\
|
||||||
target = self.copymessageto,
|
self.getcopyinstancelimit(),
|
||||||
name = "Copy message %d from %s" % (uid,
|
target = self.copymessageto,
|
||||||
|
name = "Copy message %d from %s" % (uid,
|
||||||
self.getvisiblename()),
|
self.getvisiblename()),
|
||||||
args = (uid, dstfolder, statusfolder))
|
args = (uid, dstfolder, statusfolder))
|
||||||
thread.setDaemon(1)
|
thread.setDaemon(1)
|
||||||
thread.start()
|
thread.start()
|
||||||
threads.append(thread)
|
threads.append(thread)
|
||||||
else:
|
else:
|
||||||
self.copymessageto(uid, dstfolder, statusfolder, register = 0)
|
self.copymessageto(uid, dstfolder, statusfolder,
|
||||||
|
register = 0)
|
||||||
|
except OfflineImapError, e:
|
||||||
|
if e.severity > OfflineImapError.ERROR.Message:
|
||||||
|
raise # buble severe errors up
|
||||||
|
self.ui.error(e, exc_info()[2])
|
||||||
|
except Exception, e:
|
||||||
|
self.ui.error(e, "Copying message %s [acc: %s]:\n %s" %\
|
||||||
|
(uid, self.getaccountname(),
|
||||||
|
traceback.format_exc()))
|
||||||
|
raise #raise on unknown errors, so we can fix those
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
thread.join()
|
thread.join()
|
||||||
|
|
||||||
@ -421,8 +425,12 @@ class BaseFolder(object):
|
|||||||
action(dstfolder, statusfolder)
|
action(dstfolder, statusfolder)
|
||||||
except (KeyboardInterrupt):
|
except (KeyboardInterrupt):
|
||||||
raise
|
raise
|
||||||
except:
|
except OfflineImap, e:
|
||||||
self.ui.warn("ERROR attempting to sync flags " \
|
if e.severity > OfflineImapError.ERROR.FOLDER:
|
||||||
+ "for account " + self.getaccountname() \
|
raise
|
||||||
+ ":" + traceback.format_exc())
|
self.ui.error(e, exc_info()[2])
|
||||||
raise
|
except Exception, e:
|
||||||
|
self.ui.error(e, msg = "ERROR attempting to sync folder %s "
|
||||||
|
"[acc: %s]:\n %s" (self, self.getaccountname(),
|
||||||
|
traceback.format_exc()))
|
||||||
|
raise # raise unknown Exceptions so we can fix them
|
||||||
|
Loading…
Reference in New Issue
Block a user