Merge branch 'next'

Conflicts:
	Changelog.draft.rst
This commit is contained in:
Sebastian Spaeth 2012-01-07 13:17:34 +01:00
commit 05e43b0363
12 changed files with 45 additions and 38 deletions

View File

@ -18,5 +18,3 @@ Changes
Bug Fixes Bug Fixes
--------- ---------
* Fix regression that broke MachineUI

View File

@ -11,6 +11,25 @@ ChangeLog
on releases. And because I'm lazy, it will also be used as a draft for the on releases. And because I'm lazy, it will also be used as a draft for the
releases announces. releases announces.
OfflineIMAP v6.5.1 (2012-01-07) - "Quest for stability"
=======================================================
* Fixed Maildir regression "flagmatchre" not found. (regressed in 6.5.0)
* Have console output go by default to STDOUT and not STDERR (regression
in 6.5.0)
* Fixed MachineUI to urlencode() output lines again, rather than
outputting multi-line items. It's ugly as hell, but it had been that
way for years.
* Remove the old global locking system. We lock only the accounts that
we currently sync, so you can invoke OfflineImap multiple times now as
long as you sync different accounts. This system is compatible with
all releases >= 6.4.0, so don't run older releases simultanous to this
one.
OfflineIMAP v6.5.0 (2012-01-06) OfflineIMAP v6.5.0 (2012-01-06)
=============================== ===============================

View File

@ -1,7 +1,7 @@
__all__ = ['OfflineImap'] __all__ = ['OfflineImap']
__productname__ = 'OfflineIMAP' __productname__ = 'OfflineIMAP'
__version__ = "6.5.0" __version__ = "6.5.1"
__copyright__ = "Copyright 2002-2012 John Goerzen & contributors" __copyright__ = "Copyright 2002-2012 John Goerzen & contributors"
__author__ = "John Goerzen" __author__ = "John Goerzen"
__author_email__= "john@complete.org" __author_email__= "john@complete.org"
@ -9,7 +9,7 @@ __description__ = "Disconnected Universal IMAP Mail Synchronization/Reader Suppo
__license__ = "Licensed under the GNU GPL v2+ (v2 or any later version)" __license__ = "Licensed under the GNU GPL v2+ (v2 or any later version)"
__bigcopyright__ = """%(__productname__)s %(__version__)s __bigcopyright__ = """%(__productname__)s %(__version__)s
%(__license__)s""" % locals() %(__license__)s""" % locals()
__homepage__ = "http://github.com/nicolas33/offlineimap" __homepage__ = "http://offlineimap.org"
banner = __bigcopyright__ banner = __bigcopyright__

View File

@ -191,7 +191,6 @@ class SyncableAccount(Account):
def lock(self): def lock(self):
"""Lock the account, throwing an exception if it is locked already""" """Lock the account, throwing an exception if it is locked already"""
# Take a new-style per-account lock
self._lockfd = open(self._lockfilepath, 'w') self._lockfd = open(self._lockfilepath, 'w')
try: try:
fcntl.lockf(self._lockfd, fcntl.LOCK_EX|fcntl.LOCK_NB) fcntl.lockf(self._lockfd, fcntl.LOCK_EX|fcntl.LOCK_NB)

View File

@ -68,9 +68,10 @@ class IMAPFolder(BaseFolder):
def getuidvalidity(self): def getuidvalidity(self):
imapobj = self.imapserver.acquireconnection() imapobj = self.imapserver.acquireconnection()
try: try:
# Primes untagged_responses # SELECT receives UIDVALIDITY response
self.selectro(imapobj) self.selectro(imapobj)
return long(imapobj._get_untagged_response('UIDVALIDITY', True)[0]) typ, uidval = imapobj.response('UIDVALIDITY')
return long(uidval[0])
finally: finally:
self.imapserver.releaseconnection(imapobj) self.imapserver.releaseconnection(imapobj)
@ -563,14 +564,15 @@ class IMAPFolder(BaseFolder):
# get the new UID. Test for APPENDUID response even if the # get the new UID. Test for APPENDUID response even if the
# server claims to not support it, as e.g. Gmail does :-( # server claims to not support it, as e.g. Gmail does :-(
if use_uidplus or imapobj._get_untagged_response('APPENDUID', True): if use_uidplus or imapobj._get_untagged_response('APPENDUID', True):
# get the new UID from the APPENDUID response, it could look like # get new UID from the APPENDUID response, it could look
# OK [APPENDUID 38505 3955] APPEND completed # like OK [APPENDUID 38505 3955] APPEND completed with
# with 38505 bein folder UIDvalidity and 3955 the new UID # 38505 bein folder UIDvalidity and 3955 the new UID
if not imapobj._get_untagged_response('APPENDUID', True): typ, resp = imapobj.response('APPENDUID')
if resp == [None]:
self.ui.warn("Server supports UIDPLUS but got no APPENDUID " self.ui.warn("Server supports UIDPLUS but got no APPENDUID "
"appending a message.") "appending a message.")
return 0 return 0
uid = long(imapobj._get_untagged_response('APPENDUID')[-1].split(' ')[1]) uid = long(resp[-1].split(' ')[1])
else: else:
# we don't support UIDPLUS # we don't support UIDPLUS

View File

