def runUpdates(output = True): backupFilename = "%s-preupgrade.tar.gz" % dbFilename if output: print "Backing up database to %s" % backupFilename db().archive(backupFilename) if output: print "Updating" toApply = updates[settings.dbVersion:] try: for f in toApply: if f.__doc__: print " v%d: %s" % (settings.dbVersion + 1, f.__doc__) f() settings.dbVersion += 1 except: if output: print "Unable to update to version %d. Restoring database from backup" % (settings.dbVersion + 1) rmtree(dbFilename) f = tarfile.open(backupFilename, 'r:gz') f.extractall() f.close() if output: print "Update rolled back. Error follows:" print raise
def save(self): if not self.id: # Shift everything after this sequence for id, group in db()['groups'].iteritems(): if group['sprintid'] == self.sprintid and group['seq'] >= self.seq: with db()['groups'].change(id) as data: data['seq'] += 1 return ActiveRecord.save(self)
def logArchive(): if not isdir('logs'): print "No logs directory exists; aborting" return logDB = DiskMap('logs') logDB['log'].merge(db()['log']) print "Archived %s; %d total" % (pluralize(len(db()['log']), 'log entry', 'log entries'), len(logDB['log'])) db()['log'].truncate(resetID = False)
def backup(): if not isdir('backups'): print "No backups directory exists; aborting" return filename = datetime.now().strftime('backups/%Y%m%d-%H%M%S.tar.gz') if exists(filename): print "Backup file <code>%s</code> already exists; aborting" % filename return db().archive(filename) print "Backup to <code>%s</code> successful" % filename
def save(self): #DEBUG #NO if not isinstance(self.assignedids, (set, frozenset)): raise RuntimeError("Broken type (%s)" % type(self.assignedids).__name__) if not isinstance(self.assigned, (set, frozenset)): raise RuntimeError("Broken type (%s)" % type(self.assigned).__name__) if not self.id: # Shift everything after this sequence for id, task in db()['tasks'].iteritems(): rev = task[-1] if rev['groupid'] == self.groupid and rev['seq'] >= self.seq: with db()['tasks'].change(id) as data: data[-1]['seq'] += 1 return ActiveRecord.save(self)
def move(self, newSeq): # Remove group from the list for id, group in db()['groups'].iteritems(): if group['sprintid'] == self.sprintid and group['seq'] > self.seq: with db()['groups'].change(id) as data: data['seq'] -= 1 # Insert it at the new spot if newSeq: self.seq = newSeq for id, group in db()['groups'].iteritems(): if group['sprintid'] == self.sprintid and group['seq'] >= self.seq: with db()['groups'].change(id) as data: data['seq'] += 1 self.save()
def set(self, user, timestamp, hours): table = db()['availability'] if self.sprint.id not in table: table[self.sprint.id] = {} with table.change(self.sprint.id) as data: if user.id not in data: data[user.id] = {} data[user.id][dateToTs(timestamp)] = hours
def saveDataFilter(cls, data): if data['id']: if data['id'] not in db()['tasks']: return [data] rev = data['revision'] - 1 revs = db()['tasks'][data['id']] if rev < len(revs): revs[rev] = data elif rev == len(revs): revs.append(data) else: raise StasisError("Invalid revision %d for task %d" % (data['revision'], data['id'])) return revs else: if data['revision'] != 1: raise StasisError("Invalid first revision (%d)" % data['revision']) return [data]
def v21(): """Move all existing Dev grants to Admin""" table = db()['users'] for id in table: with table.change(id) as data: if 'Dev' in data['privileges']: data['privileges'].remove('Dev') data['privileges'].add('Admin')
def getAll(self, timestamp): rtn = 0 ts = dateToTs(timestamp) table = db()['availability'] if self.sprint.id in table: for data in table[self.sprint.id].values(): if ts in data: rtn += data[ts] return rtn
def get(self, user, timestamp): table = db()['availability'] if self.sprint.id in table: data = table[self.sprint.id] if user.id in data: ts = dateToTs(timestamp) if ts in data[user.id]: return data[user.id][ts] return 0
def v23(): """Convert bugzillaURL to autolinkPatterns""" table = db()['settings'] table['autolink'] = ([], [], []) if 'bugzillaURL' in table: with table.change('autolink') as data: icons, patterns, urls = data icons.append('bugzilla') patterns.append('(?:bug |bz)(?P<id>[0-9]+)') urls.append("%s/show_bug.cgi?id=$id" % table['bugzillaURL']) del table['bugzillaURL']
def v24(): """Fix tasks 'deleted' field type""" table = db()['tasks'] for id in table: with table.change(id) as data: for rev in range(len(data)): if data[rev]['deleted'] in [0, '0']: data[rev]['deleted'] = False elif data[rev]['deleted'] in [1, '1']: data[rev]['deleted'] = True else: raise RuntimeError("Unexpected deleted value for task #%d, revision %d: %s" % (id, rev + 1, data['deleted']))
def getAllForward(self, timestamp, user = None): rtn = 0 ts = dateToTs(timestamp) table = db()['availability'] if self.sprint.id in table: for userid, data in table[self.sprint.id].iteritems(): if user is not None and user.id != userid: continue for thisstamp, hours in data.iteritems(): if thisstamp >= ts: rtn += hours return rtn
def move(self, newSeq, newGroup): # newSeq is the new sequence number this task should have # newGroup is the group to move to, or None to stay in the same group # Remove from current group (shift all later tasks up) for id, task in db()['tasks'].iteritems(): rev = task[-1] if rev['groupid'] == self.groupid and rev['seq'] > self.seq: with db()['tasks'].change(id) as data: for rev in data: rev['seq'] -= 1 # Switch group (for all revisions) if self.group != newGroup: self.group = newGroup with db()['tasks'].change(self.id) as data: for rev in data: rev['groupid'] = self.groupid # Add to new group (shift all later tasks down) self.seq = newSeq for id, task in db()['tasks'].iteritems(): rev = task[-1] if rev['groupid'] == self.groupid and rev['seq'] >= self.seq: with db()['tasks'].change(id) as data: for rev in data: rev['seq'] += 1 with db()['tasks'].change(self.id) as data: for rev in data: rev['seq'] = self.seq
def oldResetKeys(): if 'reset-keys' not in db()['cron']: db()['cron']['reset-keys'] = {} with db()['cron'].change('reset-keys') as data: for user in User.loadAll(): if user.resetkey: if user.id in data: if user.resetkey == data[user.id]: user.resetkey = None user.save() del data[user.id] print "<b>%s</b>: Key expired<br>" % user.safe.username else: data[user.id] = user.resetkey print "<b>%s</b>: New key marked<br>" % user.safe.username else: data[user.id] = user.resetkey print "<b>%s</b>: New key marked<br>" % user.safe.username else: if user.id in data: del data[user.id] print "<b>%s</b>: Key consumed; removed old mark<br>" % user.safe.username
def getIDs(self): return db()['sessions'].keys()
def destroy(self, sessionID): if sessionID in self.cache: del self.cache[sessionID] del db()['sessions'][sessionID]
def items(self): return db()['settings'].all().items()
def keys(self): return db()['settings'].keys()
def __delitem__(self, name): del db()['settings'][name]
def __setitem__(self, name, value): db()['settings'][name] = value
def __getitem__(self, name): return db()['settings'][name]
def __contains__(self, item): return item in db()['settings']
def get(self, sessionID): if sessionID not in self.cache: if sessionID not in db()['sessions']: db()['sessions'][sessionID] = Session(sessionID) self.cache[sessionID] = db()['sessions'][sessionID] return self.cache[sessionID]
def delete(self, user): table = db()['availability'] if self.sprint.id in table: if user.id in table[self.sprint.id]: with table.change(self.sprint.id) as data: del data[user.id]
def wipe(self): table = db()['availability'] if self.sprint.id in table: del table[self.sprint.id]
def getRevision(self, revision): revision -= 1 # revision is 1-indexed data = db()['tasks'][self.id] return Task(**data[revision]) if revision < len(data) else None
def getRevisions(self): data = db()['tasks'][self.id] return map(lambda x: Task(**x), data)
def trim(self): table = db()['availability'] if self.sprint.id in table: with table.change(self.sprint.id) as data: for userid, hourmap in data.iteritems(): data[userid] = {timestamp: hours for timestamp, hours in hourmap.iteritems() if self.sprint.start <= timestamp <= self.sprint.end}