[fix] Backup without info.json (#342)

* [fix] Backup without info.json
* Add test of archive restore with no info.json
* Fix exception handling in backup_delete when info.json is missng
This commit is contained in:
ljf (zamentur) 2017-08-13 22:26:28 +02:00 committed by Alexandre Aubin
parent 02ea0c0656
commit 3ede5fc39d
2 changed files with 37 additions and 10 deletions

View file

@ -2193,7 +2193,11 @@ def backup_list(with_info=False, human_readable=False):
if result and with_info:
d = OrderedDict()
for a in result:
d[a] = backup_info(a, human_readable=human_readable)
try:
d[a] = backup_info(a, human_readable=human_readable)
except MoulinetteError, e:
logger.warning('%s: %s' % (a, e.strerror))
result = d
return {'archives': result}
@ -2231,9 +2235,16 @@ def backup_info(name, with_details=False, human_readable=False):
if not os.path.exists(info_file):
tar = tarfile.open(archive_file, "r:gz")
info_dir = info_file + '.d'
tar.extract('info.json', path=info_dir)
tar.close()
shutil.move(os.path.join(info_dir, 'info.json'), info_file)
try:
tar.extract('info.json', path=info_dir)
except KeyError:
logger.debug("unable to retrieve '%s' inside the archive",
info_file, exc_info=1)
raise MoulinetteError(errno.EIO, m18n.n('backup_invalid_archive'))
else:
shutil.move(os.path.join(info_dir, 'info.json'), info_file)
finally:
tar.close()
os.rmdir(info_dir)
try:
@ -2281,21 +2292,21 @@ def backup_delete(name):
name -- Name of the local backup archive
"""
if name not in backup_list()["archives"]:
raise MoulinetteError(errno.EIO, m18n.n('backup_archive_name_unknown',
name=name))
hook_callback('pre_backup_delete', args=[name])
archive_file = '%s/%s.tar.gz' % (ARCHIVES_PATH, name)
info_file = "%s/%s.info.json" % (ARCHIVES_PATH, name)
for backup_file in [archive_file, info_file]:
if not os.path.isfile(backup_file) and not os.path.islink(backup_file):
raise MoulinetteError(errno.EIO,
m18n.n('backup_archive_name_unknown', name=backup_file))
try:
os.remove(backup_file)
except:
logger.debug("unable to delete '%s'", backup_file, exc_info=1)
raise MoulinetteError(errno.EIO,
m18n.n('backup_delete_error', path=backup_file))
logger.warning(m18n.n('backup_delete_error', path=backup_file))
hook_callback('post_backup_delete', args=[name])

View file

@ -634,5 +634,21 @@ def _test_backup_and_restore_app(app):
assert app_is_installed(app)
###############################################################################
# Some edge cases #
###############################################################################
def test_restore_archive_with_no_json(mocker):
# Create a backup with no info.json associated
os.system("touch /tmp/afile")
os.system("tar -czvf /home/yunohost.backup/archives/badbackup.tar.gz /tmp/afile")
assert "badbackup" in backup_list()["archives"]
mocker.spy(m18n, "n")
with pytest.raises(MoulinetteError):
backup_restore(auth, name="badbackup", force=True,
ignore_system=False, ignore_apps=False)
m18n.n.assert_any_call('backup_invalid_archive')