Prevent modifications on a folder level to occur in dry-run

Prevent savemessage(), and savemessageflags() to occur in dryrun mode in
all backends. Still need to protect against deletemessage().

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This commit is contained in:
Sebastian Spaeth 2011-09-16 11:44:50 +02:00
parent b6807355b5
commit 5ef69e95c0
7 changed files with 81 additions and 7 deletions

View File

@ -208,6 +208,10 @@ class BaseFolder(object):
If the uid is > 0, the backend should set the uid to this, if it can. If the uid is > 0, the backend should set the uid to this, if it can.
If it cannot set the uid to that, it will save it anyway. If it cannot set the uid to that, it will save it anyway.
It will return the uid assigned in any case. It will return the uid assigned in any case.
Note that savemessage() does not check against dryrun settings,
so you need to ensure that savemessage is never called in a
dryrun mode.
""" """
raise NotImplementedException raise NotImplementedException
@ -220,27 +224,48 @@ class BaseFolder(object):
raise NotImplementedException raise NotImplementedException
def savemessageflags(self, uid, flags): def savemessageflags(self, uid, flags):
"""Sets the specified message's flags to the given set.""" """Sets the specified message's flags to the given set.
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode."""
raise NotImplementedException raise NotImplementedException
def addmessageflags(self, uid, flags): def addmessageflags(self, uid, flags):
"""Adds the specified flags to the message's flag set. If a given """Adds the specified flags to the message's flag set. If a given
flag is already present, it will not be duplicated. flag is already present, it will not be duplicated.
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode.
:param flags: A set() of flags""" :param flags: A set() of flags"""
newflags = self.getmessageflags(uid) | flags newflags = self.getmessageflags(uid) | flags
self.savemessageflags(uid, newflags) self.savemessageflags(uid, newflags)
def addmessagesflags(self, uidlist, flags): def addmessagesflags(self, uidlist, flags):
"""
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode."""
for uid in uidlist: for uid in uidlist:
self.addmessageflags(uid, flags) self.addmessageflags(uid, flags)
def deletemessageflags(self, uid, flags): def deletemessageflags(self, uid, flags):
"""Removes each flag given from the message's flag set. If a given """Removes each flag given from the message's flag set. If a given
flag is already removed, no action will be taken for that flag.""" flag is already removed, no action will be taken for that flag.
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode."""
newflags = self.getmessageflags(uid) - flags newflags = self.getmessageflags(uid) - flags
self.savemessageflags(uid, newflags) self.savemessageflags(uid, newflags)
def deletemessagesflags(self, uidlist, flags): def deletemessagesflags(self, uidlist, flags):
"""
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode."""
for uid in uidlist: for uid in uidlist:
self.deletemessageflags(uid, flags) self.deletemessageflags(uid, flags)
@ -345,6 +370,10 @@ class BaseFolder(object):
statusfolder.uidexists(uid), statusfolder.uidexists(uid),
self.getmessageuidlist()) self.getmessageuidlist())
num_to_copy = len(copylist) num_to_copy = len(copylist)
if num_to_copy and self.repository.account.dryrun:
self.ui.info("[DRYRUN] Copy {} messages from {}[{}] to {}".format(
num_to_copy, self, self.repository, dstfolder.repository))
return
for num, uid in enumerate(copylist): for num, uid in enumerate(copylist):
# bail out on CTRL-C or SIGTERM # bail out on CTRL-C or SIGTERM
if offlineimap.accounts.Account.abort_NOW_signal.is_set(): if offlineimap.accounts.Account.abort_NOW_signal.is_set():
@ -422,11 +451,15 @@ class BaseFolder(object):
for flag, uids in addflaglist.items(): for flag, uids in addflaglist.items():
self.ui.addingflags(uids, flag, dstfolder) self.ui.addingflags(uids, flag, dstfolder)
if self.repository.account.dryrun:
continue #don't actually add in a dryrun
dstfolder.addmessagesflags(uids, set(flag)) dstfolder.addmessagesflags(uids, set(flag))
statusfolder.addmessagesflags(uids, set(flag)) statusfolder.addmessagesflags(uids, set(flag))
for flag,uids in delflaglist.items(): for flag,uids in delflaglist.items():
self.ui.deletingflags(uids, flag, dstfolder) self.ui.deletingflags(uids, flag, dstfolder)
if self.repository.account.dryrun:
continue #don't actually remove in a dryrun
dstfolder.deletemessagesflags(uids, set(flag)) dstfolder.deletemessagesflags(uids, set(flag))
statusfolder.deletemessagesflags(uids, set(flag)) statusfolder.deletemessagesflags(uids, set(flag))

View File

@ -488,12 +488,16 @@ class IMAPFolder(BaseFolder):
This function will update the self.messagelist dict to contain This function will update the self.messagelist dict to contain
the new message after sucessfully saving it. the new message after sucessfully saving it.
See folder/Base for details. Note that savemessage() does not
check against dryrun settings, so you need to ensure that
savemessage is never called in a dryrun mode.
:param rtime: A timestamp to be used as the mail date :param rtime: A timestamp to be used as the mail date
:returns: the UID of the new message as assigned by the server. If the :returns: the UID of the new message as assigned by the server. If the
message is saved, but it's UID can not be found, it will message is saved, but it's UID can not be found, it will
return 0. If the message can't be written (folder is return 0. If the message can't be written (folder is
read-only for example) it will return -1.""" read-only for example) it will return -1."""
self.ui.debug('imap', 'savemessage: called') self.ui.savemessage('imap', uid, flags, self)
# already have it, just save modified flags # already have it, just save modified flags
if uid > 0 and self.uidexists(uid): if uid > 0 and self.uidexists(uid):
@ -611,7 +615,11 @@ class IMAPFolder(BaseFolder):
return uid return uid
def savemessageflags(self, uid, flags): def savemessageflags(self, uid, flags):
"""Change a message's flags to `flags`.""" """Change a message's flags to `flags`.
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode."""
imapobj = self.imapserver.acquireconnection() imapobj = self.imapserver.acquireconnection()
try: try:
try: try:

