comparison profilemanager/manager.py @ 65:1cd3e3c71bff

determine which backup to use from the given date
author Jeff Hammel <jhammel@mozilla.com>
date Fri, 07 May 2010 14:14:17 -0700
parents 18f16bd1ba6b
children 67dc95a355cc
comparison
equal deleted inserted replaced
64:18f16bd1ba6b 65:1cd3e3c71bff
5 import os 5 import os
6 import shutil 6 import shutil
7 import string 7 import string
8 import time 8 import time
9 import ConfigParser 9 import ConfigParser
10 from datetime import datetime
11 from dateutil.parser import parse
10 from random import Random 12 from random import Random
11 from utils import format_tabular 13 from utils import format_tabular
12 #from ConfigParser import NoOptionError
13 from ConfigParser import SafeConfigParser as ConfigParser 14 from ConfigParser import SafeConfigParser as ConfigParser
14 15
15 # Changes to profiles.ini: 16 # Changes to profiles.ini:
16 # - add a ``backups`` field for each profile: 17 # - add a ``backups`` field for each profile:
17 # Backups = /path/to/backup:1273104310 /path/to/other/backup:1273104355 18 # Backups = /path/to/backup:1273104310 /path/to/other/backup:1273104355
24 def __init__(self, profile, config): 25 def __init__(self, profile, config):
25 self.profile = profile 26 self.profile = profile
26 self.config = config 27 self.config = config
27 Exception.__init__(self, 28 Exception.__init__(self,
28 'Profile %s not found in %s' % (profile, config)) 29 'Profile %s not found in %s' % (profile, config))
30
31 class NoBackupError(Exception):
32 """
33 exception when a sought backup is not found
34 """
29 35
30 class ProfileManager(object): 36 class ProfileManager(object):
31 37
32 backups_dir = 'backups' # directory for backups relative to profile_dir 38 backups_dir = 'backups' # directory for backups relative to profile_dir
33 39
168 profile is not given; returns a list of backups if 174 profile is not given; returns a list of backups if
169 profile is given or a dictionary of lists otherwise 175 profile is given or a dictionary of lists otherwise
170 - datestamp: format of date; otherwise, seconds since epoch 176 - datestamp: format of date; otherwise, seconds since epoch
171 """ 177 """
172 if profile is None: # all profiles 178 if profile is None: # all profiles
173 # XXX this should probably be recursive
174 retval = {} 179 retval = {}
175 profiles_dict = self.profiles_dict() 180 profiles_dict = self.profiles_dict()
176 for profile in profiles_dict: 181 for profile in profiles_dict:
177 if 'Backups' in profiles_dict[profile]: 182 if 'Backups' in profiles_dict[profile]:
178 retval[profile] = self.backups(profile, datestamp) 183 retval[profile] = self.backups(profile, datestamp)
205 210
206 def restore(self, profile, date=None, delete=False): 211 def restore(self, profile, date=None, delete=False):
207 """ 212 """
208 restore the profile from a backup 213 restore the profile from a backup
209 the most recent backup is used unless `date` is given 214 the most recent backup is used unless `date` is given
210 - date : date to restore from 215 - date : date to restore from (will not delete)
211 - delete : delete the backup after restoration 216 - delete : delete the backup after restoration
212 """ 217 """
218
219 assert not (date and delete), 'date and delete cannot be used in conjunction'
213 220
214 # get the possible backups 221 # get the possible backups
215 backups = self.backups(profile) 222 backups = self.backups(profile)
216 # TODO: check to see if these all exist (print warnings if not) 223 # TODO: check to see if these all exist (print warnings if not)
217 224
225 # determine the backup to use
226 if date:
227
228 if isinstance(date, basestring):
229
230 # test for s since epoch
231 seconds_snice_epoch = None
232 try:
233 seconds_since_epoch = int(date)
234
235 except ValueError:
236 pass
237 if seconds_since_epoch and seconds_since_epoch > time.localtime().tm_year:
238 date = seconds_since_epoch
239 else:
240 date = parse(date) # parse date from string
241
242 if isinstance(date, datetime):
243 # convert to s since epoch
244 date = time.mktime(date.timetuple())
245
246 for backup in backups:
247 raise NotImplementedError
248 else:
249 if not backups:
250 raise NoBackupError("No backups for profile %s in %s" % (profile, self.profiles))
251 backups = backups[0][0]
252
218 # restore the backup over ``profile`` 253 # restore the backup over ``profile``
254
219 255
220 if delete: # delete the backup 256 if delete: # delete the backup
221 # delete the directory 257 # delete the directory
222 # delete the entry from ``profiles.ini`` 258 # delete the entry from ``profiles.ini``
223 # if there are no backups, delete the ``backups`` line 259 # if there are no backups, delete the ``backups`` line