Improve attic check documentation

Closes #24.
This commit is contained in:
Jonas Borgström 2014-02-26 23:13:48 +01:00
parent 678fb2c845
commit 3982c34e6c
6 changed files with 43 additions and 37 deletions

View file

@ -451,17 +451,15 @@ class ArchiveChecker:
def __init__(self):
self.error_found = False
self.progress = True
self.possibly_superseded = set()
self.tmpdir = tempfile.mkdtemp()
def __del__(self):
shutil.rmtree(self.tmpdir)
def check(self, repository, progress=True, repair=False):
def check(self, repository, repair=False):
self.report_progress('Starting archive consistency check...')
self.repair = repair
self.progress = progress
self.repository = repository
self.init_chunks()
self.key = self.identify_key(repository)
@ -494,9 +492,8 @@ class ArchiveChecker:
def report_progress(self, msg, error=False):
if error:
self.error_found = True
if error or self.progress:
print(msg, file=sys.stderr)
sys.stderr.flush()
print(msg, file=sys.stderr)
sys.stderr.flush()
def identify_key(self, repository):
cdata = repository.get(next(self.chunks.iteritems())[0])

View file

@ -6,6 +6,7 @@ import io
import os
import stat
import sys
import textwrap
from attic import __version__
from attic.archive import Archive, ArchiveChecker
@ -72,13 +73,10 @@ in data loss.
Type "Yes I am sure" if you understand this and want to continue.\n""")
if input('Do you want to continue? ') == 'Yes I am sure':
break
if args.progress is None:
args.progress = sys.stdout.isatty() or args.verbose
if not repository.check(progress=args.progress, repair=args.repair):
return 1
if not ArchiveChecker().check(repository, progress=args.progress, repair=args.repair):
return 1
if args.phase in ('all', 'repository') and not repository.check(repair=args.repair):
return 1
if args.phase in ('all', 'archive') and not ArchiveChecker().check(repository, repair=args.repair):
return 1
return 0
def do_change_passphrase(self, args):
@ -429,26 +427,31 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
choices=('none', 'passphrase', 'keyfile'), default='none',
help='select encryption method')
check_epilog = """
Progress status will be reported on the standard error stream by default when
it is attached to a terminal. Any problems found are printed to the standard error
stream and the command will have a non zero exit code.
"""
check_epilog = textwrap.dedent("""
The check command verifies the consistency of a repository and corresponding
archives. The check is performed in two phases. In the first phase the
checksums of the underlying repository segment files are verified to detect
bit rot and other types of damage. In the second phase the consistency and
correctness of the archive metadata is verified.
A specific check phase can be selected using the --phase=repository|archive
option. This can be useful since the "archive" phase can be time consuming
and requires access to the key file and/or passphrase if encryption is enabled.
""")
subparser = subparsers.add_parser('check', parents=[common_parser],
description=self.do_check.__doc__,
epilog=check_epilog)
epilog=check_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter)
subparser.set_defaults(func=self.do_check)
subparser.add_argument('repository', metavar='REPOSITORY',
type=location_validator(archive=False),
help='repository to check consistency of')
subparser.add_argument('--progress', dest='progress', action='store_true',
default=None,
help='Report progress status to standard output stream')
subparser.add_argument('--no-progress', dest='progress', action='store_false',
help='Disable progress reporting')
subparser.add_argument('--phase', dest='phase', choices=['repository', 'archive', 'all'],
default='all',
help='which checks to perform (default: all)')
subparser.add_argument('--repair', dest='repair', action='store_true',
default=False,
help='Attempt to repair any inconsistencies found')
help='attempt to repair any inconsistencies found')
subparser = subparsers.add_parser('change-passphrase', parents=[common_parser],
description=self.do_change_passphrase.__doc__)

View file

@ -182,8 +182,8 @@ class RemoteRepository(object):
w_fds = []
self.ignore_responses |= set(waiting_for)
def check(self, progress=False, repair=False):
return self.call('check', progress, repair)
def check(self, repair=False):
return self.call('check', repair)
def commit(self, *args):
return self.call('commit')

View file

@ -233,7 +233,7 @@ class Repository(object):
self.write_index()
self.rollback()
def check(self, progress=False, repair=False):
def check(self, repair=False):
"""Check repository consistency
This method verifies all segment checksums and makes sure
@ -244,9 +244,8 @@ class Repository(object):
nonlocal error_found
if error:
error_found = True
if error or progress:
print(msg, file=sys.stderr)
sys.stderr.flush()
print(msg, file=sys.stderr)
sys.stderr.flush()
assert not self._active_txn
report_progress('Starting repository check...')

View file

@ -340,6 +340,17 @@ class ArchiverCheckTestCase(ArchiverTestCaseBase):
archive = Archive(repository, key, manifest, name)
return archive, repository
def test_check_usage(self):
output = self.attic('check', self.repository_location, exit_code=0)
self.assert_in('Starting repository check', output)
self.assert_in('Starting archive consistency check', output)
output = self.attic('check', '--phase', 'repository', self.repository_location, exit_code=0)
self.assert_in('Starting repository check', output)
self.assert_not_in('Starting archive consistency check', output)
output = self.attic('check', '--phase', 'archive', self.repository_location, exit_code=0)
self.assert_not_in('Starting repository check', output)
self.assert_in('Starting archive consistency check', output)
def test_missing_file_chunk(self):
archive, repository = self.open_archive('archive1')
for item in archive.iter_items():
@ -372,8 +383,8 @@ class ArchiverCheckTestCase(ArchiverTestCaseBase):
repository.delete(Manifest.MANIFEST_ID)
repository.commit()
self.attic('check', self.repository_location, exit_code=1)
self.attic('check', '--repair', '--progress', self.repository_location, exit_code=0)
self.attic('check', '--progress', self.repository_location, exit_code=0)
self.attic('check', '--repair', self.repository_location, exit_code=0)
self.attic('check', self.repository_location, exit_code=0)
def test_extra_chunks(self):
self.attic('check', self.repository_location, exit_code=0)

View file

@ -86,10 +86,6 @@ Examples
.. include:: usage/check.rst.inc
The check command verifies the consistency of a repository. Any inconsistencies
found are reported to the standard error stream and the command will have a
non zero exit code.
.. include:: usage/delete.rst.inc
This command deletes an archive from the repository. Any disk space not