Fix broken list_details, progress, and statistics options (#303).

This commit is contained in:
Dan Helfman
2025-03-31 11:33:56 -07:00
parent de4d7af507
commit cf477bdc1c
47 changed files with 357 additions and 739 deletions
+1 -2
View File
@@ -372,7 +372,7 @@ def collect_spot_check_source_paths(
borgmatic.borg.create.make_base_create_command(
dry_run=True,
repository_path=repository['path'],
config=config,
config=dict(config, list_details=True),
patterns=borgmatic.actions.create.process_patterns(
borgmatic.actions.create.collect_patterns(config),
working_directory,
@@ -382,7 +382,6 @@ def collect_spot_check_source_paths(
borgmatic_runtime_directory=borgmatic_runtime_directory,
local_path=local_path,
remote_path=remote_path,
list_files=True,
stream_processes=stream_processes,
)
)
-10
View File
@@ -37,17 +37,7 @@ def run_compact(
global_arguments,
local_path=local_path,
remote_path=remote_path,
progress=(
config.get('progress')
if compact_arguments.progress is None
else compact_arguments.progress
),
cleanup_commits=compact_arguments.cleanup_commits,
threshold=(
config.get('compact_threshold')
if compact_arguments.threshold is None
else compact_arguments.threshold
),
)
else: # pragma: nocover
logger.info('Skipping compact (only available/needed in Borg 1.2+)')
-1
View File
@@ -127,5 +127,4 @@ def run_bootstrap(bootstrap_arguments, global_arguments, local_borg_version):
extract_to_stdout=False,
destination_path=bootstrap_arguments.destination,
strip_components=bootstrap_arguments.strip_components,
progress=bootstrap_arguments.progress,
)
+10 -15
View File
@@ -289,6 +289,16 @@ def run_create(
):
return
if config.get('list_details') and config.get('progress'):
raise ValueError(
'With the create action, only one of --list/--files/list_details and --progress/progress can be used.'
)
if config.get('list_details') and create_arguments.json:
raise ValueError(
'With the create action, only one of --list/--files/list_details and --json can be used.'
)
logger.info(f'Creating archive{dry_run_label}')
working_directory = borgmatic.config.paths.get_working_directory(config)
@@ -327,22 +337,7 @@ def run_create(
borgmatic_runtime_directory,
local_path=local_path,
remote_path=remote_path,
progress=(
config.get('progress')
if create_arguments.progress is None
else create_arguments.progress
),
stats=(
config.get('statistics')
if create_arguments.stats is None
else create_arguments.stats
),
json=create_arguments.json,
list_files=(
config.get('list_details')
if create_arguments.list_files is None
else create_arguments.list_files
),
stream_processes=stream_processes,
)
-5
View File
@@ -43,10 +43,5 @@ def run_export_tar(
local_path=local_path,
remote_path=remote_path,
tar_filter=export_tar_arguments.tar_filter,
list_files=(
config.get('list_details')
if export_tar_arguments.list_files is None
else export_tar_arguments.list_files
),
strip_components=export_tar_arguments.strip_components,
)
-5
View File
@@ -45,9 +45,4 @@ def run_extract(
remote_path=remote_path,
destination_path=extract_arguments.destination,
strip_components=extract_arguments.strip_components,
progress=(
config.get('progress')
if extract_arguments.progress is None
else extract_arguments.progress
),
)
+6
View File
@@ -17,7 +17,13 @@ def run_transfer(
'''
Run the "transfer" action for the given repository.
'''
if transfer_arguments.archive and config.get('match_archives'):
raise ValueError(
'With the transfer action, only one of --archive and --match-archives/match_archives can be used.'
)
logger.info('Transferring archives to repository')
borgmatic.borg.transfer.transfer_archives(
global_arguments.dry_run,
repository['path'],
+5 -6
View File
@@ -32,7 +32,7 @@ def make_archive_filter_flags(local_borg_version, config, checks, check_argument
if prefix
else (
flags.make_match_archives_flags(
check_arguments.match_archives or config.get('match_archives'),
config.get('match_archives'),
config.get('archive_name_format'),
local_borg_version,
)
@@ -143,9 +143,6 @@ def check_archives(
umask = config.get('umask')
borg_exit_codes = config.get('borg_exit_codes')
working_directory = borgmatic.config.paths.get_working_directory(config)
progress = (
config.get('progress') if check_arguments.progress is None else check_arguments.progress
)
if 'data' in checks:
checks.add('archives')
@@ -173,7 +170,7 @@ def check_archives(
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ verbosity_flags
+ (('--progress',) if progress else ())
+ (('--progress',) if config.get('progress') else ())
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
+ flags.make_repository_flags(repository_path, local_borg_version)
)
@@ -182,7 +179,9 @@ def check_archives(
full_command,
# The Borg repair option triggers an interactive prompt, which won't work when output is
# captured. And progress messes with the terminal directly.
output_file=(DO_NOT_CAPTURE if check_arguments.repair or progress else None),
output_file=(
DO_NOT_CAPTURE if check_arguments.repair or config.get('progress') else None
),
environment=environment.make_environment(config),
working_directory=working_directory,
borg_local_path=local_path,
+2 -3
View File
@@ -15,9 +15,7 @@ def compact_segments(
global_arguments,
local_path='borg',
remote_path=None,
progress=False,
cleanup_commits=False,
threshold=None,
):
'''
Given dry-run flag, a local or remote repository path, a configuration dict, and the local Borg
@@ -26,6 +24,7 @@ def compact_segments(
umask = config.get('umask', None)
lock_wait = config.get('lock_wait', None)
extra_borg_options = config.get('extra_borg_options', {}).get('compact', '')
threshold = config.get('compact_threshold')
full_command = (
(local_path, 'compact')
@@ -33,7 +32,7 @@ def compact_segments(
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--progress',) if progress else ())
+ (('--progress',) if config.get('progress') else ())
+ (('--cleanup-commits',) if cleanup_commits else ())
+ (('--threshold', str(threshold)) if threshold else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+5 -12
View File
@@ -213,9 +213,7 @@ def make_base_create_command(
borgmatic_runtime_directory,
local_path='borg',
remote_path=None,
progress=False,
json=False,
list_files=False,
stream_processes=None,
):
'''
@@ -293,7 +291,7 @@ def make_base_create_command(
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (
('--list', '--filter', list_filter_flags)
if list_files and not json and not progress
if config.get('list_details') and not json and not config.get('progress')
else ()
)
+ (('--dry-run',) if dry_run else ())
@@ -361,10 +359,7 @@ def create_archive(
borgmatic_runtime_directory,
local_path='borg',
remote_path=None,
progress=False,
stats=False,
json=False,
list_files=False,
stream_processes=None,
):
'''
@@ -389,28 +384,26 @@ def create_archive(
borgmatic_runtime_directory,
local_path,
remote_path,
progress,
json,
list_files,
stream_processes,
)
if json:
output_log_level = None
elif list_files or (stats and not dry_run):
elif config.get('list_details') or (config.get('statistics') and not dry_run):
output_log_level = logging.ANSWER
else:
output_log_level = logging.INFO
# The progress output isn't compatible with captured and logged output, as progress messes with
# the terminal directly.
output_file = DO_NOT_CAPTURE if progress else None
output_file = DO_NOT_CAPTURE if config.get('progress') else None
create_flags += (
(('--info',) if logger.getEffectiveLevel() == logging.INFO and not json else ())
+ (('--stats',) if stats and not json and not dry_run else ())
+ (('--stats',) if config.get('statistics') and not json and not dry_run else ())
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) and not json else ())
+ (('--progress',) if progress else ())
+ (('--progress',) if config.get('progress') else ())
+ (('--json',) if json else ())
)
borg_exit_codes = config.get('borg_exit_codes')
+11 -10
View File
@@ -34,14 +34,7 @@ def make_delete_command(
+ borgmatic.borg.flags.make_flags('umask', config.get('umask'))
+ borgmatic.borg.flags.make_flags('log-json', global_arguments.log_json)
+ borgmatic.borg.flags.make_flags('lock-wait', config.get('lock_wait'))
+ borgmatic.borg.flags.make_flags(
'list',
(
config.get('list_details')
if delete_arguments.list_archives is None
else delete_arguments.list_archives
),
)
+ borgmatic.borg.flags.make_flags('list', config.get('list_details'))
+ (
(('--force',) + (('--force',) if delete_arguments.force >= 2 else ()))
if delete_arguments.force
@@ -55,9 +48,17 @@ def make_delete_command(
local_borg_version=local_borg_version,
default_archive_name_format='*',
)
+ (('--stats',) if config.get('statistics') else ())
+ borgmatic.borg.flags.make_flags_from_arguments(
delete_arguments,
excludes=('list_archives', 'force', 'match_archives', 'archive', 'repository'),
excludes=(
'list_details',
'statistics',
'force',
'match_archives',
'archive',
'repository',
),
)
+ borgmatic.borg.flags.make_repository_flags(repository['path'], local_borg_version)
)
@@ -105,7 +106,7 @@ def delete_archives(
repo_delete_arguments = argparse.Namespace(
repository=repository['path'],
list_archives=delete_arguments.list_archives,
list_details=delete_arguments.list_details,
force=delete_arguments.force,
cache_only=delete_arguments.cache_only,
keep_security_info=delete_arguments.keep_security_info,
+2 -3
View File
@@ -20,7 +20,6 @@ def export_tar_archive(
local_path='borg',
remote_path=None,
tar_filter=None,
list_files=False,
strip_components=None,
):
'''
@@ -43,7 +42,7 @@ def export_tar_archive(
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ (('--list',) if list_files else ())
+ (('--list',) if config.get('list_details') else ())
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
+ (('--dry-run',) if dry_run else ())
+ (('--tar-filter', tar_filter) if tar_filter else ())
@@ -57,7 +56,7 @@ def export_tar_archive(
+ (tuple(paths) if paths else ())
)
if list_files:
if config.get('list_details'):
output_log_level = logging.ANSWER
else:
output_log_level = logging.INFO
+4 -5
View File
@@ -77,7 +77,6 @@ def extract_archive(
remote_path=None,
destination_path=None,
strip_components=None,
progress=False,
extract_to_stdout=False,
):
'''
@@ -92,8 +91,8 @@ def extract_archive(
umask = config.get('umask', None)
lock_wait = config.get('lock_wait', None)
if progress and extract_to_stdout:
raise ValueError('progress and extract_to_stdout cannot both be set')
if config.get('progress') and extract_to_stdout:
raise ValueError('progress and extract to stdout cannot both be set')
if feature.available(feature.Feature.NUMERIC_IDS, local_borg_version):
numeric_ids_flags = ('--numeric-ids',) if config.get('numeric_ids') else ()
@@ -128,7 +127,7 @@ def extract_archive(
+ (('--debug', '--list', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
+ (('--dry-run',) if dry_run else ())
+ (('--strip-components', str(strip_components)) if strip_components else ())
+ (('--progress',) if progress else ())
+ (('--progress',) if config.get('progress') else ())
+ (('--stdout',) if extract_to_stdout else ())
+ flags.make_repository_archive_flags(
# Make the repository path absolute so the destination directory used below via changing
@@ -148,7 +147,7 @@ def extract_archive(
# The progress output isn't compatible with captured and logged output, as progress messes with
# the terminal directly.
if progress:
if config.get('progress'):
return execute_command(
full_command,
output_file=DO_NOT_CAPTURE,
+1 -3
View File
@@ -48,9 +48,7 @@ def make_info_command(
if info_arguments.prefix
else (
flags.make_match_archives_flags(
info_arguments.match_archives
or info_arguments.archive
or config.get('match_archives'),
info_arguments.archive or config.get('match_archives'),
config.get('archive_name_format'),
local_borg_version,
)
+5 -11
View File
@@ -41,7 +41,7 @@ def make_prune_flags(config, prune_arguments, local_borg_version):
if prefix
else (
flags.make_match_archives_flags(
prune_arguments.match_archives or config.get('match_archives'),
config.get('match_archives'),
config.get('archive_name_format'),
local_borg_version,
)
@@ -66,12 +66,6 @@ def prune_archives(
borgmatic.logger.add_custom_log_levels()
umask = config.get('umask', None)
lock_wait = config.get('lock_wait', None)
stats = config.get('statistics') if prune_arguments.stats is None else prune_arguments.stats
list_archives = (
config.get('list_details')
if prune_arguments.list_archives is None
else prune_arguments.list_archives
)
extra_borg_options = config.get('extra_borg_options', {}).get('prune', '')
full_command = (
@@ -83,7 +77,7 @@ def prune_archives(
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (
('--stats',)
if stats
if config.get('statistics')
and not dry_run
and not feature.available(feature.Feature.NO_PRUNE_STATS, local_borg_version)
else ()
@@ -91,16 +85,16 @@ def prune_archives(
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ flags.make_flags_from_arguments(
prune_arguments,
excludes=('repository', 'match_archives', 'stats', 'list_archives'),
excludes=('repository', 'match_archives', 'statistics', 'list_details'),
)
+ (('--list',) if list_archives else ())
+ (('--list',) if config.get('list_details') else ())
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
+ (('--dry-run',) if dry_run else ())
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
+ flags.make_repository_flags(repository_path, local_borg_version)
)
if stats or list_archives:
if config.get('statistics') or config.get('list_details'):
output_log_level = logging.ANSWER
else:
output_log_level = logging.INFO
+2 -7
View File
@@ -38,9 +38,6 @@ def recreate_archive(
patterns_file = write_patterns_file(
patterns, borgmatic.config.paths.get_working_directory(config)
)
list_files = (
config.get('list_details') if recreate_arguments.list is None else recreate_arguments.list
)
recreate_command = (
(local_path, 'recreate')
@@ -56,7 +53,7 @@ def recreate_archive(
'--filter',
make_list_filter_flags(local_borg_version, global_arguments.dry_run),
)
if list_files
if config.get('list_details')
else ()
)
# Flag --target works only for a single archive.
@@ -71,12 +68,10 @@ def recreate_archive(
+ (('--chunker-params', chunker_params) if chunker_params else ())
+ (
flags.make_match_archives_flags(
recreate_arguments.match_archives or archive or config.get('match_archives'),
archive or config.get('match_archives'),
config.get('archive_name_format'),
local_borg_version,
)
if recreate_arguments.match_archives
else ()
)
+ (('--recompress', recompress) if recompress else ())
+ exclude_flags
+2 -2
View File
@@ -39,14 +39,14 @@ def make_repo_delete_command(
+ borgmatic.borg.flags.make_flags('umask', config.get('umask'))
+ borgmatic.borg.flags.make_flags('log-json', global_arguments.log_json)
+ borgmatic.borg.flags.make_flags('lock-wait', config.get('lock_wait'))
+ borgmatic.borg.flags.make_flags('list', repo_delete_arguments.list_archives)
+ borgmatic.borg.flags.make_flags('list', config.get('list_details'))
+ (
(('--force',) + (('--force',) if repo_delete_arguments.force >= 2 else ()))
if repo_delete_arguments.force
else ()
)
+ borgmatic.borg.flags.make_flags_from_arguments(
repo_delete_arguments, excludes=('list_archives', 'force', 'repository')
repo_delete_arguments, excludes=('list_details', 'force', 'repository')
)
+ borgmatic.borg.flags.make_repository_flags(repository['path'], local_borg_version)
)
+1 -1
View File
@@ -113,7 +113,7 @@ def make_repo_list_command(
if repo_list_arguments.prefix
else (
flags.make_match_archives_flags(
repo_list_arguments.match_archives or config.get('match_archives'),
config.get('match_archives'),
config.get('archive_name_format'),
local_borg_version,
)
+2 -9
View File
@@ -40,9 +40,7 @@ def transfer_archives(
)
or (
flags.make_match_archives_flags(
transfer_arguments.match_archives
or transfer_arguments.archive
or config.get('match_archives'),
transfer_arguments.archive or config.get('match_archives'),
config.get('archive_name_format'),
local_borg_version,
)
@@ -52,16 +50,11 @@ def transfer_archives(
+ flags.make_flags('other-repo', transfer_arguments.source_repository)
+ flags.make_flags('dry-run', dry_run)
)
progress = (
config.get('progress')
if transfer_arguments.progress is None
else transfer_arguments.progress
)
return execute_command(
full_command,
output_log_level=logging.ANSWER,
output_file=DO_NOT_CAPTURE if progress else None,
output_file=DO_NOT_CAPTURE if config.get('progress') else None,
environment=environment.make_environment(config),
working_directory=borgmatic.config.paths.get_working_directory(config),
borg_local_path=local_path,
+39 -40
View File
@@ -709,7 +709,7 @@ def make_parsers(schema, unparsed_arguments):
)
transfer_group.add_argument(
'--progress',
default=False,
default=None,
action='store_true',
help='Display progress as each archive is transferred',
)
@@ -776,13 +776,17 @@ def make_parsers(schema, unparsed_arguments):
)
prune_group.add_argument(
'--stats',
dest='stats',
default=False,
dest='statistics',
default=None,
action='store_true',
help='Display statistics of the pruned archive [Borg 1 only]',
)
prune_group.add_argument(
'--list', dest='list_archives', action='store_true', help='List archives kept/pruned'
'--list',
dest='list_details',
default=None,
action='store_true',
help='List archives kept/pruned',
)
prune_group.add_argument(
'--oldest',
@@ -820,8 +824,7 @@ def make_parsers(schema, unparsed_arguments):
)
compact_group.add_argument(
'--progress',
dest='progress',
default=False,
default=None,
action='store_true',
help='Display progress as each segment is compacted',
)
@@ -835,7 +838,7 @@ def make_parsers(schema, unparsed_arguments):
compact_group.add_argument(
'--threshold',
type=int,
dest='threshold',
dest='compact_threshold',
help='Minimum saved space percentage threshold for compacting a segment, defaults to 10',
)
compact_group.add_argument(
@@ -856,20 +859,24 @@ def make_parsers(schema, unparsed_arguments):
)
create_group.add_argument(
'--progress',
dest='progress',
default=False,
default=None,
action='store_true',
help='Display progress for each file as it is backed up',
)
create_group.add_argument(
'--stats',
dest='stats',
default=False,
dest='statistics',
default=None,
action='store_true',
help='Display statistics of archive',
)
create_group.add_argument(
'--list', '--files', dest='list_files', action='store_true', help='Show per-file details'
'--list',
'--files',
dest='list_details',
default=None,
action='store_true',
help='Show per-file details',
)
create_group.add_argument(
'--json', dest='json', default=False, action='store_true', help='Output results as JSON'
@@ -890,8 +897,7 @@ def make_parsers(schema, unparsed_arguments):
)
check_group.add_argument(
'--progress',
dest='progress',
default=False,
default=None,
action='store_true',
help='Display progress for each file as it is checked',
)
@@ -948,12 +954,15 @@ def make_parsers(schema, unparsed_arguments):
)
delete_group.add_argument(
'--list',
dest='list_archives',
dest='list_details',
default=None,
action='store_true',
help='Show details for the deleted archives',
)
delete_group.add_argument(
'--stats',
dest='statistics',
default=None,
action='store_true',
help='Display statistics for the deleted archives',
)
@@ -1058,8 +1067,7 @@ def make_parsers(schema, unparsed_arguments):
)
extract_group.add_argument(
'--progress',
dest='progress',
default=False,
default=None,
action='store_true',
help='Display progress for each file as it is extracted',
)
@@ -1134,8 +1142,7 @@ def make_parsers(schema, unparsed_arguments):
)
config_bootstrap_group.add_argument(
'--progress',
dest='progress',
default=False,
default=None,
action='store_true',
help='Display progress for each file as it is extracted',
)
@@ -1228,7 +1235,12 @@ def make_parsers(schema, unparsed_arguments):
'--tar-filter', help='Name of filter program to pipe data through'
)
export_tar_group.add_argument(
'--list', '--files', dest='list_files', action='store_true', help='Show per-file details'
'--list',
'--files',
dest='list_details',
default=None,
action='store_true',
help='Show per-file details',
)
export_tar_group.add_argument(
'--strip-components',
@@ -1339,7 +1351,8 @@ def make_parsers(schema, unparsed_arguments):
)
repo_delete_group.add_argument(
'--list',
dest='list_archives',
dest='list_details',
default=None,
action='store_true',
help='Show details for the archives in the given repository',
)
@@ -1770,7 +1783,11 @@ def make_parsers(schema, unparsed_arguments):
help='Archive name, hash, or series to recreate',
)
recreate_group.add_argument(
'--list', dest='list', action='store_true', help='Show per-file details'
'--list',
dest='list_details',
default=None,
action='store_true',
help='Show per-file details',
)
recreate_group.add_argument(
'--target',
@@ -1865,15 +1882,6 @@ def parse_arguments(schema, *unparsed_arguments):
f"Unrecognized argument{'s' if len(unknown_arguments) > 1 else ''}: {' '.join(unknown_arguments)}"
)
if 'create' in arguments and arguments['create'].list_files and arguments['create'].progress:
raise ValueError(
'With the create action, only one of --list (--files) and --progress flags can be used.'
)
if 'create' in arguments and arguments['create'].list_files and arguments['create'].json:
raise ValueError(
'With the create action, only one of --list (--files) and --json flags can be used.'
)
if (
('list' in arguments and 'repo-info' in arguments and arguments['list'].json)
or ('list' in arguments and 'info' in arguments and arguments['list'].json)
@@ -1881,15 +1889,6 @@ def parse_arguments(schema, *unparsed_arguments):
):
raise ValueError('With the --json flag, multiple actions cannot be used together.')
if (
'transfer' in arguments
and arguments['transfer'].archive
and arguments['transfer'].match_archives
):
raise ValueError(
'With the transfer action, only one of --archive and --match-archives flags can be used.'
)
if 'list' in arguments and (arguments['list'].prefix and arguments['list'].match_archives):
raise ValueError(
'With the list action, only one of --prefix or --match-archives flags can be used.'
+9 -9
View File
@@ -600,14 +600,14 @@ def run_actions(
)
def load_configurations(config_filenames, global_arguments, overrides=None, resolve_env=True):
def load_configurations(config_filenames, arguments, overrides=None, resolve_env=True):
'''
Given a sequence of configuration filenames, global arguments as an argparse.Namespace, a
sequence of configuration file override strings in the form of "option.suboption=value", and
whether to resolve environment variables, load and validate each configuration file. Return the
results as a tuple of: dict of configuration filename to corresponding parsed configuration, a
sequence of paths for all loaded configuration files (including includes), and a sequence of
logging.LogRecord instances containing any parse errors.
Given a sequence of configuration filenames, arguments as a dict from action name to
argparse.Namespace, a sequence of configuration file override strings in the form of
"option.suboption=value", and whether to resolve environment variables, load and validate each
configuration file. Return the results as a tuple of: dict of configuration filename to
corresponding parsed configuration, a sequence of paths for all loaded configuration files
(including includes), and a sequence of logging.LogRecord instances containing any parse errors.
Log records are returned here instead of being logged directly because logging isn't yet
initialized at this point! (Although with the Delayed_logging_handler now in place, maybe this
@@ -635,7 +635,7 @@ def load_configurations(config_filenames, global_arguments, overrides=None, reso
configs[config_filename], paths, parse_logs = validate.parse_configuration(
config_filename,
validate.schema_filename(),
global_arguments,
arguments,
overrides,
resolve_env,
)
@@ -1010,7 +1010,7 @@ def main(extra_summary_logs=[]): # pragma: no cover
config_filenames = tuple(collect.collect_config_filenames(global_arguments.config_paths))
configs, config_paths, parse_logs = load_configurations(
config_filenames,
global_arguments,
arguments,
global_arguments.overrides,
resolve_env=global_arguments.resolve_env and not validate,
)
+7 -6
View File
@@ -160,15 +160,16 @@ def prepare_arguments_for_config(global_arguments, schema):
return tuple(prepared_values)
def apply_arguments_to_config(config, schema, global_arguments): # pragma: no cover
def apply_arguments_to_config(config, schema, arguments):
'''
Given a configuration dict, a corresponding configuration schema dict, and global arguments as
an argparse.Namespace, set those given argument values into their corresponding configuration
options in the configuration dict.
Given a configuration dict, a corresponding configuration schema dict, and arguments as a dict
from action name to argparse.Namespace, set those given argument values into their corresponding
configuration options in the configuration dict.
This supports argument flags of the from "--foo.bar.baz" where each dotted component is a nested
configuration object. Additionally, flags like "--foo.bar[0].baz" are supported to update a list
element in the configuration.
'''
for keys, value in prepare_arguments_for_config(global_arguments, schema):
set_values(config, keys, value)
for action_arguments in arguments.values():
for keys, value in prepare_arguments_for_config(action_arguments, schema):
set_values(config, keys, value)
+6 -6
View File
@@ -97,14 +97,14 @@ def apply_logical_validation(config_filename, parsed_configuration):
def parse_configuration(
config_filename, schema_filename, global_arguments, overrides=None, resolve_env=True
config_filename, schema_filename, arguments, overrides=None, resolve_env=True
):
'''
Given the path to a config filename in YAML format, the path to a schema filename in a YAML
rendition of JSON Schema format, global arguments as an argparse.Namespace, a sequence of
configuration file override strings in the form of "option.suboption=value", and whether to
resolve environment variables, return the parsed configuration as a data structure of nested
dicts and lists corresponding to the schema. Example return value.
rendition of JSON Schema format, arguments as dict from action name to argparse.Namespace, a
sequence of configuration file override strings in the form of "option.suboption=value", and
whether to resolve environment variables, return the parsed configuration as a data structure of
nested dicts and lists corresponding to the schema. Example return value.
Example return value:
@@ -129,7 +129,7 @@ def parse_configuration(
except (ruamel.yaml.error.YAMLError, RecursionError) as error:
raise Validation_error(config_filename, (str(error),))
borgmatic.config.arguments.apply_arguments_to_config(config, schema, global_arguments)
borgmatic.config.arguments.apply_arguments_to_config(config, schema, arguments)
override.apply_overrides(config, schema, overrides)
constants.apply_constants(config, config.get('constants') if config else {})
+4 -34
View File
@@ -271,11 +271,11 @@ def test_parse_arguments_with_no_actions_passes_argument_to_relevant_actions():
arguments = module.parse_arguments({}, '--stats', '--list')
assert 'prune' in arguments
assert arguments['prune'].stats
assert arguments['prune'].list_archives
assert arguments['prune'].statistics
assert arguments['prune'].list_details
assert 'create' in arguments
assert arguments['create'].stats
assert arguments['create'].list_files
assert arguments['create'].statistics
assert arguments['create'].list_details
assert 'check' in arguments
@@ -557,20 +557,6 @@ def test_parse_arguments_with_list_flag_but_no_relevant_action_raises_value_erro
module.parse_arguments({}, '--list', 'repo-create')
def test_parse_arguments_disallows_list_with_progress_for_create_action():
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
with pytest.raises(ValueError):
module.parse_arguments({}, 'create', '--list', '--progress')
def test_parse_arguments_disallows_list_with_json_for_create_action():
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
with pytest.raises(ValueError):
module.parse_arguments({}, 'create', '--list', '--json')
def test_parse_arguments_allows_json_with_list_or_info():
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
@@ -599,22 +585,6 @@ def test_parse_arguments_disallows_json_with_both_repo_info_and_info():
module.parse_arguments({}, 'repo-info', 'info', '--json')
def test_parse_arguments_disallows_transfer_with_both_archive_and_match_archives():
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
with pytest.raises(ValueError):
module.parse_arguments(
{},
'transfer',
'--source-repository',
'source.borg',
'--archive',
'foo',
'--match-archives',
'sh:*bar',
)
def test_parse_arguments_disallows_list_with_both_prefix_and_match_archives():
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
+13 -11
View File
@@ -59,7 +59,7 @@ def test_parse_configuration_transforms_file_into_mapping():
)
config, config_paths, logs = module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
assert config == {
@@ -89,7 +89,7 @@ def test_parse_configuration_passes_through_quoted_punctuation():
)
config, config_paths, logs = module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
assert config == {
@@ -123,7 +123,9 @@ def test_parse_configuration_with_schema_lacking_examples_does_not_raise():
''',
)
module.parse_configuration('/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock())
module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
def test_parse_configuration_inlines_include_inside_deprecated_section():
@@ -150,7 +152,7 @@ def test_parse_configuration_inlines_include_inside_deprecated_section():
builtins.should_receive('open').with_args('/tmp/include.yaml').and_return(include_file)
config, config_paths, logs = module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
assert config == {
@@ -188,7 +190,7 @@ def test_parse_configuration_merges_include():
builtins.should_receive('open').with_args('/tmp/include.yaml').and_return(include_file)
config, config_paths, logs = module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
assert config == {
@@ -205,7 +207,7 @@ def test_parse_configuration_merges_include():
def test_parse_configuration_raises_for_missing_config_file():
with pytest.raises(FileNotFoundError):
module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
@@ -219,7 +221,7 @@ def test_parse_configuration_raises_for_missing_schema_file():
with pytest.raises(FileNotFoundError):
module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
@@ -228,7 +230,7 @@ def test_parse_configuration_raises_for_syntax_error():
with pytest.raises(ValueError):
module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
@@ -243,7 +245,7 @@ def test_parse_configuration_raises_for_validation_error():
with pytest.raises(module.Validation_error):
module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
@@ -263,7 +265,7 @@ def test_parse_configuration_applies_overrides():
config, config_paths, logs = module.parse_configuration(
'/tmp/config.yaml',
'/tmp/schema.yaml',
global_arguments=flexmock(),
arguments={'global': flexmock()},
overrides=['local_path=borg2'],
)
@@ -293,7 +295,7 @@ def test_parse_configuration_applies_normalization_after_environment_variable_in
flexmock(os).should_receive('getenv').replace_with(lambda variable_name, default: default)
config, config_paths, logs = module.parse_configuration(
'/tmp/config.yaml', '/tmp/schema.yaml', global_arguments=flexmock()
'/tmp/config.yaml', '/tmp/schema.yaml', arguments={'global': flexmock()}
)
assert config == {
@@ -267,7 +267,6 @@ def test_run_bootstrap_does_not_raise():
archive='archive',
destination='dest',
strip_components=1,
progress=False,
user_runtime_directory='/borgmatic',
ssh_command=None,
local_path='borg7',
@@ -307,7 +306,6 @@ def test_run_bootstrap_translates_ssh_command_argument_to_config():
archive='archive',
destination='dest',
strip_components=1,
progress=False,
user_runtime_directory='/borgmatic',
ssh_command='ssh -i key',
local_path='borg7',
@@ -339,7 +337,6 @@ def test_run_bootstrap_translates_ssh_command_argument_to_config():
extract_to_stdout=False,
destination_path='dest',
strip_components=1,
progress=False,
local_path='borg7',
remote_path='borg8',
).and_return(extract_process).once()
+1 -6
View File
@@ -577,7 +577,6 @@ def test_collect_spot_check_source_paths_parses_borg_output():
borgmatic_runtime_directory='/run/borgmatic',
local_path=object,
remote_path=object,
list_files=True,
stream_processes=True,
).and_return((('borg', 'create'), ('repo::archive',), flexmock()))
flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
@@ -625,7 +624,6 @@ def test_collect_spot_check_source_paths_passes_through_stream_processes_false()
borgmatic_runtime_directory='/run/borgmatic',
local_path=object,
remote_path=object,
list_files=True,
stream_processes=False,
).and_return((('borg', 'create'), ('repo::archive',), flexmock()))
flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
@@ -673,7 +671,6 @@ def test_collect_spot_check_source_paths_without_working_directory_parses_borg_o
borgmatic_runtime_directory='/run/borgmatic',
local_path=object,
remote_path=object,
list_files=True,
stream_processes=True,
).and_return((('borg', 'create'), ('repo::archive',), flexmock()))
flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
@@ -721,7 +718,6 @@ def test_collect_spot_check_source_paths_skips_directories():
borgmatic_runtime_directory='/run/borgmatic',
local_path=object,
remote_path=object,
list_files=True,
stream_processes=True,
).and_return((('borg', 'create'), ('repo::archive',), flexmock()))
flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
@@ -860,14 +856,13 @@ def test_collect_spot_check_source_paths_uses_working_directory():
flexmock(module.borgmatic.borg.create).should_receive('make_base_create_command').with_args(
dry_run=True,
repository_path='repo',
config=object,
config={'working_directory': '/working/dir', 'list_details': True},
patterns=[Pattern('foo'), Pattern('bar')],
local_borg_version=object,
global_arguments=object,
borgmatic_runtime_directory='/run/borgmatic',
local_path=object,
remote_path=object,
list_files=True,
stream_processes=True,
).and_return((('borg', 'create'), ('repo::archive',), flexmock()))
flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
+12 -81
View File
@@ -9,7 +9,10 @@ def test_compact_actions_calls_hooks_for_configured_repository():
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()
flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').once()
compact_arguments = flexmock(
repository=None, progress=flexmock(), cleanup_commits=flexmock(), threshold=flexmock()
repository=None,
progress=flexmock(),
cleanup_commits=flexmock(),
compact_threshold=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
@@ -34,7 +37,10 @@ def test_compact_runs_with_selected_repository():
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').once()
compact_arguments = flexmock(
repository=flexmock(), progress=flexmock(), cleanup_commits=flexmock(), threshold=flexmock()
repository=flexmock(),
progress=flexmock(),
cleanup_commits=flexmock(),
compact_threshold=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
@@ -51,84 +57,6 @@ def test_compact_runs_with_selected_repository():
)
def test_compact_favors_flags_over_config():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
'repositories_match'
).once().and_return(True)
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').with_args(
object,
object,
object,
object,
object,
local_path=object,
remote_path=object,
progress=False,
cleanup_commits=object,
threshold=15,
).once()
compact_arguments = flexmock(
repository=flexmock(),
progress=False,
cleanup_commits=flexmock(),
threshold=15,
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
module.run_compact(
config_filename='test.yaml',
repository={'path': 'repo'},
config={'progress': True, 'compact_threshold': 20},
local_borg_version=None,
compact_arguments=compact_arguments,
global_arguments=global_arguments,
dry_run_label='',
local_path=None,
remote_path=None,
)
def test_compact_favors_defaults_to_config():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
'repositories_match'
).once().and_return(True)
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').with_args(
object,
object,
object,
object,
object,
local_path=object,
remote_path=object,
progress=True,
cleanup_commits=object,
threshold=20,
).once()
compact_arguments = flexmock(
repository=flexmock(),
progress=None,
cleanup_commits=flexmock(),
threshold=None,
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
module.run_compact(
config_filename='test.yaml',
repository={'path': 'repo'},
config={'progress': True, 'compact_threshold': 20},
local_borg_version=None,
compact_arguments=compact_arguments,
global_arguments=global_arguments,
dry_run_label='',
local_path=None,
remote_path=None,
)
def test_compact_bails_if_repository_does_not_match():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
@@ -137,7 +65,10 @@ def test_compact_bails_if_repository_does_not_match():
).once().and_return(False)
flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').never()
compact_arguments = flexmock(
repository=flexmock(), progress=flexmock(), cleanup_commits=flexmock(), threshold=flexmock()
repository=flexmock(),
progress=flexmock(),
cleanup_commits=flexmock(),
compact_threshold=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+74 -120
View File
@@ -443,9 +443,9 @@ def test_run_create_executes_and_calls_hooks_for_configured_repository():
create_arguments = flexmock(
repository=None,
progress=flexmock(),
stats=flexmock(),
statistics=flexmock(),
json=False,
list_files=flexmock(),
list_details=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
@@ -484,9 +484,9 @@ def test_run_create_runs_with_selected_repository():
create_arguments = flexmock(
repository=flexmock(),
progress=flexmock(),
stats=flexmock(),
statistics=flexmock(),
json=False,
list_files=flexmock(),
list_details=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
@@ -506,118 +506,6 @@ def test_run_create_runs_with_selected_repository():
)
def test_run_create_favors_flags_over_config():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
'repositories_match'
).once().and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
flexmock()
)
flexmock(module.borgmatic.borg.create).should_receive('create_archive').with_args(
object,
object,
object,
object,
object,
object,
object,
local_path=object,
remote_path=object,
progress=False,
stats=False,
json=object,
list_files=False,
stream_processes=object,
).once()
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return({})
flexmock(module.borgmatic.hooks.dispatch).should_receive(
'call_hooks_even_if_unconfigured'
).and_return({})
flexmock(module).should_receive('collect_patterns').and_return(())
flexmock(module).should_receive('process_patterns').and_return([])
flexmock(module.os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
create_arguments = flexmock(
repository=flexmock(),
progress=False,
stats=False,
json=False,
list_files=False,
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
list(
module.run_create(
config_filename='test.yaml',
repository={'path': 'repo'},
config={'progress': True, 'statistics': True, 'list_details': True},
config_paths=['/tmp/test.yaml'],
local_borg_version=None,
create_arguments=create_arguments,
global_arguments=global_arguments,
dry_run_label='',
local_path=None,
remote_path=None,
)
)
def test_run_create_defaults_to_config():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
'repositories_match'
).once().and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
flexmock()
)
flexmock(module.borgmatic.borg.create).should_receive('create_archive').with_args(
object,
object,
object,
object,
object,
object,
object,
local_path=object,
remote_path=object,
progress=True,
stats=True,
json=object,
list_files=True,
stream_processes=object,
).once()
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return({})
flexmock(module.borgmatic.hooks.dispatch).should_receive(
'call_hooks_even_if_unconfigured'
).and_return({})
flexmock(module).should_receive('collect_patterns').and_return(())
flexmock(module).should_receive('process_patterns').and_return([])
flexmock(module.os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
create_arguments = flexmock(
repository=flexmock(),
progress=True,
stats=True,
json=False,
list_files=True,
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
list(
module.run_create(
config_filename='test.yaml',
repository={'path': 'repo'},
config={'progress': True, 'statistics': True, 'list_details': True},
config_paths=['/tmp/test.yaml'],
local_borg_version=None,
create_arguments=create_arguments,
global_arguments=global_arguments,
dry_run_label='',
local_path=None,
remote_path=None,
)
)
def test_run_create_bails_if_repository_does_not_match():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
@@ -628,9 +516,9 @@ def test_run_create_bails_if_repository_does_not_match():
create_arguments = flexmock(
repository=flexmock(),
progress=flexmock(),
stats=flexmock(),
statistics=flexmock(),
json=False,
list_files=flexmock(),
list_details=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
@@ -650,6 +538,72 @@ def test_run_create_bails_if_repository_does_not_match():
)
def test_run_create_with_both_list_and_json_errors():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
'repositories_match'
).once().and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').never()
flexmock(module.borgmatic.borg.create).should_receive('create_archive').never()
create_arguments = flexmock(
repository=flexmock(),
progress=flexmock(),
statistics=flexmock(),
json=True,
list_details=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
with pytest.raises(ValueError):
list(
module.run_create(
config_filename='test.yaml',
repository={'path': 'repo'},
config={'list_details': True},
config_paths=['/tmp/test.yaml'],
local_borg_version=None,
create_arguments=create_arguments,
global_arguments=global_arguments,
dry_run_label='',
local_path=None,
remote_path=None,
)
)
def test_run_create_with_both_list_and_progress_errors():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
'repositories_match'
).once().and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').never()
flexmock(module.borgmatic.borg.create).should_receive('create_archive').never()
create_arguments = flexmock(
repository=flexmock(),
progress=flexmock(),
statistics=flexmock(),
json=False,
list_details=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
with pytest.raises(ValueError):
list(
module.run_create(
config_filename='test.yaml',
repository={'path': 'repo'},
config={'list_details': True, 'progress': True},
config_paths=['/tmp/test.yaml'],
local_borg_version=None,
create_arguments=create_arguments,
global_arguments=global_arguments,
dry_run_label='',
local_path=None,
remote_path=None,
)
)
def test_run_create_produces_json():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
@@ -673,9 +627,9 @@ def test_run_create_produces_json():
create_arguments = flexmock(
repository=flexmock(),
progress=flexmock(),
stats=flexmock(),
statistics=flexmock(),
json=True,
list_files=flexmock(),
list_details=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+3 -5
View File
@@ -13,7 +13,7 @@ def test_run_export_tar_does_not_raise():
paths=flexmock(),
destination=flexmock(),
tar_filter=flexmock(),
list_files=flexmock(),
list_details=flexmock(),
strip_components=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
@@ -44,7 +44,6 @@ def test_run_export_tar_favors_flags_over_config():
local_path=object,
remote_path=object,
tar_filter=object,
list_files=False,
strip_components=object,
).once()
export_tar_arguments = flexmock(
@@ -53,7 +52,7 @@ def test_run_export_tar_favors_flags_over_config():
paths=flexmock(),
destination=flexmock(),
tar_filter=flexmock(),
list_files=False,
list_details=False,
strip_components=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
@@ -84,7 +83,6 @@ def test_run_export_tar_defaults_to_config():
local_path=object,
remote_path=object,
tar_filter=object,
list_files=True,
strip_components=object,
).once()
export_tar_arguments = flexmock(
@@ -93,7 +91,7 @@ def test_run_export_tar_defaults_to_config():
paths=flexmock(),
destination=flexmock(),
tar_filter=flexmock(),
list_files=None,
list_details=None,
strip_components=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
-2
View File
@@ -44,7 +44,6 @@ def test_run_extract_favors_flags_over_config():
remote_path=object,
destination_path=object,
strip_components=object,
progress=False,
).once()
extract_arguments = flexmock(
paths=flexmock(),
@@ -83,7 +82,6 @@ def test_run_extract_defaults_to_config():
remote_path=object,
destination_path=object,
strip_components=object,
progress=True,
).once()
extract_arguments = flexmock(
paths=flexmock(),
+7 -3
View File
@@ -7,7 +7,7 @@ def test_run_prune_calls_hooks_for_configured_repository():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()
flexmock(module.borgmatic.borg.prune).should_receive('prune_archives').once()
prune_arguments = flexmock(repository=None, stats=flexmock(), list_archives=flexmock())
prune_arguments = flexmock(repository=None, statistics=flexmock(), list_details=flexmock())
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
module.run_prune(
@@ -29,7 +29,9 @@ def test_run_prune_runs_with_selected_repository():
'repositories_match'
).once().and_return(True)
flexmock(module.borgmatic.borg.prune).should_receive('prune_archives').once()
prune_arguments = flexmock(repository=flexmock(), stats=flexmock(), list_archives=flexmock())
prune_arguments = flexmock(
repository=flexmock(), statistics=flexmock(), list_details=flexmock()
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
module.run_prune(
@@ -51,7 +53,9 @@ def test_run_prune_bails_if_repository_does_not_match():
'repositories_match'
).once().and_return(False)
flexmock(module.borgmatic.borg.prune).should_receive('prune_archives').never()
prune_arguments = flexmock(repository=flexmock(), stats=flexmock(), list_archives=flexmock())
prune_arguments = flexmock(
repository=flexmock(), statistics=flexmock(), list_details=flexmock()
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
module.run_prune(
+20 -1
View File
@@ -1,3 +1,4 @@
import pytest
from flexmock import flexmock
from borgmatic.actions import transfer as module
@@ -6,7 +7,7 @@ from borgmatic.actions import transfer as module
def test_run_transfer_does_not_raise():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.borg.transfer).should_receive('transfer_archives')
transfer_arguments = flexmock()
transfer_arguments = flexmock(archive=None)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
module.run_transfer(
@@ -18,3 +19,21 @@ def test_run_transfer_does_not_raise():
local_path=None,
remote_path=None,
)
def test_run_transfer_with_archive_and_match_archives_raises():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.borg.transfer).should_receive('transfer_archives')
transfer_arguments = flexmock(archive='foo')
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
with pytest.raises(ValueError):
module.run_transfer(
repository={'path': 'repo'},
config={'match_archives': 'foo*'},
local_borg_version=None,
transfer_arguments=transfer_arguments,
global_arguments=global_arguments,
local_path=None,
remote_path=None,
)
+1 -52
View File
@@ -155,22 +155,6 @@ def test_make_archive_filter_flags_with_data_check_and_prefix_includes_match_arc
assert flags == ('--match-archives', 'sh:foo-*')
def test_make_archive_filter_flags_prefers_check_arguments_match_archives_to_config_match_archives():
flexmock(module.feature).should_receive('available').and_return(True)
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
'baz-*', None, '1.2.3'
).and_return(('--match-archives', 'sh:baz-*'))
flags = module.make_archive_filter_flags(
'1.2.3',
{'match_archives': 'bar-{now}', 'prefix': ''}, # noqa: FS003
('archives',),
check_arguments=flexmock(match_archives='baz-*'),
)
assert flags == ('--match-archives', 'sh:baz-*')
def test_make_archive_filter_flags_with_archives_check_and_empty_prefix_uses_archive_name_format_instead():
flexmock(module.feature).should_receive('available').and_return(True)
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
@@ -331,42 +315,7 @@ def test_get_repository_id_with_missing_json_keys_raises():
)
def test_check_archives_favors_progress_flag_over_config():
config = {'progress': False}
flexmock(module).should_receive('make_check_name_flags').with_args(
{'repository'}, ()
).and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
flexmock(module).should_receive('execute_command').with_args(
('borg', 'check', '--progress', 'repo'),
output_file=module.DO_NOT_CAPTURE,
environment=None,
working_directory=None,
borg_local_path='borg',
borg_exit_codes=None,
).once()
module.check_archives(
repository_path='repo',
config=config,
local_borg_version='1.2.3',
check_arguments=flexmock(
progress=True,
repair=None,
only_checks=None,
force=None,
match_archives=None,
max_duration=None,
),
global_arguments=flexmock(log_json=False),
checks={'repository'},
archive_filter_flags=(),
)
def test_check_archives_defaults_to_progress_config():
def test_check_archives_with_progress_passes_through_to_borg():
config = {'progress': True}
flexmock(module).should_receive('make_check_name_flags').with_args(
{'repository'}, ()
+12 -14
View File
@@ -27,7 +27,7 @@ def insert_execute_command_mock(
COMPACT_COMMAND = ('borg', 'compact')
def test_compact_segments_calls_borg_with_parameters():
def test_compact_segments_calls_borg_with_flags():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('repo',), logging.INFO)
@@ -40,7 +40,7 @@ def test_compact_segments_calls_borg_with_parameters():
)
def test_compact_segments_with_log_info_calls_borg_with_info_parameter():
def test_compact_segments_with_log_info_calls_borg_with_info_flag():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--info', 'repo'), logging.INFO)
insert_logging_mock(logging.INFO)
@@ -54,7 +54,7 @@ def test_compact_segments_with_log_info_calls_borg_with_info_parameter():
)
def test_compact_segments_with_log_debug_calls_borg_with_debug_parameter():
def test_compact_segments_with_log_debug_calls_borg_with_debug_flag():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--debug', '--show-rc', 'repo'), logging.INFO)
insert_logging_mock(logging.DEBUG)
@@ -110,7 +110,7 @@ def test_compact_segments_with_exit_codes_calls_borg_using_them():
)
def test_compact_segments_with_remote_path_calls_borg_with_remote_path_parameters():
def test_compact_segments_with_remote_path_calls_borg_with_remote_path_flags():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--remote-path', 'borg1', 'repo'), logging.INFO)
@@ -124,21 +124,20 @@ def test_compact_segments_with_remote_path_calls_borg_with_remote_path_parameter
)
def test_compact_segments_with_progress_calls_borg_with_progress_parameter():
def test_compact_segments_with_progress_calls_borg_with_progress_flag():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--progress', 'repo'), logging.INFO)
module.compact_segments(
dry_run=False,
repository_path='repo',
config={},
config={'progress': True},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
progress=True,
)
def test_compact_segments_with_cleanup_commits_calls_borg_with_cleanup_commits_parameter():
def test_compact_segments_with_cleanup_commits_calls_borg_with_cleanup_commits_flag():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--cleanup-commits', 'repo'), logging.INFO)
@@ -152,21 +151,20 @@ def test_compact_segments_with_cleanup_commits_calls_borg_with_cleanup_commits_p
)
def test_compact_segments_with_threshold_calls_borg_with_threshold_parameter():
def test_compact_segments_with_threshold_calls_borg_with_threshold_flag():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--threshold', '20', 'repo'), logging.INFO)
module.compact_segments(
dry_run=False,
repository_path='repo',
config={},
config={'compact_threshold': 20},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
threshold=20,
)
def test_compact_segments_with_umask_calls_borg_with_umask_parameters():
def test_compact_segments_with_umask_calls_borg_with_umask_flags():
config = {'umask': '077'}
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--umask', '077', 'repo'), logging.INFO)
@@ -180,7 +178,7 @@ def test_compact_segments_with_umask_calls_borg_with_umask_parameters():
)
def test_compact_segments_with_log_json_calls_borg_with_log_json_parameters():
def test_compact_segments_with_log_json_calls_borg_with_log_json_flags():
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--log-json', 'repo'), logging.INFO)
@@ -193,7 +191,7 @@ def test_compact_segments_with_log_json_calls_borg_with_log_json_parameters():
)
def test_compact_segments_with_lock_wait_calls_borg_with_lock_wait_parameters():
def test_compact_segments_with_lock_wait_calls_borg_with_lock_wait_flags():
config = {'lock_wait': 5}
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
insert_execute_command_mock(COMPACT_COMMAND + ('--lock-wait', '5', 'repo'), logging.INFO)
+13 -15
View File
@@ -631,12 +631,12 @@ def test_make_base_create_command_includes_list_flags_in_borg_command():
config={
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'list_details': True,
},
patterns=[Pattern('foo'), Pattern('bar')],
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/run/borgmatic',
list_files=True,
)
assert create_flags == ('borg', 'create', '--list', '--filter', 'FOO')
@@ -962,7 +962,7 @@ def test_make_base_create_command_with_non_existent_directory_and_source_directo
)
def test_create_archive_calls_borg_with_parameters():
def test_create_archive_calls_borg_with_flags():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_base_create_command').and_return(
@@ -1029,7 +1029,7 @@ def test_create_archive_calls_borg_with_environment():
)
def test_create_archive_with_log_info_calls_borg_with_info_parameter():
def test_create_archive_with_log_info_calls_borg_with_info_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_base_create_command').and_return(
@@ -1096,7 +1096,7 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output():
)
def test_create_archive_with_log_debug_calls_borg_with_debug_parameter():
def test_create_archive_with_log_debug_calls_borg_with_debug_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_base_create_command').and_return(
@@ -1196,7 +1196,6 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats():
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/borgmatic/run',
stats=True,
)
@@ -1271,7 +1270,7 @@ def test_create_archive_with_exit_codes_calls_borg_using_them():
)
def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_answer_output_log_level():
def test_create_archive_with_stats_calls_borg_with_stats_flag_and_answer_output_log_level():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_base_create_command').and_return(
@@ -1296,12 +1295,12 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_answer_ou
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'exclude_patterns': None,
'statistics': True,
},
patterns=[Pattern('foo'), Pattern('bar')],
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/borgmatic/run',
stats=True,
)
@@ -1334,16 +1333,16 @@ def test_create_archive_with_files_calls_borg_with_answer_output_log_level():
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'exclude_patterns': None,
'list_details': True,
},
patterns=[Pattern('foo'), Pattern('bar')],
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/borgmatic/run',
list_files=True,
)
def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_parameter_and_no_list():
def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_flag_and_no_list():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_base_create_command').and_return(
@@ -1369,16 +1368,16 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'exclude_patterns': None,
'progress': True,
},
patterns=[Pattern('foo'), Pattern('bar')],
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/borgmatic/run',
progress=True,
)
def test_create_archive_with_progress_calls_borg_with_progress_parameter():
def test_create_archive_with_progress_calls_borg_with_progress_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_base_create_command').and_return(
@@ -1403,16 +1402,16 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter():
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'exclude_patterns': None,
'progress': True,
},
patterns=[Pattern('foo'), Pattern('bar')],
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/borgmatic/run',
progress=True,
)
def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progress_parameter():
def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progress_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
processes = flexmock()
@@ -1459,12 +1458,12 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'exclude_patterns': None,
'progress': True,
},
patterns=[Pattern('foo'), Pattern('bar')],
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/borgmatic/run',
progress=True,
stream_processes=processes,
)
@@ -1532,7 +1531,6 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_flag():
global_arguments=flexmock(log_json=False),
borgmatic_runtime_directory='/borgmatic/run',
json=True,
stats=True,
)
assert json_output == '[]'
+14 -38
View File
@@ -21,7 +21,7 @@ def test_make_delete_command_includes_log_info():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -43,7 +43,7 @@ def test_make_delete_command_includes_log_debug():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -67,7 +67,7 @@ def test_make_delete_command_includes_dry_run():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=True, log_json=False),
local_path='borg',
remote_path=None,
@@ -91,7 +91,7 @@ def test_make_delete_command_includes_remote_path():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path='borg1',
@@ -114,7 +114,7 @@ def test_make_delete_command_includes_umask():
repository={'path': 'repo'},
config={'umask': '077'},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -138,7 +138,7 @@ def test_make_delete_command_includes_log_json():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=True),
local_path='borg',
remote_path=None,
@@ -162,7 +162,7 @@ def test_make_delete_command_includes_lock_wait():
repository={'path': 'repo'},
config={'lock_wait': 5},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -171,31 +171,7 @@ def test_make_delete_command_includes_lock_wait():
assert command == ('borg', 'delete', '--lock-wait', '5', 'repo')
def test_make_delete_command_favors_list_flag_over_config():
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
'list', True
).and_return(('--list',))
flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
('repo',)
)
command = module.make_delete_command(
repository={'path': 'repo'},
config={'list_details': False},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=True, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
)
assert command == ('borg', 'delete', '--list', 'repo')
def test_make_delete_command_defaults_to_list_config():
def test_make_delete_command_with_list_config_calls_borg_with_list_flag():
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
'list', True
@@ -210,7 +186,7 @@ def test_make_delete_command_defaults_to_list_config():
repository={'path': 'repo'},
config={'list_details': True},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=None, force=0, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=None, force=0, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -231,7 +207,7 @@ def test_make_delete_command_includes_force():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=1, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=1, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -252,7 +228,7 @@ def test_make_delete_command_includes_force_twice():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(list_archives=False, force=2, match_archives=None, archive=None),
delete_arguments=flexmock(list_details=False, force=2, match_archives=None, archive=None),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -276,7 +252,7 @@ def test_make_delete_command_includes_archive():
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(
list_archives=False, force=0, match_archives=None, archive='archive'
list_details=False, force=0, match_archives=None, archive='archive'
),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
@@ -301,7 +277,7 @@ def test_make_delete_command_includes_match_archives():
config={},
local_borg_version='1.2.3',
delete_arguments=flexmock(
list_archives=False, force=0, match_archives='sh:foo*', archive='archive'
list_details=False, force=0, match_archives='sh:foo*', archive='archive'
),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
@@ -390,7 +366,7 @@ def test_delete_archives_without_archive_related_argument_calls_borg_repo_delete
config={},
local_borg_version=flexmock(),
delete_arguments=flexmock(
list_archives=True, force=False, cache_only=False, keep_security_info=False
list_details=True, force=False, cache_only=False, keep_security_info=False
),
global_arguments=flexmock(),
)
+7 -8
View File
@@ -144,7 +144,7 @@ def test_export_tar_archive_calls_borg_with_umask_flags():
)
def test_export_tar_archive_calls_borg_with_log_json_parameter():
def test_export_tar_archive_calls_borg_with_log_json_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
@@ -186,7 +186,7 @@ def test_export_tar_archive_calls_borg_with_lock_wait_flags():
)
def test_export_tar_archive_with_log_info_calls_borg_with_info_parameter():
def test_export_tar_archive_with_log_info_calls_borg_with_info_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
@@ -230,7 +230,7 @@ def test_export_tar_archive_with_log_debug_calls_borg_with_debug_flags():
)
def test_export_tar_archive_calls_borg_with_dry_run_parameter():
def test_export_tar_archive_calls_borg_with_dry_run_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
@@ -273,7 +273,7 @@ def test_export_tar_archive_calls_borg_with_tar_filter_flags():
)
def test_export_tar_archive_calls_borg_with_list_parameter():
def test_export_tar_archive_calls_borg_with_list_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
@@ -290,14 +290,13 @@ def test_export_tar_archive_calls_borg_with_list_parameter():
archive='archive',
paths=None,
destination_path='test.tar',
config={},
config={'list_details': True},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
list_files=True,
)
def test_export_tar_archive_calls_borg_with_strip_components_parameter():
def test_export_tar_archive_calls_borg_with_strip_components_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
@@ -320,7 +319,7 @@ def test_export_tar_archive_calls_borg_with_strip_components_parameter():
)
def test_export_tar_archive_skips_abspath_for_remote_repository_parameter():
def test_export_tar_archive_skips_abspath_for_remote_repository_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
+3 -5
View File
@@ -580,7 +580,7 @@ def test_extract_archive_with_strip_components_all_and_no_paths_raises():
)
def test_extract_archive_calls_borg_with_progress_parameter():
def test_extract_archive_calls_borg_with_progress_flag():
flexmock(module.os.path).should_receive('abspath').and_return('repo')
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -606,10 +606,9 @@ def test_extract_archive_calls_borg_with_progress_parameter():
repository='repo',
archive='archive',
paths=None,
config={},
config={'progress': True},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
progress=True,
)
@@ -622,10 +621,9 @@ def test_extract_archive_with_progress_and_extract_to_stdout_raises():
repository='repo',
archive='archive',
paths=None,
config={},
config={'progress': True},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
progress=True,
extract_to_stdout=True,
)
+1 -1
View File
@@ -380,7 +380,7 @@ def test_make_info_command_with_match_archives_flag_passes_through_to_command():
command = module.make_info_command(
repository_path='repo',
config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
config={'archive_name_format': 'bar-{now}', 'match_archives': 'sh:foo-*'}, # noqa: FS003
local_borg_version='2.3.4',
global_arguments=flexmock(log_json=False),
info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives='sh:foo-*'),
+20 -88
View File
@@ -135,32 +135,6 @@ def test_make_prune_flags_without_prefix_uses_archive_name_format_instead():
assert result == expected
def test_make_prune_flags_without_prefix_uses_match_archives_flag_instead_of_option():
config = {
'archive_name_format': 'bar-{now}', # noqa: FS003
'match_archives': 'foo*',
'keep_daily': 1,
'prefix': None,
}
flexmock(module.feature).should_receive('available').and_return(True)
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
'baz*', 'bar-{now}', '1.2.3' # noqa: FS003
).and_return(('--match-archives', 'sh:bar-*')).once()
result = module.make_prune_flags(
config, flexmock(match_archives='baz*'), local_borg_version='1.2.3'
)
expected = (
'--keep-daily',
'1',
'--match-archives',
'sh:bar-*', # noqa: FS003
)
assert result == expected
def test_make_prune_flags_without_prefix_uses_match_archives_option():
config = {
'archive_name_format': 'bar-{now}', # noqa: FS003
@@ -215,7 +189,7 @@ def test_prune_archives_calls_borg_with_flags():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('repo',), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -237,7 +211,7 @@ def test_prune_archives_with_log_info_calls_borg_with_info_flag():
insert_execute_command_mock(PRUNE_COMMAND + ('--info', 'repo'), logging.INFO)
insert_logging_mock(logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
repository_path='repo',
config={},
@@ -259,7 +233,7 @@ def test_prune_archives_with_log_debug_calls_borg_with_debug_flag():
insert_execute_command_mock(PRUNE_COMMAND + ('--debug', '--show-rc', 'repo'), logging.INFO)
insert_logging_mock(logging.DEBUG)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
repository_path='repo',
config={},
@@ -280,7 +254,7 @@ def test_prune_archives_with_dry_run_calls_borg_with_dry_run_flag():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--dry-run', 'repo'), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
repository_path='repo',
config={},
@@ -301,7 +275,7 @@ def test_prune_archives_with_local_path_calls_borg_via_local_path():
).and_return(False)
insert_execute_command_mock(('borg1',) + PRUNE_COMMAND[1:] + ('repo',), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -328,7 +302,7 @@ def test_prune_archives_with_exit_codes_calls_borg_using_them():
borg_exit_codes=borg_exit_codes,
)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -349,7 +323,7 @@ def test_prune_archives_with_remote_path_calls_borg_with_remote_path_flags():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--remote-path', 'borg1', 'repo'), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -361,7 +335,7 @@ def test_prune_archives_with_remote_path_calls_borg_with_remote_path_flags():
)
def test_prune_archives_favors_stats_flag_over_config():
def test_prune_archives_with_stats_config_calls_borg_with_stats_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
@@ -371,28 +345,7 @@ def test_prune_archives_favors_stats_flag_over_config():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--stats', 'repo'), module.borgmatic.logger.ANSWER)
prune_arguments = flexmock(stats=True, list_archives=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
config={'statistics': False},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
prune_arguments=prune_arguments,
)
def test_prune_archives_defaults_to_stats_config():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.feature).should_receive('available').with_args(
module.feature.Feature.NO_PRUNE_STATS, '1.2.3'
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--stats', 'repo'), module.borgmatic.logger.ANSWER)
prune_arguments = flexmock(stats=None, list_archives=False)
prune_arguments = flexmock(statistics=None, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -403,7 +356,7 @@ def test_prune_archives_defaults_to_stats_config():
)
def test_prune_archives_favors_list_flag_over_config():
def test_prune_archives_with_list_config_calls_borg_with_list_flag():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
@@ -413,28 +366,7 @@ def test_prune_archives_favors_list_flag_over_config():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--list', 'repo'), module.borgmatic.logger.ANSWER)
prune_arguments = flexmock(stats=False, list_archives=True)
module.prune_archives(
dry_run=False,
repository_path='repo',
config={'list_details': False},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
prune_arguments=prune_arguments,
)
def test_prune_archives_defaults_to_list_config():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.feature).should_receive('available').with_args(
module.feature.Feature.NO_PRUNE_STATS, '1.2.3'
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--list', 'repo'), module.borgmatic.logger.ANSWER)
prune_arguments = flexmock(stats=False, list_archives=None)
prune_arguments = flexmock(statistics=False, list_details=None)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -456,7 +388,7 @@ def test_prune_archives_with_umask_calls_borg_with_umask_flags():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--umask', '077', 'repo'), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -477,7 +409,7 @@ def test_prune_archives_with_log_json_calls_borg_with_log_json_flag():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--log-json', 'repo'), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -499,7 +431,7 @@ def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_flags():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--lock-wait', '5', 'repo'), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -520,7 +452,7 @@ def test_prune_archives_with_extra_borg_options_calls_borg_with_extra_options():
).and_return(False)
insert_execute_command_mock(PRUNE_COMMAND + ('--extra', '--options', 'repo'), logging.INFO)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -588,7 +520,7 @@ def test_prune_archives_with_date_based_matching_calls_borg_with_date_based_flag
)
prune_arguments = flexmock(
stats=False, list_archives=False, newer='1d', newest='1y', older='1m', oldest='1w'
statistics=False, list_details=False, newer='1d', newest='1y', older='1m', oldest='1w'
)
module.prune_archives(
dry_run=False,
@@ -612,7 +544,7 @@ def test_prune_archives_calls_borg_with_working_directory():
PRUNE_COMMAND + ('repo',), logging.INFO, working_directory='/working/dir'
)
prune_arguments = flexmock(stats=False, list_archives=False)
prune_arguments = flexmock(statistics=False, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
@@ -623,7 +555,7 @@ def test_prune_archives_calls_borg_with_working_directory():
)
def test_prune_archives_calls_borg_with_flags_and_when_feature_available():
def test_prune_archives_calls_borg_without_stats_when_feature_is_not_available():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
@@ -633,11 +565,11 @@ def test_prune_archives_calls_borg_with_flags_and_when_feature_available():
).and_return(True)
insert_execute_command_mock(PRUNE_COMMAND + ('repo',), logging.ANSWER)
prune_arguments = flexmock(stats=True, list_archives=False)
prune_arguments = flexmock(statistics=True, list_details=False)
module.prune_archives(
dry_run=False,
repository_path='repo',
config={},
config={'statistics': True},
local_borg_version='2.0.0b10',
global_arguments=flexmock(log_json=False),
prune_arguments=prune_arguments,
+1 -31
View File
@@ -225,37 +225,7 @@ def test_recreate_with_log_json():
)
def test_recreate_archive_favors_list_flag_over_config():
flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.borgmatic.borg.flags).should_receive(
'make_repository_archive_flags'
).and_return(('repo::archive',))
flexmock(module).should_receive('make_list_filter_flags').and_return('AME+-')
insert_execute_command_mock(
('borg', 'recreate', '--list', '--filter', 'AME+-', 'repo::archive')
)
module.recreate_archive(
repository='repo',
archive='archive',
config={'list_details': False},
local_borg_version='1.2.3',
recreate_arguments=flexmock(
list=True,
target=None,
comment=None,
timestamp=None,
match_archives=None,
),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
patterns=None,
)
def test_recreate_archive_defaults_to_list_config():
def test_recreate_with_list_config_calls_borg_with_list_flag():
flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+13 -13
View File
@@ -19,7 +19,7 @@ def test_make_repo_delete_command_with_feature_available_runs_borg_repo_delete()
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -40,7 +40,7 @@ def test_make_repo_delete_command_without_feature_available_runs_borg_delete():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -62,7 +62,7 @@ def test_make_repo_delete_command_includes_log_info():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -84,7 +84,7 @@ def test_make_repo_delete_command_includes_log_debug():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -108,7 +108,7 @@ def test_make_repo_delete_command_includes_dry_run():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=True, log_json=False),
local_path='borg',
remote_path=None,
@@ -132,7 +132,7 @@ def test_make_repo_delete_command_includes_remote_path():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path='borg1',
@@ -155,7 +155,7 @@ def test_make_repo_delete_command_includes_umask():
repository={'path': 'repo'},
config={'umask': '077'},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -179,7 +179,7 @@ def test_make_repo_delete_command_includes_log_json():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=True),
local_path='borg',
remote_path=None,
@@ -203,7 +203,7 @@ def test_make_repo_delete_command_includes_lock_wait():
repository={'path': 'repo'},
config={'lock_wait': 5},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=0),
repo_delete_arguments=flexmock(list_details=False, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -225,9 +225,9 @@ def test_make_repo_delete_command_includes_list():
command = module.make_repo_delete_command(
repository={'path': 'repo'},
config={},
config={'list_details': True},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=True, force=0),
repo_delete_arguments=flexmock(list_details=True, force=0),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -248,7 +248,7 @@ def test_make_repo_delete_command_includes_force():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=1),
repo_delete_arguments=flexmock(list_details=False, force=1),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
@@ -269,7 +269,7 @@ def test_make_repo_delete_command_includes_force_twice():
repository={'path': 'repo'},
config={},
local_borg_version='1.2.3',
repo_delete_arguments=flexmock(list_archives=False, force=2),
repo_delete_arguments=flexmock(list_details=False, force=2),
global_arguments=flexmock(dry_run=False, log_json=False),
local_path='borg',
remote_path=None,
+1 -1
View File
@@ -664,7 +664,7 @@ def test_make_repo_list_command_with_match_archives_calls_borg_with_match_archiv
command = module.make_repo_list_command(
repository_path='repo',
config={},
config={'match_archives': 'foo-*'},
local_borg_version='1.2.3',
repo_list_arguments=flexmock(
archive=None,
+2 -33
View File
@@ -193,7 +193,7 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl
module.transfer_archives(
dry_run=False,
repository_path='repo',
config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
config={'archive_name_format': 'bar-{now}', 'match_archives': 'sh:foo*'}, # noqa: FS003
local_borg_version='2.3.4',
transfer_arguments=flexmock(
archive=None, progress=None, match_archives='sh:foo*', source_repository=None
@@ -436,38 +436,7 @@ def test_transfer_archives_with_lock_wait_calls_borg_with_lock_wait_flags():
)
def test_transfer_archives_favors_progress_flag_over_config():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_flags').and_return(())
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--progress',))
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
flexmock(module).should_receive('execute_command').with_args(
('borg', 'transfer', '--progress', '--repo', 'repo'),
output_log_level=module.borgmatic.logger.ANSWER,
output_file=module.DO_NOT_CAPTURE,
environment=None,
working_directory=None,
borg_local_path='borg',
borg_exit_codes=None,
)
module.transfer_archives(
dry_run=False,
repository_path='repo',
config={'progress': False},
local_borg_version='2.3.4',
transfer_arguments=flexmock(
archive=None, progress=True, match_archives=None, source_repository=None
),
global_arguments=flexmock(log_json=False),
)
def test_transfer_archives_defaults_to_progress_flag():
def test_transfer_archives_with_progress_calls_borg_with_progress_flags():
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
flexmock(module.flags).should_receive('make_flags').and_return(())
+3 -3
View File
@@ -1578,7 +1578,7 @@ def test_load_configurations_collects_parsed_configurations_and_logs(resolve_env
configs, config_paths, logs = tuple(
module.load_configurations(
('test.yaml', 'other.yaml'),
global_arguments=flexmock(),
arguments=flexmock(),
resolve_env=resolve_env,
)
)
@@ -1592,7 +1592,7 @@ def test_load_configurations_logs_warning_for_permission_error():
flexmock(module.validate).should_receive('parse_configuration').and_raise(PermissionError)
configs, config_paths, logs = tuple(
module.load_configurations(('test.yaml',), global_arguments=flexmock())
module.load_configurations(('test.yaml',), arguments=flexmock())
)
assert configs == {}
@@ -1604,7 +1604,7 @@ def test_load_configurations_logs_critical_for_parse_error():
flexmock(module.validate).should_receive('parse_configuration').and_raise(ValueError)
configs, config_paths, logs = tuple(
module.load_configurations(('test.yaml',), global_arguments=flexmock())
module.load_configurations(('test.yaml',), arguments=flexmock())
)
assert configs == {}
+12
View File
@@ -189,3 +189,15 @@ def test_prepare_arguments_for_config_skips_option_missing_from_schema():
},
},
) == ((('other_option',), 'value2'),)
def test_apply_arguments_to_config_does_not_raise():
flexmock(module).should_receive('prepare_arguments_for_config').and_return(
(
(('foo', 'bar'), 'baz'),
(('one', 'two'), 'three'),
)
)
flexmock(module).should_receive('set_values')
module.apply_arguments_to_config(config={}, schema={}, arguments={'global': flexmock()})