check: rebuild manifest if it's corrupted

This commit is contained in:
Marian Beermann 2016-11-30 01:06:21 +01:00
parent cdd9891444
commit 71775bac97
No known key found for this signature in database
GPG Key ID: 9B8450B91D1362C1
2 changed files with 21 additions and 2 deletions

View File

@ -19,7 +19,7 @@ from . import xattr
from .helpers import Error, uid2user, user2uid, gid2group, group2gid, bin_to_hex, \
parse_timestamp, to_localtime, format_time, format_timedelta, remove_surrogates, \
Manifest, Statistics, decode_dict, make_path_safe, StableDict, int_to_bigint, bigint_to_int, \
ProgressIndicatorPercent
ProgressIndicatorPercent, IntegrityError
from .platform import acl_get, acl_set
from .chunker import Chunker
from .hashindex import ChunkIndex
@ -849,7 +849,13 @@ class ArchiveChecker:
self.error_found = True
self.manifest = self.rebuild_manifest()
else:
try:
self.manifest, _ = Manifest.load(repository, key=self.key)
except IntegrityError as exc:
logger.error('Repository manifest is corrupted: %s', exc)
self.error_found = True
del self.chunks[Manifest.MANIFEST_ID]
self.manifest = self.rebuild_manifest()
self.rebuild_refcounts(archive=archive, last=last, prefix=prefix)
self.orphan_chunks_check()
self.finish(save_space=save_space)

View File

@ -1433,6 +1433,19 @@ class ArchiverCheckTestCase(ArchiverTestCaseBase):
self.assert_in('archive2', output)
self.cmd('check', self.repository_location, exit_code=0)
def test_corrupted_manifest(self):
archive, repository = self.open_archive('archive1')
with repository:
manifest = repository.get(Manifest.MANIFEST_ID)
corrupted_manifest = manifest + b'corrupted!'
repository.put(Manifest.MANIFEST_ID, corrupted_manifest)
repository.commit()
self.cmd('check', self.repository_location, exit_code=1)
output = self.cmd('check', '-v', '--repair', self.repository_location, exit_code=0)
self.assert_in('archive1', output)
self.assert_in('archive2', output)
self.cmd('check', self.repository_location, exit_code=0)
def test_extra_chunks(self):
self.cmd('check', self.repository_location, exit_code=0)
with Repository(self.repository_location, exclusive=True) as repository: