Merge branch 'next'
Conflicts: Changelog.draft.rst
This commit is contained in:
commit
05e43b0363
@ -18,5 +18,3 @@ Changes
|
|||||||
|
|
||||||
Bug Fixes
|
Bug Fixes
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* Fix regression that broke MachineUI
|
|
||||||
|
@ -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)
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
|
@ -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__
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)))
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user