]> code.delx.au - offlineimap/blob - offlineimap/repository/Base.py
Resolve conflict
[offlineimap] / offlineimap / repository / Base.py
1 # Base repository support
2 # Copyright (C) 2002-2007 John Goerzen
3 # <jgoerzen@complete.org>
4 #
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.
9 #
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.
14 #
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
18
19 from offlineimap import CustomConfig
20 import os.path
21
22 def LoadRepository(name, account, reqtype):
23 from offlineimap.repository.IMAP import IMAPRepository, MappedIMAPRepository
24 from offlineimap.repository.Maildir import MaildirRepository
25 if reqtype == 'remote':
26 # For now, we don't support Maildirs on the remote side.
27 typemap = {'IMAP': IMAPRepository}
28 elif reqtype == 'local':
29 typemap = {'IMAP': MappedIMAPRepository,
30 'Maildir': MaildirRepository}
31 else:
32 raise ValueError, "Request type %s not supported" % reqtype
33 config = account.getconfig()
34 repostype = config.get('Repository ' + name, 'type').strip()
35 return typemap[repostype](name, account)
36
37 class BaseRepository(CustomConfig.ConfigHelperMixin):
38 def __init__(self, reposname, account):
39 self.account = account
40 self.config = account.getconfig()
41 self.name = reposname
42 self.localeval = account.getlocaleval()
43 self.accountname = self.account.getname()
44 self.uiddir = os.path.join(self.config.getmetadatadir(), 'Repository-' + self.name)
45 if not os.path.exists(self.uiddir):
46 os.mkdir(self.uiddir, 0700)
47 self.mapdir = os.path.join(self.uiddir, 'UIDMapping')
48 if not os.path.exists(self.mapdir):
49 os.mkdir(self.mapdir, 0700)
50 self.uiddir = os.path.join(self.uiddir, 'FolderValidity')
51 if not os.path.exists(self.uiddir):
52 os.mkdir(self.uiddir, 0700)
53
54 # The 'restoreatime' config parameter only applies to local Maildir
55 # mailboxes.
56 def restore_atime(self):
57 if self.config.get('Repository ' + self.name, 'type').strip() != \
58 'Maildir':
59 return
60
61 if not self.config.has_option('Repository ' + self.name, 'restoreatime') or not self.config.getboolean('Repository ' + self.name, 'restoreatime'):
62 return
63
64 return self.restore_folder_atimes()
65
66 def connect(self):
67 """Establish a connection to the remote, if necessary. This exists
68 so that IMAP connections can all be established up front, gathering
69 passwords as needed. It was added in order to support the
70 error recovery -- we need to connect first outside of the error
71 trap in order to validate the password, and that's the point of
72 this function."""
73 pass
74
75 def holdordropconnections(self):
76 pass
77
78 def dropconnections(self):
79 pass
80
81 def getaccount(self):
82 return self.account
83
84 def getname(self):
85 return self.name
86
87 def getuiddir(self):
88 return self.uiddir
89
90 def getmapdir(self):
91 return self.mapdir
92
93 def getaccountname(self):
94 return self.accountname
95
96 def getsection(self):
97 return 'Repository ' + self.name
98
99 def getconfig(self):
100 return self.config
101
102 def getlocaleval(self):
103 return self.account.getlocaleval()
104
105 def getfolders(self):
106 """Returns a list of ALL folders on this server."""
107 return []
108
109 def forgetfolders(self):
110 """Forgets the cached list of folders, if any. Useful to run
111 after a sync run."""
112 pass
113
114 def getsep(self):
115 raise NotImplementedError
116
117 def makefolder(self, foldername):
118 raise NotImplementedError
119
120 def deletefolder(self, foldername):
121 raise NotImplementedError
122
123 def getfolder(self, foldername):
124 raise NotImplementedError
125
126 def syncfoldersto(self, dest):
127 """Syncs the folders in this repository to those in dest.
128 It does NOT sync the contents of those folders."""
129 src = self
130 srcfolders = src.getfolders()
131 destfolders = dest.getfolders()
132
133 # Create hashes with the names, but convert the source folders
134 # to the dest folder's sep.
135
136 srchash = {}
137 for folder in srcfolders:
138 srchash[folder.getvisiblename().replace(src.getsep(), dest.getsep())] = \
139 folder
140 desthash = {}
141 for folder in destfolders:
142 desthash[folder.getvisiblename()] = folder
143
144 #
145 # Find new folders.
146 #
147
148 for key in srchash.keys():
149 if not key in desthash:
150 dest.makefolder(key)
151
152 #
153 # Find deleted folders.
154 #
155 # We don't delete folders right now.
156
157 #for key in desthash.keys():
158 # if not key in srchash:
159 # dest.deletefolder(key)
160
161 ##### Keepalive
162
163 def startkeepalive(self):
164 """The default implementation will do nothing."""
165 pass
166
167 def stopkeepalive(self, abrupt = 0):
168 """Stop keep alive. If abrupt is 1, stop it but don't bother waiting
169 for the threads to terminate."""
170 pass
171