Detect and abort if repository is older than the cache

This commit is contained in:
Jonas Borgström 2013-08-09 23:23:00 +02:00
parent b2346b7c9b
commit 5fa5380f0f
4 changed files with 27 additions and 1 deletions

View file

@ -4,6 +4,14 @@ Attic Changelog
Here you can see the full list of changes between each Attic release.
Version 0.8
-----------
(feature release, released on X)
- Detect and abort if repository is older than the cache
Version 0.7
-----------

View file

@ -492,6 +492,9 @@ def main():
except Archive.DoesNotExist as e:
archiver.print_error('Error: Archive "%s" does not exist', e)
exit_code = 1
except Cache.RepositoryReplay:
archiver.print_error('Cache is newer than repository, refusing to continue')
exit_code = 1
except ConnectionClosed:
archiver.print_error('Connection closed by remote host')
exit_code = 1

View file

@ -14,7 +14,12 @@ class Cache(object):
"""Client Side cache
"""
class RepositoryReplay(Exception):
"""
"""
def __init__(self, repository, key, manifest):
self.timestamp = None
self.txn_active = False
self.repository = repository
self.key = key
@ -24,6 +29,9 @@ class Cache(object):
self.create()
self.open()
if self.manifest.id != self.manifest_id:
# If repository is older than the cache something fishy is going on
if self.timestamp and self.timestamp > manifest.timestamp:
raise self.RepositoryReplay()
self.sync()
self.commit()
@ -31,7 +39,7 @@ class Cache(object):
self.close()
def create(self):
"""Create a new empty repository at `path`
"""Create a new empty cache at `path`
"""
os.makedirs(self.path)
with open(os.path.join(self.path, 'README'), 'w') as fd:
@ -59,6 +67,7 @@ class Cache(object):
raise Exception('%s Does not look like an Attic cache')
self.id = self.config.get('cache', 'repository')
self.manifest_id = unhexlify(self.config.get('cache', 'manifest'))
self.timestamp = self.config.get('cache', 'timestamp', fallback=None)
self.chunks = ChunkIndex(os.path.join(self.path, 'chunks').encode('utf-8'))
self.files = None
@ -103,6 +112,7 @@ class Cache(object):
if item[1][0] < 10 and item[1][3] < self._newest_mtime:
msgpack.pack(item, fd)
self.config.set('cache', 'manifest', hexlify(self.manifest.id).decode('ascii'))
self.config.set('cache', 'timestamp', self.manifest.timestamp)
with open(os.path.join(self.path, 'config'), 'w') as fd:
self.config.write(fd)
self.chunks.flush()

View file

@ -34,13 +34,18 @@ class Manifest:
if not m.get(b'version') == 1:
raise ValueError('Invalid manifest version')
manifest.archives = dict((k.decode('utf-8'), v) for k,v in m[b'archives'].items())
manifest.timestamp = m.get(b'timestamp')
if manifest.timestamp:
manifest.timestamp = manifest.timestamp.decode('ascii')
manifest.config = m[b'config']
return manifest, key
def write(self):
self.timestamp = datetime.utcnow().isoformat()
data = msgpack.packb({
'version': 1,
'archives': self.archives,
'timestamp': self.timestamp,
'config': self.config,
})
self.id = self.key.id_hash(data)