From 71775bac97858d917e99e6030402fa35406a5da8 Mon Sep 17 00:00:00 2001 From: Marian Beermann Date: Wed, 30 Nov 2016 01:06:21 +0100 Subject: [PATCH] check: rebuild manifest if it's corrupted --- borg/archive.py | 10 ++++++++-- borg/testsuite/archiver.py | 13 +++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/borg/archive.py b/borg/archive.py index f69834ce4..3c27c45d5 100644 --- a/borg/archive.py +++ b/borg/archive.py @@ -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: - self.manifest, _ = Manifest.load(repository, key=self.key) + 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) diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index a7d8ff3e6..b493be534 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -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: