After pruning, run attic's consistency checks on all archives.

This commit is contained in:
Dan Helfman 2015-02-14 09:23:40 -08:00
parent 6d4e40a819
commit e3fa18b892
5 changed files with 64 additions and 11 deletions

3
NEWS
View file

@ -1,5 +1,6 @@
default
0.0.3
* After pruning, run attic's consistency checks on all archives.
* Integration tests for argument parsing.
* Documentation updates about repository encryption.

View file

@ -5,10 +5,11 @@ save_as: atticmatic/index.html
## Overview
atticmatic is a simple Python wrapper script for the [Attic backup
software](https://attic-backup.org/) that initiates a backup and prunes any
old backups according to a retention policy. The script supports specifying
your settings in a declarative configuration file rather than having to put
them all on the command-line, and handles common errors.
software](https://attic-backup.org/) that initiates a backup, prunes any old
backups according to a retention policy, and validates backups for
consistency. The script supports specifying your settings in a declarative
configuration file rather than having to put them all on the command-line, and
handles common errors.
Here's an example config file:
@ -68,7 +69,9 @@ arguments:
atticmatic
This will also prune any old backups as per the configured retention policy.
This will also prune any old backups as per the configured retention policy,
and check backups for consistency problems due to things like file damage.
By default, the backup will proceed silently except in the case of errors. But
if you'd like to to get additional information about the progress of the
backup as it proceeds, use the verbose option instead:

View file

@ -1,5 +1,5 @@
from datetime import datetime
import os
import platform
import subprocess
@ -63,3 +63,19 @@ def prune_archives(verbose, repository, retention_config):
) + (('--verbose',) if verbose else ())
subprocess.check_call(command)
def check_archives(verbose, repository):
'''
Given a verbosity flag and a local or remote repository path, check the contained attic archives
for consistency.
'''
command = (
'attic', 'check',
repository,
) + (('--verbose',) if verbose else ())
# Attic's check command spews to stdout even without the verbose flag. Suppress it.
stdout = None if verbose else open(os.devnull, 'w')
subprocess.check_call(command, stdout=stdout)

View file

@ -3,7 +3,7 @@ from argparse import ArgumentParser
from subprocess import CalledProcessError
import sys
from atticmatic.attic import create_archive, prune_archives
from atticmatic.attic import check_archives, create_archive, prune_archives
from atticmatic.config import parse_configuration
@ -41,9 +41,11 @@ def main():
try:
args = parse_arguments(*sys.argv[1:])
location_config, retention_config = parse_configuration(args.config_filename)
repository = location_config['repository']
create_archive(args.excludes_filename, args.verbose, **location_config)
prune_archives(args.verbose, location_config['repository'], retention_config)
prune_archives(args.verbose, repository, retention_config)
check_archives(args.verbose, repository)
except (ValueError, IOError, CalledProcessError) as error:
print(error, file=sys.stderr)
sys.exit(1)

View file

@ -5,9 +5,9 @@ from flexmock import flexmock
from atticmatic import attic as module
def insert_subprocess_mock(check_call_command):
def insert_subprocess_mock(check_call_command, **kwargs):
subprocess = flexmock()
subprocess.should_receive('check_call').with_args(check_call_command).once()
subprocess.should_receive('check_call').with_args(check_call_command, **kwargs).once()
flexmock(module).subprocess = subprocess
@ -111,3 +111,34 @@ def test_prune_archives_with_verbose_should_call_attic_with_verbose_parameters()
verbose=True,
retention_config=retention_config,
)
def test_check_archives_should_call_attic_with_parameters():
stdout = flexmock()
insert_subprocess_mock(
('attic', 'check', 'repo'),
stdout=stdout,
)
insert_platform_mock()
insert_datetime_mock()
flexmock(module).open = lambda filename, mode: stdout
flexmock(module).os = flexmock().should_receive('devnull').mock
module.check_archives(
verbose=False,
repository='repo',
)
def test_check_archives_with_verbose_should_call_attic_with_verbose_parameters():
insert_subprocess_mock(
('attic', 'check', 'repo', '--verbose'),
stdout=None,
)
insert_platform_mock()
insert_datetime_mock()
module.check_archives(
verbose=True,
repository='repo',
)