1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2024-12-25 01:06:50 +00:00

Make the manifest format more extensible

This commit is contained in:
Jonas Borgström 2011-08-21 21:35:00 +02:00
parent 52c02ceda3
commit 80cbdcd8f1
3 changed files with 22 additions and 12 deletions

View file

@ -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

View file

@ -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:

View file

@ -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')