2002-06-19 06:39:00 +02:00
|
|
|
# Base repository support
|
2006-12-11 06:12:00 +01:00
|
|
|
# Copyright (C) 2002, 2003, 2006 John Goerzen
|
2002-06-19 06:39:00 +02:00
|
|
|
# <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
|
2003-04-16 21:23:45 +02:00
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
2002-06-19 06:39:00 +02:00
|
|
|
#
|
|
|
|
# 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
|
2006-08-12 06:15:55 +02:00
|
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2002-06-19 06:39:00 +02:00
|
|
|
|
2003-04-18 04:18:34 +02:00
|
|
|
from offlineimap import CustomConfig
|
|
|
|
import os.path
|
|
|
|
|
|
|
|
def LoadRepository(name, account, reqtype):
|
|
|
|
from offlineimap.repository.IMAP import IMAPRepository, MappedIMAPRepository
|
|
|
|
from offlineimap.repository.Maildir import MaildirRepository
|
|
|
|
if reqtype == 'remote':
|
|
|
|
# For now, we don't support Maildirs on the remote side.
|
|
|
|
typemap = {'IMAP': IMAPRepository}
|
|
|
|
elif reqtype == 'local':
|
|
|
|
typemap = {'IMAP': MappedIMAPRepository,
|
|
|
|
'Maildir': MaildirRepository}
|
|
|
|
else:
|
|
|
|
raise ValueError, "Request type %s not supported" % reqtype
|
|
|
|
config = account.getconfig()
|
|
|
|
repostype = config.get('Repository ' + name, 'type').strip()
|
|
|
|
return typemap[repostype](name, account)
|
|
|
|
|
|
|
|
class BaseRepository(CustomConfig.ConfigHelperMixin):
|
|
|
|
def __init__(self, reposname, account):
|
|
|
|
self.account = account
|
|
|
|
self.config = account.getconfig()
|
|
|
|
self.name = reposname
|
|
|
|
self.localeval = account.getlocaleval()
|
|
|
|
self.accountname = self.account.getname()
|
|
|
|
self.uiddir = os.path.join(self.config.getmetadatadir(), 'Repository-' + self.name)
|
|
|
|
if not os.path.exists(self.uiddir):
|
|
|
|
os.mkdir(self.uiddir, 0700)
|
|
|
|
self.mapdir = os.path.join(self.uiddir, 'UIDMapping')
|
|
|
|
if not os.path.exists(self.mapdir):
|
|
|
|
os.mkdir(self.mapdir, 0700)
|
|
|
|
self.uiddir = os.path.join(self.uiddir, 'FolderValidity')
|
|
|
|
if not os.path.exists(self.uiddir):
|
|
|
|
os.mkdir(self.uiddir, 0700)
|
|
|
|
|
New restoreatime patch from Ben Kibbey
From: Ben Kibbey
Subject: Re: Removed restoratime from OfflineIMAP
On Wed, May 03, 2006 at 10:08:35PM -0500, John Goerzen wrote:
> Hi Ben,
>
> Thanks for your restoreatime patch.
>
> However, I have received this bug report:
>
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=365933
>
> After looking at the problem, here's what's going on.
>
> The person is using IMAP as the local repository as well.
>
> You really need to move the atime save and restore code from accounts.py
> into the repository/Maildir.py. Then, for any new call you add to the
> Maildir repository (that will be called from outside Maildir.py), you
> need to add a corresponding default function to repository/Base.py, and
> also make sure that on folders (such as IMAP) where atime restoration
> makes no sense, no error is generated.
>
> Let me know if that doesn't make sense to you. If you get it fixed, I'd
> be happy to re-apply it to a future version of OfflineIMAP.
>
> -- John Goerzen
>
Attached is a new diff that should work though not really tested
(v4.0.14). In repository/Base.py restore_atime() will call
self.restore_folder_atimes() only if the folder type is Maildir. Let me
know if it has any more problems.
2006-09-06 03:33:07 +02:00
|
|
|
# The 'restoreatime' config parameter only applies to local Maildir
|
|
|
|
# mailboxes.
|
|
|
|
def restore_atime(self):
|
|
|
|
if self.config.get('Repository ' + self.name, 'type').strip() != \
|
|
|
|
'Maildir':
|
|
|
|
return
|
|
|
|
|
|
|
|
if not self.config.has_option('Repository ' + self.name, 'restoreatime') or not self.config.getboolean('Repository ' + self.name, 'restoreatime'):
|
|
|
|
return
|
|
|
|
|
|
|
|
return self.restore_folder_atimes()
|
|
|
|
|
2003-04-18 04:18:34 +02:00
|
|
|
def holdordropconnections(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def dropconnections(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def getaccount(self):
|
|
|
|
return self.account
|
|
|
|
|
|
|
|
def getname(self):
|
|
|
|
return self.name
|
|
|
|
|
|
|
|
def getuiddir(self):
|
|
|
|
return self.uiddir
|
|
|
|
|
|
|
|
def getmapdir(self):
|
|
|
|
return self.mapdir
|
|
|
|
|
|
|
|
def getaccountname(self):
|
|
|
|
return self.accountname
|
|
|
|
|
|
|
|
def getsection(self):
|
|
|
|
return 'Repository ' + self.name
|
|
|
|
|
|
|
|
def getconfig(self):
|
|
|
|
return self.config
|
|
|
|
|
|
|
|
def getlocaleval(self):
|
|
|
|
return self.account.getlocaleval()
|
|
|
|
|
2002-06-19 06:39:00 +02:00
|
|
|
def getfolders(self):
|
|
|
|
"""Returns a list of ALL folders on this server."""
|
|
|
|
return []
|
2002-06-19 08:16:19 +02:00
|
|
|
|
|
|
|
def getsep(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2002-06-20 04:55:24 +02:00
|
|
|
def makefolder(self, foldername):
|
2002-06-19 08:16:19 +02:00
|
|
|
raise NotImplementedError
|
|
|
|
|
2002-06-20 04:55:24 +02:00
|
|
|
def deletefolder(self, foldername):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def getfolder(self, foldername):
|
2002-06-19 08:16:19 +02:00
|
|
|
raise NotImplementedError
|
2002-06-19 06:39:00 +02:00
|
|
|
|
2002-06-19 08:16:19 +02:00
|
|
|
def syncfoldersto(self, dest):
|
|
|
|
"""Syncs the folders in this repository to those in dest.
|
|
|
|
It does NOT sync the contents of those folders."""
|
|
|
|
src = self
|
|
|
|
srcfolders = src.getfolders()
|
|
|
|
destfolders = dest.getfolders()
|
|
|
|
|
|
|
|
# Create hashes with the names, but convert the source folders
|
|
|
|
# to the dest folder's sep.
|
|
|
|
|
|
|
|
srchash = {}
|
|
|
|
for folder in srcfolders:
|
2002-06-21 08:51:21 +02:00
|
|
|
srchash[folder.getvisiblename().replace(src.getsep(), dest.getsep())] = \
|
2002-06-19 08:16:19 +02:00
|
|
|
folder
|
|
|
|
desthash = {}
|
|
|
|
for folder in destfolders:
|
2002-06-21 08:51:21 +02:00
|
|
|
desthash[folder.getvisiblename()] = folder
|
2002-06-19 08:16:19 +02:00
|
|
|
|
|
|
|
#
|
|
|
|
# Find new folders.
|
|
|
|
#
|
|
|
|
|
|
|
|
for key in srchash.keys():
|
|
|
|
if not key in desthash:
|
|
|
|
dest.makefolder(key)
|
|
|
|
|
|
|
|
#
|
|
|
|
# Find deleted folders.
|
|
|
|
#
|
2002-08-17 03:01:12 +02:00
|
|
|
# We don't delete folders right now.
|
2002-06-19 08:16:19 +02:00
|
|
|
|
2002-08-17 03:01:12 +02:00
|
|
|
#for key in desthash.keys():
|
|
|
|
# if not key in srchash:
|
|
|
|
# dest.deletefolder(key)
|
2002-06-19 08:16:19 +02:00
|
|
|
|
2003-04-18 04:18:34 +02:00
|
|
|
##### Keepalive
|
|
|
|
|
|
|
|
def startkeepalive(self):
|
|
|
|
"""The default implementation will do nothing."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def stopkeepalive(self, abrupt = 0):
|
|
|
|
"""Stop keep alive. If abrupt is 1, stop it but don't bother waiting
|
|
|
|
for the threads to terminate."""
|
|
|
|
pass
|
|
|
|
|