View File

@ -111,6 +111,11 @@ class LocalStatusFolder(BaseFolder):
return self.messagelist return self.messagelist
def savemessage(self, uid, content, flags, rtime): def savemessage(self, uid, content, flags, rtime):
"""Writes a new message, with the specified uid.
See folder/Base for detail. Note that savemessage() does not
check against dryrun settings, so you need to ensure that
savemessage is never called in a dryrun mode."""
if uid < 0: if uid < 0:
# We cannot assign a uid. # We cannot assign a uid.
return uid return uid

View File

@ -216,6 +216,11 @@ class LocalStatusSQLiteFolder(LocalStatusFolder):
# assert False,"getmessageflags() called on non-existing message" # assert False,"getmessageflags() called on non-existing message"
def savemessage(self, uid, content, flags, rtime): def savemessage(self, uid, content, flags, rtime):
"""Writes a new message, with the specified uid.
See folder/Base for detail. Note that savemessage() does not
check against dryrun settings, so you need to ensure that
savemessage is never called in a dryrun mode."""
if uid < 0: if uid < 0:
# We cannot assign a uid. # We cannot assign a uid.
return uid return uid

View File

@ -237,13 +237,18 @@ class MaildirFolder(BaseFolder):
uid, self._foldermd5, self.infosep, ''.join(sorted(flags))) uid, self._foldermd5, self.infosep, ''.join(sorted(flags)))
def savemessage(self, uid, content, flags, rtime): def savemessage(self, uid, content, flags, rtime):
"""Writes a new message, with the specified uid.
See folder/Base for detail. Note that savemessage() does not
check against dryrun settings, so you need to ensure that
savemessage is never called in a dryrun mode."""
# This function only ever saves to tmp/, # This function only ever saves to tmp/,
# but it calls savemessageflags() to actually save to cur/ or new/. # but it calls savemessageflags() to actually save to cur/ or new/.
self.ui.debug('maildir', 'savemessage: called to write with flags %s ' self.ui.savemessage('maildir', uid, flags, self)
'and content %s' % (repr(flags), repr(content)))
if uid < 0: if uid < 0:
# We cannot assign a new uid. # We cannot assign a new uid.
return uid return uid
if uid in self.messagelist: if uid in self.messagelist:
# We already have it, just update flags. # We already have it, just update flags.
self.savemessageflags(uid, flags) self.savemessageflags(uid, flags)
@ -291,8 +296,11 @@ class MaildirFolder(BaseFolder):
"""Sets the specified message's flags to the given set. """Sets the specified message's flags to the given set.
This function moves the message to the cur or new subdir, This function moves the message to the cur or new subdir,
depending on the 'S'een flag.""" depending on the 'S'een flag.
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode."""
oldfilename = self.messagelist[uid]['filename'] oldfilename = self.messagelist[uid]['filename']
dir_prefix, filename = os.path.split(oldfilename) dir_prefix, filename = os.path.split(oldfilename)
# If a message has been seen, it goes into 'cur' # If a message has been seen, it goes into 'cur'

View File

@ -184,7 +184,12 @@ class MappedIMAPFolder(IMAPFolder):
If the uid is > 0, the backend should set the uid to this, if it can. If the uid is > 0, the backend should set the uid to this, if it can.
If it cannot set the uid to that, it will save it anyway. If it cannot set the uid to that, it will save it anyway.
It will return the uid assigned in any case. It will return the uid assigned in any case.
See folder/Base for details. Note that savemessage() does not
check against dryrun settings, so you need to ensure that
savemessage is never called in a dryrun mode.
""" """
self.ui.savemessage('imap', uid, flags, self)
# Mapped UID instances require the source to already have a # Mapped UID instances require the source to already have a
# positive UID, so simply return here. # positive UID, so simply return here.
if uid < 0: if uid < 0:
@ -217,6 +222,11 @@ class MappedIMAPFolder(IMAPFolder):
return None return None
def savemessageflags(self, uid, flags): def savemessageflags(self, uid, flags):
"""
Note that this function does not check against dryrun settings,
so you need to ensure that it is never called in a
dryrun mode."""
self._mb.savemessageflags(self.r2l[uid], flags) self._mb.savemessageflags(self.r2l[uid], flags)
def addmessageflags(self, uid, flags): def addmessageflags(self, uid, flags):

View File

@ -408,6 +408,11 @@ class UIBase(object):
if conn: #release any existing IMAP connection if conn: #release any existing IMAP connection
repository.imapserver.close() repository.imapserver.close()
def savemessage(self, debugtype, uid, flags, folder):
"""Output a log line stating that we save a msg"""
self.debug(debugtype, "Write mail '%s:%d' with flags %s" %
(folder, uid, repr(flags)))
################################################## Threads ################################################## Threads
def getThreadDebugLog(self, thread): def getThreadDebugLog(self, thread):