From 80cbdcd8f19a8bb749e3b1dd96a7d8f77ac70390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Borgstr=C3=B6m?= Date: Sun, 21 Aug 2011 21:35:00 +0200 Subject: [PATCH] Make the manifest format more extensible --- darc/archive.py | 23 +++++++++++++---------- darc/cache.py | 3 ++- darc/test.py | 8 +++++++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/darc/archive.py b/darc/archive.py index 1f08fd849..2b71f7f6d 100644 --- a/darc/archive.py +++ b/darc/archive.py @@ -37,19 +37,22 @@ def __init__(self, store, key, name=None, cache=None): if name: manifest = Archive.read_manifest(self.store, self.key) try: - id, ts = manifest[name] + info = manifest['archives'][name] except KeyError: raise Archive.DoesNotExist - self.load(id) + self.load(info['id']) @staticmethod def read_manifest(store, key): mid = store.meta['manifest'] if not mid: - return {} + return {'version': 1, 'archives': {}} mid = mid.decode('hex') data = key.decrypt(mid, store.get(mid)) - return msgpack.unpackb(data) + manifest = msgpack.unpackb(data) + if not manifest.get('version') == 1: + raise ValueError('Invalid manifest version') + return manifest def write_manifest(self, manifest): mid = self.store.meta['manifest'] @@ -134,8 +137,8 @@ def save(self, name, cache): self.id = self.key.id_hash(data) cache.add_chunk(self.id, data, self.stats) manifest = Archive.read_manifest(self.store, self.key) - assert not name in manifest - manifest[name] = self.id, metadata['time'] + assert not name in manifest['archives'] + manifest['archives'][name] = {'id': self.id, 'time': metadata['time']} self.write_manifest(manifest) self.store.commit() cache.commit() @@ -288,8 +291,8 @@ def callback(chunk, error, id): self.store.flush_rpc() self.cache.chunk_decref(self.id) manifest = Archive.read_manifest(self.store, self.key) - assert self.name in manifest - del manifest[self.name] + assert self.name in manifest['archives'] + del manifest['archives'][self.name] self.write_manifest(manifest) self.store.commit() cache.commit() @@ -370,8 +373,8 @@ def process_file(self, path, st, cache): @staticmethod def list_archives(store, key, cache=None): manifest = Archive.read_manifest(store, key) - for name, (id, ts) in manifest.items(): + for name, info in manifest['archives'].items(): archive = Archive(store, key, cache=cache) - archive.load(id) + archive.load(info['id']) yield archive diff --git a/darc/cache.py b/darc/cache.py index f9753196c..ec1b686d0 100644 --- a/darc/cache.py +++ b/darc/cache.py @@ -147,7 +147,8 @@ def cb(chunk, error, id): mdata = self.key.decrypt(mid, cdata) self.chunks[mid] = 1, len(mdata), len(cdata) unpacker = msgpack.Unpacker() - for name, (id, _) in Archive.read_manifest(self.store, self.key).items(): + for name, info in Archive.read_manifest(self.store, self.key)['archives'].items(): + id = info['id'] cdata = self.store.get(id) data = self.key.decrypt(id, cdata) try: diff --git a/darc/test.py b/darc/test.py index 6493ac5da..9a239d22f 100644 --- a/darc/test.py +++ b/darc/test.py @@ -96,7 +96,7 @@ def test_basic_functionality(self): self.create_regual_file('dir2/file2', size=1024*80) x = xattr(os.path.join(self.input_path, 'file1')) x.set('user.foo', 'bar') - os.link(os.path.join(self.input_path, 'file1'), + os.link(os.path.join(self.input_path, 'file1'), os.path.join(self.input_path, 'hardlink')) os.symlink('somewhere', os.path.join(self.input_path, 'link1')) os.mkfifo(os.path.join(self.input_path, 'fifo1')) @@ -105,6 +105,12 @@ def test_basic_functionality(self): self.darc('create', self.store_path + '::test.2', 'input') self.darc('extract', self.store_path + '::test', 'output') self.diff_dirs('input', 'output/input') + info_output = self.darc('info', self.store_path + '::test') + shutil.rmtree(self.cache_path) + info_output2 = self.darc('info', self.store_path + '::test') + # info_output2 starts with some "initializing cache" text but should + # end the same way as info_output + assert info_output2.endswith(info_output) def test_corrupted_store(self): self.create_src_archive('test')