@ -298,7 +298,7 @@ class MaildirFolder(BaseFolder):
# Flags have actually changed, construct new filename # Flags have actually changed, construct new filename
# Strip off existing infostring (preserving small letter flags that # Strip off existing infostring (preserving small letter flags that
# dovecot uses) # dovecot uses)
infomatch = self.flagmatchre.search(filename) infomatch = self.re_flagmatch.search(filename)
if infomatch: if infomatch:
filename = filename[:-len(infomatch.group())] #strip off filename = filename[:-len(infomatch.group())] #strip off
infostr = '%s2,%s' % (self.infosep, ''.join(sorted(flags))) infostr = '%s2,%s' % (self.infosep, ''.join(sorted(flags)))

View File

@ -1,6 +1,5 @@
# Base folder support # Base folder support
# Copyright (C) 2002 John Goerzen # Copyright (C) 2002-2012 John Goerzen & contributors
# <jgoerzen@complete.org>
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -15,7 +14,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from __future__ import with_statement # needed for python 2.5
from threading import Lock from threading import Lock
from IMAP import IMAPFolder from IMAP import IMAPFolder
import os.path import os.path

View File

@ -15,7 +15,6 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from __future__ import with_statement # needed for python 2.5
from offlineimap import imaplibutil, imaputil, threadutil, OfflineImapError from offlineimap import imaplibutil, imaputil, threadutil, OfflineImapError
from offlineimap.ui import getglobalui from offlineimap.ui import getglobalui
from threading import Lock, BoundedSemaphore, Thread, Event, currentThread from threading import Lock, BoundedSemaphore, Thread, Event, currentThread

View File

@ -23,10 +23,6 @@ import signal
import socket import socket
import logging import logging
from optparse import OptionParser from optparse import OptionParser
try:
import fcntl
except ImportError:
pass #it's OK
import offlineimap import offlineimap
from offlineimap import accounts, threadutil, syncmaster from offlineimap import accounts, threadutil, syncmaster
from offlineimap.error import OfflineImapError from offlineimap.error import OfflineImapError
@ -340,18 +336,6 @@ class OfflineImap:
#various initializations that need to be performed: #various initializations that need to be performed:
offlineimap.mbnames.init(self.config, syncaccounts) offlineimap.mbnames.init(self.config, syncaccounts)
#TODO: keep legacy lock for a few versions, then remove.
self._legacy_lock = open(self.config.getmetadatadir() + "/lock",
'w')
try:
fcntl.lockf(self._legacy_lock, fcntl.LOCK_EX|fcntl.LOCK_NB)
except NameError:
#fcntl not available (Windows), disable file locking... :(
pass
except IOError:
raise OfflineImapError("Could not take global lock.",
OfflineImapError.ERROR.REPO)
if options.singlethreading: if options.singlethreading:
#singlethreaded #singlethreaded
self.sync_singlethreaded(syncaccounts) self.sync_singlethreaded(syncaccounts)

View File

@ -15,7 +15,6 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from __future__ import with_statement # needed for python 2.5
from threading import RLock, currentThread, Lock, Event from threading import RLock, currentThread, Lock, Event
from thread import get_ident # python < 2.6 support from thread import get_ident # python < 2.6 support
from collections import deque from collections import deque

View File

@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from urllib import urlencode
import sys import sys
import time import time
import logging import logging
@ -23,15 +23,24 @@ import offlineimap
protocol = '7.0.0' protocol = '7.0.0'
class MachineLogFormatter(logging.Formatter):
"""urlencodes any outputted line, to avoid multi-line output"""
def format(self, record):
# urlencode the "mesg" attribute and append to regular line...
line = super(MachineLogFormatter, self).format(record)
return line + urlencode([('', record.mesg)])[1:]
class MachineUI(UIBase): class MachineUI(UIBase):
def __init__(self, config, loglevel = logging.INFO): def __init__(self, config, loglevel = logging.INFO):
super(MachineUI, self).__init__(config, loglevel) super(MachineUI, self).__init__(config, loglevel)
self._log_con_handler.createLock() self._log_con_handler.createLock()
"""lock needed to block on password input""" """lock needed to block on password input"""
# Set up the formatter that urlencodes the strings...
self._log_con_handler.setFormatter(MachineLogFormatter())
def _printData(self, command, msg): def _printData(self, command, msg):
self.logger.info("%s:%s:%s:%s" % ( self.logger.info("%s:%s:%s" % (
'msg', command, currentThread().getName(), msg)) 'msg', command, currentThread().getName()), extra={'mesg': msg})
def _msg(s, msg): def _msg(s, msg):
s._printData('_display', msg) s._printData('_display', msg)

View File

@ -69,7 +69,7 @@ class UIBase(object):
Sets up things and adds them to self.logger. Sets up things and adds them to self.logger.
:returns: The logging.Handler() for console output""" :returns: The logging.Handler() for console output"""
# create console handler with a higher log level # create console handler with a higher log level
ch = logging.StreamHandler() ch = logging.StreamHandler(sys.stdout)
#ch.setLevel(logging.DEBUG) #ch.setLevel(logging.DEBUG)
# create formatter and add it to the handlers # create formatter and add it to the handlers
self.formatter = logging.Formatter("%(message)s") self.formatter = logging.Formatter("%(message)s")