diff --git a/src/borg/helpers.py b/src/borg/helpers.py index 93413845b..a1624f1ad 100644 --- a/src/borg/helpers.py +++ b/src/borg/helpers.py @@ -1430,6 +1430,7 @@ class ItemFormatter(BaseFormatter): 'csize': 'compressed size', 'num_chunks': 'number of chunks in this file', 'unique_chunks': 'number of unique chunks in this file', + 'health': 'either "healthy" (file ok) or "broken" (if file has all-zero replacement chunks)', } KEY_GROUPS = ( ('type', 'mode', 'uid', 'gid', 'user', 'group', 'path', 'bpath', 'source', 'linktarget', 'flags'), @@ -1437,6 +1438,7 @@ class ItemFormatter(BaseFormatter): ('mtime', 'ctime', 'atime', 'isomtime', 'isoctime', 'isoatime'), tuple(sorted(hashlib.algorithms_guaranteed)), ('archiveid', 'archivename', 'extra'), + ('health', ) ) @classmethod @@ -1526,6 +1528,7 @@ class ItemFormatter(BaseFormatter): item_data['linktarget'] = source item_data['extra'] = extra item_data['flags'] = item.get('bsdflags') + item_data['health'] = 'broken' if 'chunks_healthy' in item else 'healthy' for key in self.used_call_keys: item_data[key] = self.call_keys[key](item) return item_data diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index 75f67ecbf..4c8c765da 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -2082,6 +2082,8 @@ class ArchiverCheckTestCase(ArchiverTestCaseBase): output = self.cmd('check', '--repair', self.repository_location, exit_code=0) self.assert_in('New missing file chunk detected', output) self.cmd('check', self.repository_location, exit_code=0) + output = self.cmd('list', '--format={health}#{path}{LF}', self.repository_location + '::archive1', exit_code=0) + self.assert_in('broken#', output) # check that the file in the old archives has now a different chunk list without the killed chunk for archive_name in ('archive1', 'archive2'): archive, repository = self.open_archive(archive_name) @@ -2110,6 +2112,9 @@ class ArchiverCheckTestCase(ArchiverTestCaseBase): break else: self.assert_true(False) # should not happen + # list is also all-healthy again + output = self.cmd('list', '--format={health}#{path}{LF}', self.repository_location + '::archive1', exit_code=0) + self.assert_not_in('broken#', output) def test_missing_archive_item_chunk(self): archive, repository = self.open_archive('archive1')