Update list action for Borg 2 support, add rinfo action, and update extract consistency check for Borg 2.
This commit is contained in:
parent
cce6d56661
commit
cc04bf57df
16 changed files with 1082 additions and 361 deletions
|
@ -323,6 +323,6 @@ def check_archives(
|
||||||
|
|
||||||
if 'extract' in checks:
|
if 'extract' in checks:
|
||||||
extract.extract_last_archive_dry_run(
|
extract.extract_last_archive_dry_run(
|
||||||
storage_config, repository, lock_wait, local_path, remote_path
|
storage_config, local_borg_version, repository, lock_wait, local_path, remote_path
|
||||||
)
|
)
|
||||||
write_check_time(make_check_time_path(location_config, borg_repository_id, 'extract'))
|
write_check_time(make_check_time_path(location_config, borg_repository_id, 'extract'))
|
||||||
|
|
|
@ -2,14 +2,19 @@ import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from borgmatic.borg import environment, feature, flags
|
from borgmatic.borg import environment, feature, flags, rlist
|
||||||
from borgmatic.execute import DO_NOT_CAPTURE, execute_command
|
from borgmatic.execute import DO_NOT_CAPTURE, execute_command
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def extract_last_archive_dry_run(
|
def extract_last_archive_dry_run(
|
||||||
storage_config, repository, lock_wait=None, local_path='borg', remote_path=None
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
repository,
|
||||||
|
lock_wait=None,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
Perform an extraction dry-run of the most recent archive. If there are no archives, skip the
|
Perform an extraction dry-run of the most recent archive. If there are no archives, skip the
|
||||||
|
@ -23,40 +28,23 @@ def extract_last_archive_dry_run(
|
||||||
elif logger.isEnabledFor(logging.INFO):
|
elif logger.isEnabledFor(logging.INFO):
|
||||||
verbosity_flags = ('--info',)
|
verbosity_flags = ('--info',)
|
||||||
|
|
||||||
full_list_command = (
|
|
||||||
(local_path, 'list', '--short')
|
|
||||||
+ remote_path_flags
|
|
||||||
+ lock_wait_flags
|
|
||||||
+ verbosity_flags
|
|
||||||
+ (repository,)
|
|
||||||
)
|
|
||||||
|
|
||||||
borg_environment = environment.make_environment(storage_config)
|
|
||||||
|
|
||||||
list_output = execute_command(
|
|
||||||
full_list_command,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path=local_path,
|
|
||||||
extra_environment=borg_environment,
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
last_archive_name = list_output.strip().splitlines()[-1]
|
last_archive_name = rlist.resolve_archive_name(
|
||||||
except IndexError:
|
repository, 'latest', storage_config, local_borg_version, local_path, remote_path
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
logger.warning('No archives found. Skipping extract consistency check.')
|
||||||
return
|
return
|
||||||
|
|
||||||
list_flag = ('--list',) if logger.isEnabledFor(logging.DEBUG) else ()
|
list_flag = ('--list',) if logger.isEnabledFor(logging.DEBUG) else ()
|
||||||
|
borg_environment = environment.make_environment(storage_config)
|
||||||
full_extract_command = (
|
full_extract_command = (
|
||||||
(local_path, 'extract', '--dry-run')
|
(local_path, 'extract', '--dry-run')
|
||||||
+ remote_path_flags
|
+ remote_path_flags
|
||||||
+ lock_wait_flags
|
+ lock_wait_flags
|
||||||
+ verbosity_flags
|
+ verbosity_flags
|
||||||
+ list_flag
|
+ list_flag
|
||||||
+ (
|
+ flags.make_repository_archive_flags(repository, last_archive_name, local_borg_version)
|
||||||
'{repository}::{last_archive_name}'.format(
|
|
||||||
repository=repository, last_archive_name=last_archive_name
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
execute_command(
|
execute_command(
|
||||||
|
|
|
@ -1,58 +1,24 @@
|
||||||
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from borgmatic.borg import environment
|
from borgmatic.borg import environment, feature, flags, rlist
|
||||||
from borgmatic.borg.flags import make_flags, make_flags_from_arguments
|
|
||||||
from borgmatic.execute import execute_command
|
from borgmatic.execute import execute_command
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def resolve_archive_name(repository, archive, storage_config, local_path='borg', remote_path=None):
|
|
||||||
'''
|
|
||||||
Given a local or remote repository path, an archive name, a storage config dict, a local Borg
|
|
||||||
path, and a remote Borg path, simply return the archive name. But if the archive name is
|
|
||||||
"latest", then instead introspect the repository for the latest archive and return its name.
|
|
||||||
|
|
||||||
Raise ValueError if "latest" is given but there are no archives in the repository.
|
|
||||||
'''
|
|
||||||
if archive != "latest":
|
|
||||||
return archive
|
|
||||||
|
|
||||||
lock_wait = storage_config.get('lock_wait', None)
|
|
||||||
|
|
||||||
full_command = (
|
|
||||||
(local_path, 'list')
|
|
||||||
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
|
|
||||||
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
|
|
||||||
+ make_flags('remote-path', remote_path)
|
|
||||||
+ make_flags('lock-wait', lock_wait)
|
|
||||||
+ make_flags('last', 1)
|
|
||||||
+ ('--short', repository)
|
|
||||||
)
|
|
||||||
|
|
||||||
output = execute_command(
|
|
||||||
full_command,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path=local_path,
|
|
||||||
extra_environment=environment.make_environment(storage_config),
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
latest_archive = output.strip().splitlines()[-1]
|
|
||||||
except IndexError:
|
|
||||||
raise ValueError('No archives found in the repository')
|
|
||||||
|
|
||||||
logger.debug('{}: Latest archive is {}'.format(repository, latest_archive))
|
|
||||||
|
|
||||||
return latest_archive
|
|
||||||
|
|
||||||
|
|
||||||
MAKE_FLAGS_EXCLUDES = ('repository', 'archive', 'successful', 'paths', 'find_paths')
|
MAKE_FLAGS_EXCLUDES = ('repository', 'archive', 'successful', 'paths', 'find_paths')
|
||||||
|
|
||||||
|
|
||||||
def make_list_command(
|
def make_list_command(
|
||||||
repository, storage_config, list_arguments, local_path='borg', remote_path=None
|
repository,
|
||||||
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
list_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
Given a local or remote repository path, a storage config dict, the arguments to the list
|
Given a local or remote repository path, a storage config dict, the arguments to the list
|
||||||
|
@ -73,13 +39,15 @@ def make_list_command(
|
||||||
if logger.isEnabledFor(logging.DEBUG) and not list_arguments.json
|
if logger.isEnabledFor(logging.DEBUG) and not list_arguments.json
|
||||||
else ()
|
else ()
|
||||||
)
|
)
|
||||||
+ make_flags('remote-path', remote_path)
|
+ flags.make_flags('remote-path', remote_path)
|
||||||
+ make_flags('lock-wait', lock_wait)
|
+ flags.make_flags('lock-wait', lock_wait)
|
||||||
+ make_flags_from_arguments(list_arguments, excludes=MAKE_FLAGS_EXCLUDES,)
|
+ flags.make_flags_from_arguments(list_arguments, excludes=MAKE_FLAGS_EXCLUDES,)
|
||||||
+ (
|
+ (
|
||||||
('::'.join((repository, list_arguments.archive)),)
|
flags.make_repository_archive_flags(
|
||||||
|
repository, list_arguments.archive, local_borg_version
|
||||||
|
)
|
||||||
if list_arguments.archive
|
if list_arguments.archive
|
||||||
else (repository,)
|
else flags.make_repository_flags(repository, local_borg_version)
|
||||||
)
|
)
|
||||||
+ (tuple(list_arguments.paths) if list_arguments.paths else ())
|
+ (tuple(list_arguments.paths) if list_arguments.paths else ())
|
||||||
)
|
)
|
||||||
|
@ -109,29 +77,76 @@ def make_find_paths(find_paths):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def list_archives(repository, storage_config, list_arguments, local_path='borg', remote_path=None):
|
def list_archive(
|
||||||
|
repository,
|
||||||
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
list_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
):
|
||||||
'''
|
'''
|
||||||
Given a local or remote repository path, a storage config dict, the arguments to the list
|
Given a local or remote repository path, a storage config dict, the local Borg version, the
|
||||||
action, and local and remote Borg paths, display the output of listing Borg archives in the
|
arguments to the list action, and local and remote Borg paths, display the output of listing
|
||||||
repository or return JSON output. Or, if an archive name is given, list the files in that
|
the files of a Borg archive (or return JSON output). If list_arguments.find_paths are given,
|
||||||
archive. Or, if list_arguments.find_paths are given, list the files by searching across multiple
|
list the files by searching across multiple archives. If neither find_paths nor archive name
|
||||||
archives.
|
are given, instead list the archives in the given repository.
|
||||||
'''
|
'''
|
||||||
|
if not list_arguments.archive and not list_arguments.find_paths:
|
||||||
|
if feature.available(feature.Feature.RLIST, local_borg_version):
|
||||||
|
logger.warning(
|
||||||
|
'Omitting the --archive flag on the list action is deprecated when using Borg 2.x. Use the rlist action instead.'
|
||||||
|
)
|
||||||
|
|
||||||
|
rlist_arguments = argparse.Namespace(
|
||||||
|
repository=repository,
|
||||||
|
short=list_arguments.short,
|
||||||
|
format=list_arguments.format,
|
||||||
|
json=list_arguments.json,
|
||||||
|
prefix=list_arguments.prefix,
|
||||||
|
glob_archives=list_arguments.glob_archives,
|
||||||
|
sort_by=list_arguments.sort_by,
|
||||||
|
first=list_arguments.first,
|
||||||
|
last=list_arguments.last,
|
||||||
|
)
|
||||||
|
return rlist.list_repository(
|
||||||
|
repository, storage_config, local_borg_version, rlist_arguments, local_path, remote_path
|
||||||
|
)
|
||||||
|
|
||||||
|
if feature.available(feature.Feature.RLIST, local_borg_version):
|
||||||
|
for flag_name in ('prefix', 'glob-archives', 'sort-by', 'first', 'last'):
|
||||||
|
if getattr(list_arguments, flag_name.replace('-', '_'), None):
|
||||||
|
raise ValueError(
|
||||||
|
f'The --{flag_name} flag on the list action is not supported when using the --archive flag and Borg 2.x.'
|
||||||
|
)
|
||||||
|
|
||||||
borg_environment = environment.make_environment(storage_config)
|
borg_environment = environment.make_environment(storage_config)
|
||||||
|
|
||||||
# If there are any paths to find (and there's not a single archive already selected), start by
|
# If there are any paths to find (and there's not a single archive already selected), start by
|
||||||
# getting a list of archives to search.
|
# getting a list of archives to search.
|
||||||
if list_arguments.find_paths and not list_arguments.archive:
|
if list_arguments.find_paths and not list_arguments.archive:
|
||||||
repository_arguments = copy.copy(list_arguments)
|
rlist_arguments = argparse.Namespace(
|
||||||
repository_arguments.archive = None
|
repository=repository,
|
||||||
repository_arguments.json = False
|
short=True,
|
||||||
repository_arguments.format = None
|
format=None,
|
||||||
|
json=None,
|
||||||
|
prefix=list_arguments.prefix,
|
||||||
|
glob_archives=list_arguments.glob_archives,
|
||||||
|
sort_by=list_arguments.sort_by,
|
||||||
|
first=list_arguments.first,
|
||||||
|
last=list_arguments.last,
|
||||||
|
)
|
||||||
|
|
||||||
# Ask Borg to list archives. Capture its output for use below.
|
# Ask Borg to list archives. Capture its output for use below.
|
||||||
archive_lines = tuple(
|
archive_lines = tuple(
|
||||||
execute_command(
|
execute_command(
|
||||||
make_list_command(
|
rlist.make_rlist_command(
|
||||||
repository, storage_config, repository_arguments, local_path, remote_path
|
repository,
|
||||||
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
rlist_arguments,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
),
|
),
|
||||||
output_log_level=None,
|
output_log_level=None,
|
||||||
borg_local_path=local_path,
|
borg_local_path=local_path,
|
||||||
|
@ -144,19 +159,18 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg',
|
||||||
archive_lines = (list_arguments.archive,)
|
archive_lines = (list_arguments.archive,)
|
||||||
|
|
||||||
# For each archive listed by Borg, run list on the contents of that archive.
|
# For each archive listed by Borg, run list on the contents of that archive.
|
||||||
for archive_line in archive_lines:
|
for archive in archive_lines:
|
||||||
try:
|
logger.warning(f'{repository}: Listing archive {archive}')
|
||||||
archive = archive_line.split()[0]
|
|
||||||
except (AttributeError, IndexError):
|
|
||||||
archive = None
|
|
||||||
|
|
||||||
if archive:
|
|
||||||
logger.warning(archive_line)
|
|
||||||
|
|
||||||
archive_arguments = copy.copy(list_arguments)
|
archive_arguments = copy.copy(list_arguments)
|
||||||
archive_arguments.archive = archive
|
archive_arguments.archive = archive
|
||||||
main_command = make_list_command(
|
main_command = make_list_command(
|
||||||
repository, storage_config, archive_arguments, local_path, remote_path
|
repository,
|
||||||
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
archive_arguments,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
) + make_find_paths(list_arguments.find_paths)
|
) + make_find_paths(list_arguments.find_paths)
|
||||||
|
|
||||||
output = execute_command(
|
output = execute_command(
|
||||||
|
|
121
borgmatic/borg/rlist.py
Normal file
121
borgmatic/borg/rlist.py
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from borgmatic.borg import environment, feature, flags
|
||||||
|
from borgmatic.execute import execute_command
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_archive_name(
|
||||||
|
repository, archive, storage_config, local_borg_version, local_path='borg', remote_path=None
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Given a local or remote repository path, an archive name, a storage config dict, a local Borg
|
||||||
|
path, and a remote Borg path, simply return the archive name. But if the archive name is
|
||||||
|
"latest", then instead introspect the repository for the latest archive and return its name.
|
||||||
|
|
||||||
|
Raise ValueError if "latest" is given but there are no archives in the repository.
|
||||||
|
'''
|
||||||
|
if archive != "latest":
|
||||||
|
return archive
|
||||||
|
|
||||||
|
lock_wait = storage_config.get('lock_wait', None)
|
||||||
|
|
||||||
|
full_command = (
|
||||||
|
(
|
||||||
|
local_path,
|
||||||
|
'rlist' if feature.available(feature.Feature.RLIST, local_borg_version) else 'list',
|
||||||
|
)
|
||||||
|
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
|
||||||
|
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
|
||||||
|
+ flags.make_flags('remote-path', remote_path)
|
||||||
|
+ flags.make_flags('lock-wait', lock_wait)
|
||||||
|
+ flags.make_flags('last', 1)
|
||||||
|
+ ('--short',)
|
||||||
|
+ flags.make_repository_flags(repository, local_borg_version)
|
||||||
|
)
|
||||||
|
|
||||||
|
output = execute_command(
|
||||||
|
full_command,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path=local_path,
|
||||||
|
extra_environment=environment.make_environment(storage_config),
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
latest_archive = output.strip().splitlines()[-1]
|
||||||
|
except IndexError:
|
||||||
|
raise ValueError('No archives found in the repository')
|
||||||
|
|
||||||
|
logger.debug('{}: Latest archive is {}'.format(repository, latest_archive))
|
||||||
|
|
||||||
|
return latest_archive
|
||||||
|
|
||||||
|
|
||||||
|
MAKE_FLAGS_EXCLUDES = ('repository',)
|
||||||
|
|
||||||
|
|
||||||
|
def make_rlist_command(
|
||||||
|
repository,
|
||||||
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
rlist_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Given a local or remote repository path, a storage config dict, the local Borg version, the
|
||||||
|
arguments to the rlist action, and local and remote Borg paths, return a command as a tuple to
|
||||||
|
list archives with a repository.
|
||||||
|
'''
|
||||||
|
lock_wait = storage_config.get('lock_wait', None)
|
||||||
|
|
||||||
|
return (
|
||||||
|
(
|
||||||
|
local_path,
|
||||||
|
'rlist' if feature.available(feature.Feature.RLIST, local_borg_version) else 'list',
|
||||||
|
)
|
||||||
|
+ (
|
||||||
|
('--info',)
|
||||||
|
if logger.getEffectiveLevel() == logging.INFO and not rlist_arguments.json
|
||||||
|
else ()
|
||||||
|
)
|
||||||
|
+ (
|
||||||
|
('--debug', '--show-rc')
|
||||||
|
if logger.isEnabledFor(logging.DEBUG) and not rlist_arguments.json
|
||||||
|
else ()
|
||||||
|
)
|
||||||
|
+ flags.make_flags('remote-path', remote_path)
|
||||||
|
+ flags.make_flags('lock-wait', lock_wait)
|
||||||
|
+ flags.make_flags_from_arguments(rlist_arguments, excludes=MAKE_FLAGS_EXCLUDES,)
|
||||||
|
+ flags.make_repository_flags(repository, local_borg_version)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def list_repository(
|
||||||
|
repository,
|
||||||
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
rlist_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Given a local or remote repository path, a storage config dict, the local Borg version, the
|
||||||
|
arguments to the list action, and local and remote Borg paths, display the output of listing
|
||||||
|
Borg archives in the given repository (or return JSON output).
|
||||||
|
'''
|
||||||
|
borg_environment = environment.make_environment(storage_config)
|
||||||
|
|
||||||
|
main_command = make_rlist_command(
|
||||||
|
repository, storage_config, local_borg_version, rlist_arguments, local_path, remote_path
|
||||||
|
)
|
||||||
|
|
||||||
|
output = execute_command(
|
||||||
|
main_command,
|
||||||
|
output_log_level=None if rlist_arguments.json else logging.WARNING,
|
||||||
|
borg_local_path=local_path,
|
||||||
|
extra_environment=borg_environment,
|
||||||
|
)
|
||||||
|
|
||||||
|
if rlist_arguments.json:
|
||||||
|
return output
|
|
@ -14,6 +14,7 @@ SUBPARSER_ALIASES = {
|
||||||
'mount': ['--mount', '-m'],
|
'mount': ['--mount', '-m'],
|
||||||
'umount': ['--umount', '-u'],
|
'umount': ['--umount', '-u'],
|
||||||
'restore': ['--restore', '-r'],
|
'restore': ['--restore', '-r'],
|
||||||
|
'rlist': [],
|
||||||
'list': ['--list', '-l'],
|
'list': ['--list', '-l'],
|
||||||
'rinfo': [],
|
'rinfo': [],
|
||||||
'info': ['--info', '-i'],
|
'info': ['--info', '-i'],
|
||||||
|
@ -546,18 +547,54 @@ def make_parsers():
|
||||||
'-h', '--help', action='help', help='Show this help message and exit'
|
'-h', '--help', action='help', help='Show this help message and exit'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rlist_parser = subparsers.add_parser(
|
||||||
|
'rlist',
|
||||||
|
aliases=SUBPARSER_ALIASES['rlist'],
|
||||||
|
help='List repository',
|
||||||
|
description='List the archives in a repository',
|
||||||
|
add_help=False,
|
||||||
|
)
|
||||||
|
rlist_group = rlist_parser.add_argument_group('rlist arguments')
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'--repository', help='Path of repository to list, defaults to the configured repositories',
|
||||||
|
)
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'--short', default=False, action='store_true', help='Output only archive names'
|
||||||
|
)
|
||||||
|
rlist_group.add_argument('--format', help='Format for archive listing')
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'--json', default=False, action='store_true', help='Output results as JSON'
|
||||||
|
)
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'-P', '--prefix', help='Only list archive names starting with this prefix'
|
||||||
|
)
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'-a', '--glob-archives', metavar='GLOB', help='Only list archive names matching this glob'
|
||||||
|
)
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'--sort-by', metavar='KEYS', help='Comma-separated list of sorting keys'
|
||||||
|
)
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'--first', metavar='N', help='List first N archives after other filters are applied'
|
||||||
|
)
|
||||||
|
rlist_group.add_argument(
|
||||||
|
'--last', metavar='N', help='List last N archives after other filters are applied'
|
||||||
|
)
|
||||||
|
rlist_group.add_argument('-h', '--help', action='help', help='Show this help message and exit')
|
||||||
|
|
||||||
list_parser = subparsers.add_parser(
|
list_parser = subparsers.add_parser(
|
||||||
'list',
|
'list',
|
||||||
aliases=SUBPARSER_ALIASES['list'],
|
aliases=SUBPARSER_ALIASES['list'],
|
||||||
help='List archives',
|
help='List archive',
|
||||||
description='List archives or the contents of an archive',
|
description='List the files in an archive or search for a file across archives',
|
||||||
add_help=False,
|
add_help=False,
|
||||||
)
|
)
|
||||||
list_group = list_parser.add_argument_group('list arguments')
|
list_group = list_parser.add_argument_group('list arguments')
|
||||||
list_group.add_argument(
|
list_group.add_argument(
|
||||||
'--repository', help='Path of repository to list, defaults to the configured repositories',
|
'--repository',
|
||||||
|
help='Path of repository containing archive to list, defaults to the configured repositories',
|
||||||
)
|
)
|
||||||
list_group.add_argument('--archive', help='Name of archive to list (or "latest")')
|
list_group.add_argument('--archive', help='Name of the archive to list (or "latest")')
|
||||||
list_group.add_argument(
|
list_group.add_argument(
|
||||||
'--path',
|
'--path',
|
||||||
metavar='PATH',
|
metavar='PATH',
|
||||||
|
@ -573,7 +610,7 @@ def make_parsers():
|
||||||
help='Partial paths or patterns to search for and list across multiple archives',
|
help='Partial paths or patterns to search for and list across multiple archives',
|
||||||
)
|
)
|
||||||
list_group.add_argument(
|
list_group.add_argument(
|
||||||
'--short', default=False, action='store_true', help='Output only archive or path names'
|
'--short', default=False, action='store_true', help='Output only path names'
|
||||||
)
|
)
|
||||||
list_group.add_argument('--format', help='Format for file listing')
|
list_group.add_argument('--format', help='Format for file listing')
|
||||||
list_group.add_argument(
|
list_group.add_argument(
|
||||||
|
@ -589,7 +626,7 @@ def make_parsers():
|
||||||
'--successful',
|
'--successful',
|
||||||
default=True,
|
default=True,
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Deprecated in favor of listing successful (non-checkpoint) backups by default in newer versions of Borg',
|
help='Deprecated; no effect. Newer versions of Borg list successful (non-checkpoint) archives by default.',
|
||||||
)
|
)
|
||||||
list_group.add_argument(
|
list_group.add_argument(
|
||||||
'--sort-by', metavar='KEYS', help='Comma-separated list of sorting keys'
|
'--sort-by', metavar='KEYS', help='Comma-separated list of sorting keys'
|
||||||
|
|
|
@ -25,6 +25,7 @@ from borgmatic.borg import mount as borg_mount
|
||||||
from borgmatic.borg import prune as borg_prune
|
from borgmatic.borg import prune as borg_prune
|
||||||
from borgmatic.borg import rcreate as borg_rcreate
|
from borgmatic.borg import rcreate as borg_rcreate
|
||||||
from borgmatic.borg import rinfo as borg_rinfo
|
from borgmatic.borg import rinfo as borg_rinfo
|
||||||
|
from borgmatic.borg import rlist as borg_rlist
|
||||||
from borgmatic.borg import umount as borg_umount
|
from borgmatic.borg import umount as borg_umount
|
||||||
from borgmatic.borg import version as borg_version
|
from borgmatic.borg import version as borg_version
|
||||||
from borgmatic.commands.arguments import parse_arguments
|
from borgmatic.commands.arguments import parse_arguments
|
||||||
|
@ -434,8 +435,13 @@ def run_actions(
|
||||||
borg_extract.extract_archive(
|
borg_extract.extract_archive(
|
||||||
global_arguments.dry_run,
|
global_arguments.dry_run,
|
||||||
repository,
|
repository,
|
||||||
borg_list.resolve_archive_name(
|
borg_rlist.resolve_archive_name(
|
||||||
repository, arguments['extract'].archive, storage, local_path, remote_path
|
repository,
|
||||||
|
arguments['extract'].archive,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
),
|
),
|
||||||
arguments['extract'].paths,
|
arguments['extract'].paths,
|
||||||
location,
|
location,
|
||||||
|
@ -467,8 +473,13 @@ def run_actions(
|
||||||
borg_export_tar.export_tar_archive(
|
borg_export_tar.export_tar_archive(
|
||||||
global_arguments.dry_run,
|
global_arguments.dry_run,
|
||||||
repository,
|
repository,
|
||||||
borg_list.resolve_archive_name(
|
borg_rlist.resolve_archive_name(
|
||||||
repository, arguments['export-tar'].archive, storage, local_path, remote_path
|
repository,
|
||||||
|
arguments['export-tar'].archive,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
),
|
),
|
||||||
arguments['export-tar'].paths,
|
arguments['export-tar'].paths,
|
||||||
arguments['export-tar'].destination,
|
arguments['export-tar'].destination,
|
||||||
|
@ -492,8 +503,13 @@ def run_actions(
|
||||||
|
|
||||||
borg_mount.mount_archive(
|
borg_mount.mount_archive(
|
||||||
repository,
|
repository,
|
||||||
borg_list.resolve_archive_name(
|
borg_rlist.resolve_archive_name(
|
||||||
repository, arguments['mount'].archive, storage, local_path, remote_path
|
repository,
|
||||||
|
arguments['mount'].archive,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
),
|
),
|
||||||
arguments['mount'].mount_point,
|
arguments['mount'].mount_point,
|
||||||
arguments['mount'].paths,
|
arguments['mount'].paths,
|
||||||
|
@ -525,8 +541,13 @@ def run_actions(
|
||||||
if 'all' in restore_names:
|
if 'all' in restore_names:
|
||||||
restore_names = []
|
restore_names = []
|
||||||
|
|
||||||
archive_name = borg_list.resolve_archive_name(
|
archive_name = borg_rlist.resolve_archive_name(
|
||||||
repository, arguments['restore'].archive, storage, local_path, remote_path
|
repository,
|
||||||
|
arguments['restore'].archive,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
)
|
)
|
||||||
found_names = set()
|
found_names = set()
|
||||||
|
|
||||||
|
@ -596,20 +617,45 @@ def run_actions(
|
||||||
', '.join(missing_names)
|
', '.join(missing_names)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if 'rlist' in arguments:
|
||||||
|
if arguments['rlist'].repository is None or validate.repositories_match(
|
||||||
|
repository, arguments['rlist'].repository
|
||||||
|
):
|
||||||
|
rlist_arguments = copy.copy(arguments['rlist'])
|
||||||
|
if not rlist_arguments.json: # pragma: nocover
|
||||||
|
logger.warning('{}: Listing repository'.format(repository))
|
||||||
|
json_output = borg_rlist.list_repository(
|
||||||
|
repository,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
rlist_arguments=rlist_arguments,
|
||||||
|
local_path=local_path,
|
||||||
|
remote_path=remote_path,
|
||||||
|
)
|
||||||
|
if json_output: # pragma: nocover
|
||||||
|
yield json.loads(json_output)
|
||||||
if 'list' in arguments:
|
if 'list' in arguments:
|
||||||
if arguments['list'].repository is None or validate.repositories_match(
|
if arguments['list'].repository is None or validate.repositories_match(
|
||||||
repository, arguments['list'].repository
|
repository, arguments['list'].repository
|
||||||
):
|
):
|
||||||
list_arguments = copy.copy(arguments['list'])
|
list_arguments = copy.copy(arguments['list'])
|
||||||
if not list_arguments.json: # pragma: nocover
|
if not list_arguments.json: # pragma: nocover
|
||||||
logger.warning('{}: Listing archives'.format(repository))
|
if list_arguments.find_paths:
|
||||||
list_arguments.archive = borg_list.resolve_archive_name(
|
logger.warning('{}: Searching archives'.format(repository))
|
||||||
repository, list_arguments.archive, storage, local_path, remote_path
|
else:
|
||||||
|
logger.warning('{}: Listing archive'.format(repository))
|
||||||
|
list_arguments.archive = borg_rlist.resolve_archive_name(
|
||||||
|
repository,
|
||||||
|
list_arguments.archive,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
)
|
)
|
||||||
json_output = borg_list.list_archives(
|
json_output = borg_list.list_archive(
|
||||||
repository,
|
repository,
|
||||||
storage,
|
storage,
|
||||||
|
local_borg_version,
|
||||||
list_arguments=list_arguments,
|
list_arguments=list_arguments,
|
||||||
local_path=local_path,
|
local_path=local_path,
|
||||||
remote_path=remote_path,
|
remote_path=remote_path,
|
||||||
|
@ -640,8 +686,13 @@ def run_actions(
|
||||||
info_arguments = copy.copy(arguments['info'])
|
info_arguments = copy.copy(arguments['info'])
|
||||||
if not info_arguments.json: # pragma: nocover
|
if not info_arguments.json: # pragma: nocover
|
||||||
logger.warning('{}: Displaying archive summary information'.format(repository))
|
logger.warning('{}: Displaying archive summary information'.format(repository))
|
||||||
info_arguments.archive = borg_list.resolve_archive_name(
|
info_arguments.archive = borg_rlist.resolve_archive_name(
|
||||||
repository, info_arguments.archive, storage, local_path, remote_path
|
repository,
|
||||||
|
info_arguments.archive,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
)
|
)
|
||||||
json_output = borg_info.display_archives_info(
|
json_output = borg_info.display_archives_info(
|
||||||
repository,
|
repository,
|
||||||
|
@ -658,8 +709,13 @@ def run_actions(
|
||||||
repository, arguments['borg'].repository
|
repository, arguments['borg'].repository
|
||||||
):
|
):
|
||||||
logger.warning('{}: Running arbitrary Borg command'.format(repository))
|
logger.warning('{}: Running arbitrary Borg command'.format(repository))
|
||||||
archive_name = borg_list.resolve_archive_name(
|
archive_name = borg_rlist.resolve_archive_name(
|
||||||
repository, arguments['borg'].archive, storage, local_path, remote_path
|
repository,
|
||||||
|
arguments['borg'].archive,
|
||||||
|
storage,
|
||||||
|
local_borg_version,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
)
|
)
|
||||||
borg_borg.run_arbitrary_borg(
|
borg_borg.run_arbitrary_borg(
|
||||||
repository,
|
repository,
|
||||||
|
|
|
@ -4,7 +4,7 @@ COPY . /app
|
||||||
RUN apk add --no-cache py3-pip py3-ruamel.yaml py3-ruamel.yaml.clib
|
RUN apk add --no-cache py3-pip py3-ruamel.yaml py3-ruamel.yaml.clib
|
||||||
RUN pip install --no-cache /app && generate-borgmatic-config && chmod +r /etc/borgmatic/config.yaml
|
RUN pip install --no-cache /app && generate-borgmatic-config && chmod +r /etc/borgmatic/config.yaml
|
||||||
RUN borgmatic --help > /command-line.txt \
|
RUN borgmatic --help > /command-line.txt \
|
||||||
&& for action in init prune compact create check extract export-tar mount umount restore list info borg; do \
|
&& for action in rcreate prune compact create check extract export-tar mount umount restore rlist list rinfo info borg; do \
|
||||||
echo -e "\n--------------------------------------------------------------------------------\n" >> /command-line.txt \
|
echo -e "\n--------------------------------------------------------------------------------\n" >> /command-line.txt \
|
||||||
&& borgmatic "$action" --help >> /command-line.txt; done
|
&& borgmatic "$action" --help >> /command-line.txt; done
|
||||||
|
|
||||||
|
|
|
@ -133,14 +133,13 @@ that you'd like supported.
|
||||||
|
|
||||||
To restore a database dump from an archive, use the `borgmatic restore`
|
To restore a database dump from an archive, use the `borgmatic restore`
|
||||||
action. But the first step is to figure out which archive to restore from. A
|
action. But the first step is to figure out which archive to restore from. A
|
||||||
good way to do that is to use the `list` action:
|
good way to do that is to use the `rlist` action:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
borgmatic list
|
borgmatic rlist
|
||||||
```
|
```
|
||||||
|
|
||||||
(No borgmatic `list` action? Try the old-style `--list`, or upgrade
|
(No borgmatic `rlist` action? Try `list` instead or upgrade borgmatic!)
|
||||||
borgmatic!)
|
|
||||||
|
|
||||||
That should yield output looking something like:
|
That should yield output looking something like:
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,13 @@ eleventyNavigation:
|
||||||
|
|
||||||
When the worst happens—or you want to test your backups—the first step is
|
When the worst happens—or you want to test your backups—the first step is
|
||||||
to figure out which archive to extract. A good way to do that is to use the
|
to figure out which archive to extract. A good way to do that is to use the
|
||||||
`list` action:
|
`rlist` action:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
borgmatic list
|
borgmatic rlist
|
||||||
```
|
```
|
||||||
|
|
||||||
(No borgmatic `list` action? Try the old-style `--list`, or upgrade
|
(No borgmatic `rlist` action? Try `list` instead or upgrade borgmatic!)
|
||||||
borgmatic!)
|
|
||||||
|
|
||||||
That should yield output looking something like:
|
That should yield output looking something like:
|
||||||
|
|
||||||
|
|
|
@ -46,14 +46,20 @@ borgmatic list
|
||||||
borgmatic info
|
borgmatic info
|
||||||
```
|
```
|
||||||
|
|
||||||
<span class="minilink minilink-addedin">New in borgmatic version 2.0.0</span>
|
<span class="minilink minilink-addedin">New in borgmatic version 1.7.0</span>
|
||||||
There's also an `rinfo` action for displaying repository information with Borg
|
There are also `rlist` and `rinfo` actions for displaying repository
|
||||||
2.x:
|
information with Borg 2.x:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
borgmatic rlist
|
||||||
borgmatic rinfo
|
borgmatic rinfo
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See the [borgmatic command-line
|
||||||
|
reference](https://torsion.org/borgmatic/docs/reference/command-line/) for
|
||||||
|
more information.
|
||||||
|
|
||||||
|
|
||||||
### Searching for a file
|
### Searching for a file
|
||||||
|
|
||||||
<span class="minilink minilink-addedin">New in version 1.6.3</span> Let's say
|
<span class="minilink minilink-addedin">New in version 1.6.3</span> Let's say
|
||||||
|
|
|
@ -329,9 +329,9 @@ output only shows up at the console, and not in syslog.
|
||||||
|
|
||||||
### Latest backups
|
### Latest backups
|
||||||
|
|
||||||
All borgmatic actions that accept an "--archive" flag allow you to specify an
|
All borgmatic actions that accept an `--archive` flag allow you to specify an
|
||||||
archive name of "latest". This lets you get the latest archive without having
|
archive name of `latest`. This lets you get the latest archive without having
|
||||||
to first run "borgmatic list" manually, which can be handy in automated
|
to first run `borgmatic rlist` manually, which can be handy in automated
|
||||||
scripts. Here's an example:
|
scripts. Here's an example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -46,12 +46,11 @@ options, as that part is provided by borgmatic.
|
||||||
You can also specify Borg options for relevant commands:
|
You can also specify Borg options for relevant commands:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
borgmatic borg list --progress
|
borgmatic borg rlist --short
|
||||||
```
|
```
|
||||||
|
|
||||||
This runs Borg's `list` command once on each configured borgmatic
|
This runs Borg's `rlist` command once on each configured borgmatic repository.
|
||||||
repository. However, the native `borgmatic list` action should be preferred
|
However, the native `borgmatic rlist` action should be preferred for most use.
|
||||||
for most use.
|
|
||||||
|
|
||||||
What if you only want to run Borg on a single configured borgmatic repository
|
What if you only want to run Borg on a single configured borgmatic repository
|
||||||
when you've got several configured? Not a problem.
|
when you've got several configured? Not a problem.
|
||||||
|
@ -63,7 +62,7 @@ borgmatic borg --repository repo.borg break-lock
|
||||||
And what about a single archive?
|
And what about a single archive?
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
borgmatic borg --archive your-archive-name list
|
borgmatic borg --archive your-archive-name rlist
|
||||||
```
|
```
|
||||||
|
|
||||||
### Limitations
|
### Limitations
|
||||||
|
|
|
@ -23,101 +23,100 @@ def insert_execute_command_output_mock(command, result):
|
||||||
|
|
||||||
|
|
||||||
def test_extract_last_archive_dry_run_calls_borg_with_last_archive():
|
def test_extract_last_archive_dry_run_calls_borg_with_last_archive():
|
||||||
insert_execute_command_output_mock(
|
flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
|
||||||
('borg', 'list', '--short', 'repo'), result='archive1\narchive2\n'
|
insert_execute_command_mock(('borg', 'extract', '--dry-run', 'repo::archive'))
|
||||||
)
|
|
||||||
insert_execute_command_mock(('borg', 'extract', '--dry-run', 'repo::archive2'))
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
('repo::archive2',)
|
('repo::archive',)
|
||||||
)
|
|
||||||
|
|
||||||
module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
|
|
||||||
|
|
||||||
|
|
||||||
def test_extract_last_archive_dry_run_without_any_archives_should_not_raise():
|
|
||||||
insert_execute_command_output_mock(('borg', 'list', '--short', 'repo'), result='\n')
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(('repo',))
|
|
||||||
|
|
||||||
module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
|
|
||||||
|
|
||||||
|
|
||||||
def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_parameter():
|
|
||||||
insert_execute_command_output_mock(
|
|
||||||
('borg', 'list', '--short', '--info', 'repo'), result='archive1\narchive2\n'
|
|
||||||
)
|
|
||||||
insert_execute_command_mock(('borg', 'extract', '--dry-run', '--info', 'repo::archive2'))
|
|
||||||
insert_logging_mock(logging.INFO)
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
|
||||||
('repo::archive2',)
|
|
||||||
)
|
|
||||||
|
|
||||||
module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
|
|
||||||
|
|
||||||
|
|
||||||
def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_parameter():
|
|
||||||
insert_execute_command_output_mock(
|
|
||||||
('borg', 'list', '--short', '--debug', '--show-rc', 'repo'), result='archive1\narchive2\n'
|
|
||||||
)
|
|
||||||
insert_execute_command_mock(
|
|
||||||
('borg', 'extract', '--dry-run', '--debug', '--show-rc', '--list', 'repo::archive2')
|
|
||||||
)
|
|
||||||
insert_logging_mock(logging.DEBUG)
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
|
||||||
('repo::archive2',)
|
|
||||||
)
|
|
||||||
|
|
||||||
module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
|
|
||||||
|
|
||||||
|
|
||||||
def test_extract_last_archive_dry_run_calls_borg_via_local_path():
|
|
||||||
insert_execute_command_output_mock(
|
|
||||||
('borg1', 'list', '--short', 'repo'), result='archive1\narchive2\n'
|
|
||||||
)
|
|
||||||
insert_execute_command_mock(('borg1', 'extract', '--dry-run', 'repo::archive2'))
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
|
||||||
('repo::archive2',)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
module.extract_last_archive_dry_run(
|
module.extract_last_archive_dry_run(
|
||||||
storage_config={}, repository='repo', lock_wait=None, local_path='borg1'
|
storage_config={}, local_borg_version='1.2.3', repository='repo', lock_wait=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_last_archive_dry_run_without_any_archives_should_not_raise():
|
||||||
|
flexmock(module.rlist).should_receive('resolve_archive_name').and_raise(ValueError)
|
||||||
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
module.extract_last_archive_dry_run(
|
||||||
|
storage_config={}, local_borg_version='1.2.3', repository='repo', lock_wait=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_parameter():
|
||||||
|
flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
|
||||||
|
insert_execute_command_mock(('borg', 'extract', '--dry-run', '--info', 'repo::archive'))
|
||||||
|
insert_logging_mock(logging.INFO)
|
||||||
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
|
('repo::archive',)
|
||||||
|
)
|
||||||
|
|
||||||
|
module.extract_last_archive_dry_run(
|
||||||
|
storage_config={}, local_borg_version='1.2.3', repository='repo', lock_wait=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_parameter():
|
||||||
|
flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
|
||||||
|
insert_execute_command_mock(
|
||||||
|
('borg', 'extract', '--dry-run', '--debug', '--show-rc', '--list', 'repo::archive')
|
||||||
|
)
|
||||||
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
|
('repo::archive',)
|
||||||
|
)
|
||||||
|
|
||||||
|
module.extract_last_archive_dry_run(
|
||||||
|
storage_config={}, local_borg_version='1.2.3', repository='repo', lock_wait=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_last_archive_dry_run_calls_borg_via_local_path():
|
||||||
|
flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
|
||||||
|
insert_execute_command_mock(('borg1', 'extract', '--dry-run', 'repo::archive'))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
|
('repo::archive',)
|
||||||
|
)
|
||||||
|
|
||||||
|
module.extract_last_archive_dry_run(
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
repository='repo',
|
||||||
|
lock_wait=None,
|
||||||
|
local_path='borg1',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_extract_last_archive_dry_run_calls_borg_with_remote_path_parameters():
|
def test_extract_last_archive_dry_run_calls_borg_with_remote_path_parameters():
|
||||||
insert_execute_command_output_mock(
|
flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
|
||||||
('borg', 'list', '--short', '--remote-path', 'borg1', 'repo'), result='archive1\narchive2\n'
|
|
||||||
)
|
|
||||||
insert_execute_command_mock(
|
insert_execute_command_mock(
|
||||||
('borg', 'extract', '--dry-run', '--remote-path', 'borg1', 'repo::archive2')
|
('borg', 'extract', '--dry-run', '--remote-path', 'borg1', 'repo::archive')
|
||||||
)
|
)
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
('repo::archive2',)
|
('repo::archive',)
|
||||||
)
|
)
|
||||||
|
|
||||||
module.extract_last_archive_dry_run(
|
module.extract_last_archive_dry_run(
|
||||||
storage_config={}, repository='repo', lock_wait=None, remote_path='borg1'
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
repository='repo',
|
||||||
|
lock_wait=None,
|
||||||
|
remote_path='borg1',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_parameters():
|
def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_parameters():
|
||||||
insert_execute_command_output_mock(
|
flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
|
||||||
('borg', 'list', '--short', '--lock-wait', '5', 'repo'), result='archive1\narchive2\n'
|
|
||||||
)
|
|
||||||
insert_execute_command_mock(
|
insert_execute_command_mock(
|
||||||
('borg', 'extract', '--dry-run', '--lock-wait', '5', 'repo::archive2')
|
('borg', 'extract', '--dry-run', '--lock-wait', '5', 'repo::archive')
|
||||||
)
|
)
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
('repo::archive2',)
|
('repo::archive',)
|
||||||
)
|
)
|
||||||
|
|
||||||
module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=5)
|
module.extract_last_archive_dry_run(
|
||||||
|
storage_config={}, local_borg_version='1.2.3', repository='repo', lock_wait=5
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_extract_archive_calls_borg_with_path_parameters():
|
def test_extract_archive_calls_borg_with_path_parameters():
|
||||||
|
|
|
@ -8,129 +8,17 @@ from borgmatic.borg import list as module
|
||||||
|
|
||||||
from ..test_verbosity import insert_logging_mock
|
from ..test_verbosity import insert_logging_mock
|
||||||
|
|
||||||
BORG_LIST_LATEST_ARGUMENTS = (
|
|
||||||
'--last',
|
|
||||||
'1',
|
|
||||||
'--short',
|
|
||||||
'repo',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_passes_through_non_latest_archive_name():
|
|
||||||
archive = 'myhost-2030-01-01T14:41:17.647620'
|
|
||||||
|
|
||||||
assert module.resolve_archive_name('repo', archive, storage_config={}) == archive
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_calls_borg_with_parameters():
|
|
||||||
expected_archive = 'archive-name'
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
|
||||||
('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path='borg',
|
|
||||||
extra_environment=None,
|
|
||||||
).and_return(expected_archive + '\n')
|
|
||||||
|
|
||||||
assert module.resolve_archive_name('repo', 'latest', storage_config={}) == expected_archive
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_with_log_info_calls_borg_with_info_parameter():
|
|
||||||
expected_archive = 'archive-name'
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
|
||||||
('borg', 'list', '--info') + BORG_LIST_LATEST_ARGUMENTS,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path='borg',
|
|
||||||
extra_environment=None,
|
|
||||||
).and_return(expected_archive + '\n')
|
|
||||||
insert_logging_mock(logging.INFO)
|
|
||||||
|
|
||||||
assert module.resolve_archive_name('repo', 'latest', storage_config={}) == expected_archive
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_with_log_debug_calls_borg_with_debug_parameter():
|
|
||||||
expected_archive = 'archive-name'
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
|
||||||
('borg', 'list', '--debug', '--show-rc') + BORG_LIST_LATEST_ARGUMENTS,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path='borg',
|
|
||||||
extra_environment=None,
|
|
||||||
).and_return(expected_archive + '\n')
|
|
||||||
insert_logging_mock(logging.DEBUG)
|
|
||||||
|
|
||||||
assert module.resolve_archive_name('repo', 'latest', storage_config={}) == expected_archive
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_with_local_path_calls_borg_via_local_path():
|
|
||||||
expected_archive = 'archive-name'
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
|
||||||
('borg1', 'list') + BORG_LIST_LATEST_ARGUMENTS,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path='borg1',
|
|
||||||
extra_environment=None,
|
|
||||||
).and_return(expected_archive + '\n')
|
|
||||||
|
|
||||||
assert (
|
|
||||||
module.resolve_archive_name('repo', 'latest', storage_config={}, local_path='borg1')
|
|
||||||
== expected_archive
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_parameters():
|
|
||||||
expected_archive = 'archive-name'
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
|
||||||
('borg', 'list', '--remote-path', 'borg1') + BORG_LIST_LATEST_ARGUMENTS,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path='borg',
|
|
||||||
extra_environment=None,
|
|
||||||
).and_return(expected_archive + '\n')
|
|
||||||
|
|
||||||
assert (
|
|
||||||
module.resolve_archive_name('repo', 'latest', storage_config={}, remote_path='borg1')
|
|
||||||
== expected_archive
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_without_archives_raises():
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
|
||||||
('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path='borg',
|
|
||||||
extra_environment=None,
|
|
||||||
).and_return('')
|
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
module.resolve_archive_name('repo', 'latest', storage_config={})
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
|
||||||
expected_archive = 'archive-name'
|
|
||||||
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
|
||||||
('borg', 'list', '--lock-wait', 'okay') + BORG_LIST_LATEST_ARGUMENTS,
|
|
||||||
output_log_level=None,
|
|
||||||
borg_local_path='borg',
|
|
||||||
extra_environment=None,
|
|
||||||
).and_return(expected_archive + '\n')
|
|
||||||
|
|
||||||
assert (
|
|
||||||
module.resolve_archive_name('repo', 'latest', storage_config={'lock_wait': 'okay'})
|
|
||||||
== expected_archive
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_log_info():
|
def test_make_list_command_includes_log_info():
|
||||||
insert_logging_mock(logging.INFO)
|
insert_logging_mock(logging.INFO)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=False),
|
list_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -139,10 +27,14 @@ def test_make_list_command_includes_log_info():
|
||||||
|
|
||||||
def test_make_list_command_includes_json_but_not_info():
|
def test_make_list_command_includes_json_but_not_info():
|
||||||
insert_logging_mock(logging.INFO)
|
insert_logging_mock(logging.INFO)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=True),
|
list_arguments=flexmock(archive=None, paths=None, json=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -151,10 +43,14 @@ def test_make_list_command_includes_json_but_not_info():
|
||||||
|
|
||||||
def test_make_list_command_includes_log_debug():
|
def test_make_list_command_includes_log_debug():
|
||||||
insert_logging_mock(logging.DEBUG)
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=False),
|
list_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -163,10 +59,14 @@ def test_make_list_command_includes_log_debug():
|
||||||
|
|
||||||
def test_make_list_command_includes_json_but_not_debug():
|
def test_make_list_command_includes_json_but_not_debug():
|
||||||
insert_logging_mock(logging.DEBUG)
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=True),
|
list_arguments=flexmock(archive=None, paths=None, json=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -174,9 +74,14 @@ def test_make_list_command_includes_json_but_not_debug():
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_json():
|
def test_make_list_command_includes_json():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=True),
|
list_arguments=flexmock(archive=None, paths=None, json=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -184,9 +89,16 @@ def test_make_list_command_includes_json():
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_lock_wait():
|
def test_make_list_command_includes_lock_wait():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(
|
||||||
|
('--lock-wait', '5')
|
||||||
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={'lock_wait': 5},
|
storage_config={'lock_wait': 5},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=False),
|
list_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -194,9 +106,16 @@ def test_make_list_command_includes_lock_wait():
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_archive():
|
def test_make_list_command_includes_archive():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
|
('repo::archive',)
|
||||||
|
)
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive='archive', paths=None, json=False),
|
list_arguments=flexmock(archive='archive', paths=None, json=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -204,9 +123,16 @@ def test_make_list_command_includes_archive():
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_archive_and_path():
|
def test_make_list_command_includes_archive_and_path():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
|
('repo::archive',)
|
||||||
|
)
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive='archive', paths=['var/lib'], json=False),
|
list_arguments=flexmock(archive='archive', paths=['var/lib'], json=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -214,9 +140,14 @@ def test_make_list_command_includes_archive_and_path():
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_local_path():
|
def test_make_list_command_includes_local_path():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=False),
|
list_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
local_path='borg2',
|
local_path='borg2',
|
||||||
)
|
)
|
||||||
|
@ -225,9 +156,16 @@ def test_make_list_command_includes_local_path():
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_remote_path():
|
def test_make_list_command_includes_remote_path():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(
|
||||||
|
('--remote-path', 'borg2')
|
||||||
|
).and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=False),
|
list_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
remote_path='borg2',
|
remote_path='borg2',
|
||||||
)
|
)
|
||||||
|
@ -236,9 +174,14 @@ def test_make_list_command_includes_remote_path():
|
||||||
|
|
||||||
|
|
||||||
def test_make_list_command_includes_short():
|
def test_make_list_command_includes_short():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--short',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(archive=None, paths=None, json=False, short=True),
|
list_arguments=flexmock(archive=None, paths=None, json=False, short=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -260,16 +203,23 @@ def test_make_list_command_includes_short():
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_make_list_command_includes_additional_flags(argument_name):
|
def test_make_list_command_includes_additional_flags(argument_name):
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
||||||
|
(f"--{argument_name.replace('_', '-')}", 'value')
|
||||||
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
command = module.make_list_command(
|
command = module.make_list_command(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=flexmock(
|
list_arguments=flexmock(
|
||||||
archive=None,
|
archive=None,
|
||||||
paths=None,
|
paths=None,
|
||||||
json=False,
|
json=False,
|
||||||
find_paths=None,
|
find_paths=None,
|
||||||
format=None,
|
format=None,
|
||||||
**{argument_name: 'value'}
|
**{argument_name: 'value'},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -303,89 +253,109 @@ def test_make_find_paths_adds_globs_to_path_fragments():
|
||||||
assert module.make_find_paths(('foo.txt',)) == ('sh:**/*foo.txt*/**',)
|
assert module.make_find_paths(('foo.txt',)) == ('sh:**/*foo.txt*/**',)
|
||||||
|
|
||||||
|
|
||||||
def test_list_archives_calls_borg_with_parameters():
|
def test_list_archive_calls_borg_with_parameters():
|
||||||
list_arguments = argparse.Namespace(archive=None, paths=None, json=False, find_paths=None)
|
list_arguments = argparse.Namespace(archive='archive', paths=None, json=False, find_paths=None)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
flexmock(module).should_receive('make_list_command').with_args(
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=list_arguments,
|
list_arguments=list_arguments,
|
||||||
local_path='borg',
|
local_path='borg',
|
||||||
remote_path=None,
|
remote_path=None,
|
||||||
).and_return(('borg', 'list', 'repo'))
|
).and_return(('borg', 'list', 'repo::archive'))
|
||||||
flexmock(module).should_receive('make_find_paths').and_return(())
|
flexmock(module).should_receive('make_find_paths').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'list', 'repo'),
|
('borg', 'list', 'repo::archive'),
|
||||||
output_log_level=logging.WARNING,
|
output_log_level=logging.WARNING,
|
||||||
borg_local_path='borg',
|
borg_local_path='borg',
|
||||||
extra_environment=None,
|
extra_environment=None,
|
||||||
).once()
|
).once()
|
||||||
|
|
||||||
module.list_archives(
|
module.list_archive(
|
||||||
repository='repo', storage_config={}, list_arguments=list_arguments,
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_list_archives_with_json_suppresses_most_borg_output():
|
def test_list_archive_with_json_suppresses_most_borg_output():
|
||||||
list_arguments = argparse.Namespace(archive=None, paths=None, json=True, find_paths=None)
|
list_arguments = argparse.Namespace(archive='archive', paths=None, json=True, find_paths=None)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
flexmock(module).should_receive('make_list_command').with_args(
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=list_arguments,
|
list_arguments=list_arguments,
|
||||||
local_path='borg',
|
local_path='borg',
|
||||||
remote_path=None,
|
remote_path=None,
|
||||||
).and_return(('borg', 'list', 'repo'))
|
).and_return(('borg', 'list', 'repo::archive'))
|
||||||
flexmock(module).should_receive('make_find_paths').and_return(())
|
flexmock(module).should_receive('make_find_paths').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'list', 'repo'),
|
('borg', 'list', 'repo::archive'),
|
||||||
output_log_level=None,
|
output_log_level=None,
|
||||||
borg_local_path='borg',
|
borg_local_path='borg',
|
||||||
extra_environment=None,
|
extra_environment=None,
|
||||||
).once()
|
).once()
|
||||||
|
|
||||||
module.list_archives(
|
module.list_archive(
|
||||||
repository='repo', storage_config={}, list_arguments=list_arguments,
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_list_archives_calls_borg_with_local_path():
|
def test_list_archive_calls_borg_with_local_path():
|
||||||
list_arguments = argparse.Namespace(archive=None, paths=None, json=False, find_paths=None)
|
list_arguments = argparse.Namespace(archive='archive', paths=None, json=False, find_paths=None)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
flexmock(module).should_receive('make_list_command').with_args(
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=list_arguments,
|
list_arguments=list_arguments,
|
||||||
local_path='borg2',
|
local_path='borg2',
|
||||||
remote_path=None,
|
remote_path=None,
|
||||||
).and_return(('borg2', 'list', 'repo'))
|
).and_return(('borg2', 'list', 'repo::archive'))
|
||||||
flexmock(module).should_receive('make_find_paths').and_return(())
|
flexmock(module).should_receive('make_find_paths').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg2', 'list', 'repo'),
|
('borg2', 'list', 'repo::archive'),
|
||||||
output_log_level=logging.WARNING,
|
output_log_level=logging.WARNING,
|
||||||
borg_local_path='borg2',
|
borg_local_path='borg2',
|
||||||
extra_environment=None,
|
extra_environment=None,
|
||||||
).once()
|
).once()
|
||||||
|
|
||||||
module.list_archives(
|
module.list_archive(
|
||||||
repository='repo', storage_config={}, list_arguments=list_arguments, local_path='borg2',
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
|
local_path='borg2',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_list_archives_calls_borg_multiple_times_with_find_paths():
|
def test_list_archive_calls_borg_multiple_times_with_find_paths():
|
||||||
glob_paths = ('**/*foo.txt*/**',)
|
glob_paths = ('**/*foo.txt*/**',)
|
||||||
list_arguments = argparse.Namespace(
|
list_arguments = argparse.Namespace(
|
||||||
archive=None, paths=None, json=False, find_paths=['foo.txt'], format=None
|
archive=None,
|
||||||
|
json=False,
|
||||||
|
find_paths=['foo.txt'],
|
||||||
|
prefix=None,
|
||||||
|
glob_archives=None,
|
||||||
|
sort_by=None,
|
||||||
|
first=None,
|
||||||
|
last=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
flexmock(module).should_receive('make_list_command').and_return(
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
('borg', 'list', 'repo')
|
flexmock(module.rlist).should_receive('make_rlist_command').and_return(('borg', 'list', 'repo'))
|
||||||
).and_return(('borg', 'list', 'repo::archive1')).and_return(('borg', 'list', 'repo::archive2'))
|
|
||||||
flexmock(module).should_receive('make_find_paths').and_return(glob_paths)
|
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'list', 'repo'),
|
('borg', 'list', 'repo'),
|
||||||
output_log_level=None,
|
output_log_level=None,
|
||||||
|
@ -394,6 +364,10 @@ def test_list_archives_calls_borg_multiple_times_with_find_paths():
|
||||||
).and_return(
|
).and_return(
|
||||||
'archive1 Sun, 2022-05-29 15:27:04 [abc]\narchive2 Mon, 2022-05-30 19:47:15 [xyz]'
|
'archive1 Sun, 2022-05-29 15:27:04 [abc]\narchive2 Mon, 2022-05-30 19:47:15 [xyz]'
|
||||||
).once()
|
).once()
|
||||||
|
flexmock(module).should_receive('make_list_command').and_return(
|
||||||
|
('borg', 'list', 'repo::archive1')
|
||||||
|
).and_return(('borg', 'list', 'repo::archive2'))
|
||||||
|
flexmock(module).should_receive('make_find_paths').and_return(glob_paths)
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'list', 'repo::archive1') + glob_paths,
|
('borg', 'list', 'repo::archive1') + glob_paths,
|
||||||
|
@ -408,17 +382,22 @@ def test_list_archives_calls_borg_multiple_times_with_find_paths():
|
||||||
extra_environment=None,
|
extra_environment=None,
|
||||||
).once()
|
).once()
|
||||||
|
|
||||||
module.list_archives(
|
module.list_archive(
|
||||||
repository='repo', storage_config={}, list_arguments=list_arguments,
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_list_archives_calls_borg_with_archive():
|
def test_list_archive_calls_borg_with_archive():
|
||||||
list_arguments = argparse.Namespace(archive='archive', paths=None, json=False, find_paths=None)
|
list_arguments = argparse.Namespace(archive='archive', paths=None, json=False, find_paths=None)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
flexmock(module).should_receive('make_list_command').with_args(
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
list_arguments=list_arguments,
|
list_arguments=list_arguments,
|
||||||
local_path='borg',
|
local_path='borg',
|
||||||
remote_path=None,
|
remote_path=None,
|
||||||
|
@ -432,6 +411,124 @@ def test_list_archives_calls_borg_with_archive():
|
||||||
extra_environment=None,
|
extra_environment=None,
|
||||||
).once()
|
).once()
|
||||||
|
|
||||||
module.list_archives(
|
module.list_archive(
|
||||||
repository='repo', storage_config={}, list_arguments=list_arguments,
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_archive_without_archive_delegates_to_list_repository():
|
||||||
|
list_arguments = argparse.Namespace(
|
||||||
|
archive=None,
|
||||||
|
short=None,
|
||||||
|
format=None,
|
||||||
|
json=None,
|
||||||
|
prefix=None,
|
||||||
|
glob_archives=None,
|
||||||
|
sort_by=None,
|
||||||
|
first=None,
|
||||||
|
last=None,
|
||||||
|
find_paths=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
|
flexmock(module.rlist).should_receive('list_repository')
|
||||||
|
flexmock(module.environment).should_receive('make_environment').never()
|
||||||
|
flexmock(module).should_receive('execute_command').never()
|
||||||
|
|
||||||
|
module.list_archive(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_archive_with_borg_features_without_archive_delegates_to_list_repository():
|
||||||
|
list_arguments = argparse.Namespace(
|
||||||
|
archive=None,
|
||||||
|
short=None,
|
||||||
|
format=None,
|
||||||
|
json=None,
|
||||||
|
prefix=None,
|
||||||
|
glob_archives=None,
|
||||||
|
sort_by=None,
|
||||||
|
first=None,
|
||||||
|
last=None,
|
||||||
|
find_paths=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.rlist).should_receive('list_repository')
|
||||||
|
flexmock(module.environment).should_receive('make_environment').never()
|
||||||
|
flexmock(module).should_receive('execute_command').never()
|
||||||
|
|
||||||
|
module.list_archive(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'archive_filter_flag', ('prefix', 'glob_archives', 'sort_by', 'first', 'last',),
|
||||||
|
)
|
||||||
|
def test_list_archive_with_archive_disallows_archive_filter_flag_if_rlist_feature_available(
|
||||||
|
archive_filter_flag,
|
||||||
|
):
|
||||||
|
list_arguments = argparse.Namespace(
|
||||||
|
archive='archive', paths=None, json=False, find_paths=None, **{archive_filter_flag: 'foo'}
|
||||||
|
)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').with_args(
|
||||||
|
module.feature.Feature.RLIST, '1.2.3'
|
||||||
|
).and_return(True)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
module.list_archive(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'archive_filter_flag', ('prefix', 'glob_archives', 'sort_by', 'first', 'last',),
|
||||||
|
)
|
||||||
|
def test_list_archive_with_archive_allows_archive_filter_flag_if_rlist_feature_unavailable(
|
||||||
|
archive_filter_flag,
|
||||||
|
):
|
||||||
|
list_arguments = argparse.Namespace(
|
||||||
|
archive='archive', paths=None, json=False, find_paths=None, **{archive_filter_flag: 'foo'}
|
||||||
|
)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').with_args(
|
||||||
|
module.feature.Feature.RLIST, '1.2.3'
|
||||||
|
).and_return(False)
|
||||||
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
).and_return(('borg', 'list', 'repo::archive'))
|
||||||
|
flexmock(module).should_receive('make_find_paths').and_return(())
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list', 'repo::archive'),
|
||||||
|
output_log_level=logging.WARNING,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).once()
|
||||||
|
|
||||||
|
module.list_archive(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=list_arguments,
|
||||||
)
|
)
|
||||||
|
|
381
tests/unit/borg/test_rlist.py
Normal file
381
tests/unit/borg/test_rlist.py
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from flexmock import flexmock
|
||||||
|
|
||||||
|
from borgmatic.borg import rlist as module
|
||||||
|
|
||||||
|
from ..test_verbosity import insert_logging_mock
|
||||||
|
|
||||||
|
BORG_LIST_LATEST_ARGUMENTS = (
|
||||||
|
'--last',
|
||||||
|
'1',
|
||||||
|
'--short',
|
||||||
|
'repo',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_passes_through_non_latest_archive_name():
|
||||||
|
archive = 'myhost-2030-01-01T14:41:17.647620'
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.resolve_archive_name('repo', archive, storage_config={}, local_borg_version='1.2.3')
|
||||||
|
== archive
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_calls_borg_with_parameters():
|
||||||
|
expected_archive = 'archive-name'
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return(expected_archive + '\n')
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3')
|
||||||
|
== expected_archive
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_with_log_info_calls_borg_with_info_parameter():
|
||||||
|
expected_archive = 'archive-name'
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list', '--info') + BORG_LIST_LATEST_ARGUMENTS,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return(expected_archive + '\n')
|
||||||
|
insert_logging_mock(logging.INFO)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3')
|
||||||
|
== expected_archive
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_with_log_debug_calls_borg_with_debug_parameter():
|
||||||
|
expected_archive = 'archive-name'
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list', '--debug', '--show-rc') + BORG_LIST_LATEST_ARGUMENTS,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return(expected_archive + '\n')
|
||||||
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3')
|
||||||
|
== expected_archive
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_with_local_path_calls_borg_via_local_path():
|
||||||
|
expected_archive = 'archive-name'
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg1', 'list') + BORG_LIST_LATEST_ARGUMENTS,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg1',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return(expected_archive + '\n')
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.resolve_archive_name(
|
||||||
|
'repo', 'latest', storage_config={}, local_borg_version='1.2.3', local_path='borg1'
|
||||||
|
)
|
||||||
|
== expected_archive
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_parameters():
|
||||||
|
expected_archive = 'archive-name'
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list', '--remote-path', 'borg1') + BORG_LIST_LATEST_ARGUMENTS,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return(expected_archive + '\n')
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.resolve_archive_name(
|
||||||
|
'repo', 'latest', storage_config={}, local_borg_version='1.2.3', remote_path='borg1'
|
||||||
|
)
|
||||||
|
== expected_archive
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_without_archives_raises():
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return('')
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3')
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
||||||
|
expected_archive = 'archive-name'
|
||||||
|
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list', '--lock-wait', 'okay') + BORG_LIST_LATEST_ARGUMENTS,
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return(expected_archive + '\n')
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.resolve_archive_name(
|
||||||
|
'repo', 'latest', storage_config={'lock_wait': 'okay'}, local_borg_version='1.2.3'
|
||||||
|
)
|
||||||
|
== expected_archive
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_log_info():
|
||||||
|
insert_logging_mock(logging.INFO)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--info', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_json_but_not_info():
|
||||||
|
insert_logging_mock(logging.INFO)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--json', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_log_debug():
|
||||||
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--debug', '--show-rc', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_json_but_not_debug():
|
||||||
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--json', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_json():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--json', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_lock_wait():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(
|
||||||
|
('--lock-wait', '5')
|
||||||
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={'lock_wait': 5},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--lock-wait', '5', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_local_path():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
|
local_path='borg2',
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg2', 'list', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_remote_path():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(
|
||||||
|
('--remote-path', 'borg2')
|
||||||
|
).and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False),
|
||||||
|
remote_path='borg2',
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--remote-path', 'borg2', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_includes_short():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--short',))
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False, short=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--short', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'argument_name',
|
||||||
|
(
|
||||||
|
'prefix',
|
||||||
|
'glob_archives',
|
||||||
|
'sort_by',
|
||||||
|
'first',
|
||||||
|
'last',
|
||||||
|
'exclude',
|
||||||
|
'exclude_from',
|
||||||
|
'pattern',
|
||||||
|
'patterns_from',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_make_rlist_command_includes_additional_flags(argument_name):
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
||||||
|
(f"--{argument_name.replace('_', '-')}", 'value')
|
||||||
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(
|
||||||
|
archive=None,
|
||||||
|
paths=None,
|
||||||
|
json=False,
|
||||||
|
find_paths=None,
|
||||||
|
format=None,
|
||||||
|
**{argument_name: 'value'},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--' + argument_name.replace('_', '-'), 'value', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_repository_calls_borg_with_parameters():
|
||||||
|
rlist_arguments = argparse.Namespace(json=False)
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
|
flexmock(module).should_receive('make_rlist_command').with_args(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=rlist_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
).and_return(('borg', 'rlist', 'repo'))
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'rlist', 'repo'),
|
||||||
|
output_log_level=logging.WARNING,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).once()
|
||||||
|
|
||||||
|
module.list_repository(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=rlist_arguments,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_repository_with_json_returns_borg_output():
|
||||||
|
rlist_arguments = argparse.Namespace(json=True)
|
||||||
|
json_output = flexmock()
|
||||||
|
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
|
flexmock(module).should_receive('make_rlist_command').with_args(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=rlist_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
).and_return(('borg', 'rlist', 'repo'))
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').and_return(json_output)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.list_repository(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=rlist_arguments,
|
||||||
|
)
|
||||||
|
== json_output
|
||||||
|
)
|
|
@ -571,10 +571,35 @@ def test_run_actions_does_not_raise_for_mount_action():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_actions_does_not_raise_for_rlist_action():
|
||||||
|
flexmock(module.validate).should_receive('repositories_match').and_return(True)
|
||||||
|
flexmock(module.borg_rlist).should_receive('list_repository')
|
||||||
|
arguments = {
|
||||||
|
'global': flexmock(monitoring_verbosity=1, dry_run=False),
|
||||||
|
'rlist': flexmock(repository=flexmock(), json=flexmock()),
|
||||||
|
}
|
||||||
|
|
||||||
|
list(
|
||||||
|
module.run_actions(
|
||||||
|
arguments=arguments,
|
||||||
|
config_filename='test.yaml',
|
||||||
|
location={'repositories': ['repo']},
|
||||||
|
storage={},
|
||||||
|
retention={},
|
||||||
|
consistency={},
|
||||||
|
hooks={},
|
||||||
|
local_path=None,
|
||||||
|
remote_path=None,
|
||||||
|
local_borg_version=None,
|
||||||
|
repository_path='repo',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_actions_does_not_raise_for_list_action():
|
def test_run_actions_does_not_raise_for_list_action():
|
||||||
flexmock(module.validate).should_receive('repositories_match').and_return(True)
|
flexmock(module.validate).should_receive('repositories_match').and_return(True)
|
||||||
flexmock(module.borg_list).should_receive('resolve_archive_name').and_return(flexmock())
|
flexmock(module.borg_rlist).should_receive('resolve_archive_name').and_return(flexmock())
|
||||||
flexmock(module.borg_list).should_receive('list_archives')
|
flexmock(module.borg_list).should_receive('list_archive')
|
||||||
arguments = {
|
arguments = {
|
||||||
'global': flexmock(monitoring_verbosity=1, dry_run=False),
|
'global': flexmock(monitoring_verbosity=1, dry_run=False),
|
||||||
'list': flexmock(repository=flexmock(), archive=flexmock(), json=flexmock()),
|
'list': flexmock(repository=flexmock(), archive=flexmock(), json=flexmock()),
|
||||||
|
@ -624,7 +649,7 @@ def test_run_actions_does_not_raise_for_rinfo_action():
|
||||||
|
|
||||||
def test_run_actions_does_not_raise_for_info_action():
|
def test_run_actions_does_not_raise_for_info_action():
|
||||||
flexmock(module.validate).should_receive('repositories_match').and_return(True)
|
flexmock(module.validate).should_receive('repositories_match').and_return(True)
|
||||||
flexmock(module.borg_list).should_receive('resolve_archive_name').and_return(flexmock())
|
flexmock(module.borg_rlist).should_receive('resolve_archive_name').and_return(flexmock())
|
||||||
flexmock(module.borg_info).should_receive('display_archives_info')
|
flexmock(module.borg_info).should_receive('display_archives_info')
|
||||||
arguments = {
|
arguments = {
|
||||||
'global': flexmock(monitoring_verbosity=1, dry_run=False),
|
'global': flexmock(monitoring_verbosity=1, dry_run=False),
|
||||||
|
@ -650,7 +675,7 @@ def test_run_actions_does_not_raise_for_info_action():
|
||||||
|
|
||||||
def test_run_actions_does_not_raise_for_borg_action():
|
def test_run_actions_does_not_raise_for_borg_action():
|
||||||
flexmock(module.validate).should_receive('repositories_match').and_return(True)
|
flexmock(module.validate).should_receive('repositories_match').and_return(True)
|
||||||
flexmock(module.borg_list).should_receive('resolve_archive_name').and_return(flexmock())
|
flexmock(module.borg_rlist).should_receive('resolve_archive_name').and_return(flexmock())
|
||||||
flexmock(module.borg_borg).should_receive('run_arbitrary_borg')
|
flexmock(module.borg_borg).should_receive('run_arbitrary_borg')
|
||||||
arguments = {
|
arguments = {
|
||||||
'global': flexmock(monitoring_verbosity=1, dry_run=False),
|
'global': flexmock(monitoring_verbosity=1, dry_run=False),
|
||||||
|
|
Loading…
Reference in a new issue