]>
code.delx.au - offlineimap/blob - offlineimap/repository/Base.py
1 # Base repository support
2 # Copyright (C) 2002-2007 John Goerzen
3 # <jgoerzen@complete.org>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 from offlineimap
import CustomConfig
20 from offlineimap
.ui
import UIBase
23 def LoadRepository(name
, account
, reqtype
):
24 from offlineimap
.repository
.Gmail
import GmailRepository
25 from offlineimap
.repository
.IMAP
import IMAPRepository
, MappedIMAPRepository
26 from offlineimap
.repository
.Maildir
import MaildirRepository
27 if reqtype
== 'remote':
28 # For now, we don't support Maildirs on the remote side.
29 typemap
= {'IMAP': IMAPRepository
,
30 'Gmail': GmailRepository
}
31 elif reqtype
== 'local':
32 typemap
= {'IMAP': MappedIMAPRepository
,
33 'Maildir': MaildirRepository
}
35 raise ValueError, "Request type %s not supported" % reqtype
36 config
= account
.getconfig()
37 repostype
= config
.get('Repository ' + name
, 'type').strip()
38 return typemap
[repostype
](name
, account
)
40 class BaseRepository(CustomConfig
.ConfigHelperMixin
):
41 def __init__(self
, reposname
, account
):
42 self
.account
= account
43 self
.config
= account
.getconfig()
45 self
.localeval
= account
.getlocaleval()
46 self
.accountname
= self
.account
.getname()
47 self
.uiddir
= os
.path
.join(self
.config
.getmetadatadir(), 'Repository-' + self
.name
)
48 if not os
.path
.exists(self
.uiddir
):
49 os
.mkdir(self
.uiddir
, 0700)
50 self
.mapdir
= os
.path
.join(self
.uiddir
, 'UIDMapping')
51 if not os
.path
.exists(self
.mapdir
):
52 os
.mkdir(self
.mapdir
, 0700)
53 self
.uiddir
= os
.path
.join(self
.uiddir
, 'FolderValidity')
54 if not os
.path
.exists(self
.uiddir
):
55 os
.mkdir(self
.uiddir
, 0700)
57 # The 'restoreatime' config parameter only applies to local Maildir
59 def restore_atime(self
):
60 if self
.config
.get('Repository ' + self
.name
, 'type').strip() != \
64 if not self
.config
.has_option('Repository ' + self
.name
, 'restoreatime') or not self
.config
.getboolean('Repository ' + self
.name
, 'restoreatime'):
67 return self
.restore_folder_atimes()
70 """Establish a connection to the remote, if necessary. This exists
71 so that IMAP connections can all be established up front, gathering
72 passwords as needed. It was added in order to support the
73 error recovery -- we need to connect first outside of the error
74 trap in order to validate the password, and that's the point of
78 def holdordropconnections(self
):
81 def dropconnections(self
):
96 def getaccountname(self
):
97 return self
.accountname
100 return 'Repository ' + self
.name
105 def getlocaleval(self
):
106 return self
.account
.getlocaleval()
108 def getfolders(self
):
109 """Returns a list of ALL folders on this server."""
112 def forgetfolders(self
):
113 """Forgets the cached list of folders, if any. Useful to run
118 raise NotImplementedError
120 def makefolder(self
, foldername
):
121 raise NotImplementedError
123 def deletefolder(self
, foldername
):
124 raise NotImplementedError
126 def getfolder(self
, foldername
):
127 raise NotImplementedError
129 def syncfoldersto(self
, dest
, copyfolders
):
130 """Syncs the folders in this repository to those in dest.
131 It does NOT sync the contents of those folders.
133 For every time dest.makefolder() is called, also call makefolder()
134 on each folder in copyfolders."""
136 srcfolders
= src
.getfolders()
137 destfolders
= dest
.getfolders()
139 # Create hashes with the names, but convert the source folders
140 # to the dest folder's sep.
143 for folder
in srcfolders
:
144 srchash
[folder
.getvisiblename().replace(src
.getsep(), dest
.getsep())] = \
147 for folder
in destfolders
:
148 desthash
[folder
.getvisiblename()] = folder
154 for key
in srchash
.keys():
155 if not key
in desthash
:
157 for copyfolder
in copyfolders
:
158 copyfolder
.makefolder(key
.replace(dest
.getsep(), copyfolder
.getsep()))
161 # Find deleted folders.
163 # We don't delete folders right now.
165 #for key in desthash.keys():
166 # if not key in srchash:
167 # dest.deletefolder(key)
170 ##### Find any folders that aren't being synced
172 for key
in desthash
.keys():
173 if not key
in srchash
:
174 ignoredfolders
.append(key
)
176 ignoredfolders
.sort()
177 if ignoredfolders
!= []:
178 UIBase
.getglobalui().warn("Found local folders that are not being synced: %s" % (", ".join(ignoredfolders
)))
182 def startkeepalive(self
):
183 """The default implementation will do nothing."""
186 def stopkeepalive(self
, abrupt
= 0):
187 """Stop keep alive. If abrupt is 1, stop it but don't bother waiting
188 for the threads to terminate."""