PR #251 - Merge branch 'rename_archive' into merge

This commit is contained in:
Thomas Waldmann 2015-03-24 07:19:01 +01:00
commit 3d2a3d11af
3 changed files with 66 additions and 4 deletions

View file

@ -152,12 +152,16 @@ class Archive:
info = self.manifest.archives[name]
self.load(info[b'id'])
def _load_meta(self, id):
data = self.key.decrypt(id, self.repository.get(id))
metadata = msgpack.unpackb(data)
if metadata[b'version'] != 1:
raise Exception('Unknown archive metadata version')
return metadata
def load(self, id):
self.id = id
data = self.key.decrypt(self.id, self.repository.get(self.id))
self.metadata = msgpack.unpackb(data)
if self.metadata[b'version'] != 1:
raise Exception('Unknown archive metadata version')
self.metadata = self._load_meta(self.id)
decode_dict(self.metadata, (b'name', b'hostname', b'username', b'time'))
self.metadata[b'cmdline'] = [arg.decode('utf-8', 'surrogateescape') for arg in self.metadata[b'cmdline']]
self.name = self.metadata[b'name']
@ -344,6 +348,18 @@ class Archive:
except OSError:
pass
def rename(self, name):
if name in self.manifest.archives:
raise self.AlreadyExists(name)
metadata = StableDict(self._load_meta(self.id))
metadata[b'name'] = name
data = msgpack.packb(metadata, unicode_errors='surrogateescape')
new_id = self.key.id_hash(data)
self.cache.add_chunk(new_id, data, self.stats)
self.manifest.archives[name] = {'id': new_id, 'time': metadata[b'time']}
self.cache.chunk_decref(self.id, self.stats)
del self.manifest.archives[self.name]
def delete(self, stats):
unpacker = msgpack.Unpacker(use_list=False)
for items_id, data in zip(self.metadata[b'items'], self.repository.get_many(self.metadata[b'items'])):

View file

@ -249,6 +249,18 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
archive.extract_item(dirs.pop(-1))
return self.exit_code
def do_rename(self, args):
"""Rename an existing archive"""
repository = self.open_repository(args.archive, exclusive=True)
manifest, key = Manifest.load(repository)
cache = Cache(repository, key, manifest)
archive = Archive(repository, key, manifest, args.archive.archive, cache=cache)
archive.rename(args.name)
manifest.write()
repository.commit()
cache.commit()
return self.exit_code
def do_delete(self, args):
"""Delete an existing archive"""
repository = self.open_repository(args.archive, exclusive=True)
@ -631,6 +643,20 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
subparser.add_argument('paths', metavar='PATH', nargs='*', type=str,
help='paths to extract')
rename_epilog = textwrap.dedent("""
This command renames an archive in the repository.
""")
subparser = subparsers.add_parser('rename', parents=[common_parser],
description=self.do_rename.__doc__,
epilog=rename_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter)
subparser.set_defaults(func=self.do_rename)
subparser.add_argument('archive', metavar='ARCHIVE',
type=location_validator(archive=True),
help='archive to rename')
subparser.add_argument('name', metavar='NEWNAME', type=str,
help='the new archive name to use')
delete_epilog = textwrap.dedent("""
This command deletes an archive from the repository. Any disk space not
shared with any other existing archive is also reclaimed.

View file

@ -265,6 +265,26 @@ class ArchiverTestCase(ArchiverTestCaseBase):
with changedir('output'):
self.attic('extract', self.repository_location + '::test', exit_code=1)
def test_rename(self):
self.create_regular_file('file1', size=1024 * 80)
self.create_regular_file('dir2/file2', size=1024 * 80)
self.attic('init', self.repository_location)
self.attic('create', self.repository_location + '::test', 'input')
self.attic('create', self.repository_location + '::test.2', 'input')
self.attic('extract', '--dry-run', self.repository_location + '::test')
self.attic('extract', '--dry-run', self.repository_location + '::test.2')
self.attic('rename', self.repository_location + '::test', 'test.3')
self.attic('extract', '--dry-run', self.repository_location + '::test.2')
self.attic('rename', self.repository_location + '::test.2', 'test.4')
self.attic('extract', '--dry-run', self.repository_location + '::test.3')
self.attic('extract', '--dry-run', self.repository_location + '::test.4')
# Make sure both archives have been renamed
repository = Repository(self.repository_path)
manifest, key = Manifest.load(repository)
self.assert_equal(len(manifest.archives), 2)
self.assert_in('test.3', manifest.archives)
self.assert_in('test.4', manifest.archives)
def test_delete(self):
self.create_regular_file('file1', size=1024 * 80)
self.create_regular_file('dir2/file2', size=1024 * 80)