Add support for logging each log line as a JSON object via global "--log-json" flag (#680).

This commit is contained in:
Dan Helfman 2023-05-08 23:00:49 -07:00
parent b3b08ee6d7
commit 92a2230a07
56 changed files with 934 additions and 105 deletions

1
NEWS
View File

@ -7,6 +7,7 @@
commands with arguments.
* #678: Fix calls to psql in PostgreSQL hook to ignore "~/.psqlrc", whose settings can break
database dumping.
* #680: Add support for logging each log line as a JSON object via global "--log-json" flag.
* #682: Fix "source_directories_must_exist" option to expand globs and tildes in source directories.
* #684: Rename "master" development branch to "main" to use more inclusive language. You'll need to
update your development checkouts accordingly.

View File

@ -12,6 +12,7 @@ def run_borg(
storage,
local_borg_version,
borg_arguments,
global_arguments,
local_path,
remote_path,
):
@ -27,6 +28,7 @@ def run_borg(
borg_arguments.archive,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
)

View File

@ -11,6 +11,7 @@ def run_break_lock(
storage,
local_borg_version,
break_lock_arguments,
global_arguments,
local_path,
remote_path,
):
@ -25,6 +26,7 @@ def run_break_lock(
repository['path'],
storage,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
)

View File

@ -44,6 +44,7 @@ def run_check(
storage,
consistency,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
progress=check_arguments.progress,

View File

@ -45,6 +45,7 @@ def run_compact(
repository['path'],
storage,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
progress=compact_arguments.progress,

View File

@ -67,6 +67,7 @@ def run_create(
location,
storage,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
progress=create_arguments.progress,

View File

@ -33,6 +33,7 @@ def run_export_tar(
export_tar_arguments.archive,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
),
@ -40,6 +41,7 @@ def run_export_tar(
export_tar_arguments.destination,
storage,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
tar_filter=export_tar_arguments.tar_filter,

View File

@ -44,6 +44,7 @@ def run_extract(
extract_arguments.archive,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
),
@ -51,6 +52,7 @@ def run_extract(
location,
storage,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
destination_path=extract_arguments.destination,

View File

@ -13,6 +13,7 @@ def run_info(
storage,
local_borg_version,
info_arguments,
global_arguments,
local_path,
remote_path,
):
@ -31,6 +32,7 @@ def run_info(
info_arguments.archive,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
)
@ -38,9 +40,10 @@ def run_info(
repository['path'],
storage,
local_borg_version,
info_arguments=info_arguments,
local_path=local_path,
remote_path=remote_path,
info_arguments,
global_arguments,
local_path,
remote_path,
)
if json_output: # pragma: nocover
yield json.loads(json_output)

View File

@ -12,6 +12,7 @@ def run_list(
storage,
local_borg_version,
list_arguments,
global_arguments,
local_path,
remote_path,
):
@ -33,6 +34,7 @@ def run_list(
list_arguments.archive,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
)
@ -40,9 +42,10 @@ def run_list(
repository['path'],
storage,
local_borg_version,
list_arguments=list_arguments,
local_path=local_path,
remote_path=remote_path,
list_arguments,
global_arguments,
local_path,
remote_path,
)
if json_output: # pragma: nocover
yield json.loads(json_output)

View File

@ -12,6 +12,7 @@ def run_mount(
storage,
local_borg_version,
mount_arguments,
global_arguments,
local_path,
remote_path,
):
@ -33,6 +34,7 @@ def run_mount(
mount_arguments.archive,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
),
@ -42,6 +44,7 @@ def run_mount(
mount_arguments.options,
storage,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
)

View File

@ -44,6 +44,7 @@ def run_prune(
storage,
retention,
local_borg_version,
global_arguments,
local_path=local_path,
remote_path=remote_path,
stats=prune_arguments.stats,

View File

@ -29,6 +29,7 @@ def run_rcreate(
repository['path'],
storage,
local_borg_version,
global_arguments,
rcreate_arguments.encryption_mode,
rcreate_arguments.source_repository,
rcreate_arguments.copy_crypt_key,

View File

@ -93,6 +93,7 @@ def restore_single_database(
location_config=location,
storage_config=storage,
local_borg_version=local_borg_version,
global_arguments=global_arguments,
local_path=local_path,
remote_path=remote_path,
destination_path='/',
@ -119,14 +120,15 @@ def collect_archive_database_names(
location,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
):
'''
Given a local or remote repository path, a resolved archive name, a location configuration dict,
a storage configuration dict, the local Borg version, and local and remote Borg paths, query the
archive for the names of databases it contains and return them as a dict from hook name to a
sequence of database names.
a storage configuration dict, the local Borg version, global_arguments an argparse.Namespace,
and local and remote Borg paths, query the archive for the names of databases it contains and
return them as a dict from hook name to a sequence of database names.
'''
borgmatic_source_directory = os.path.expanduser(
location.get(
@ -141,6 +143,7 @@ def collect_archive_database_names(
archive,
storage,
local_borg_version,
global_arguments,
list_path=parent_dump_path,
local_path=local_path,
remote_path=remote_path,
@ -279,6 +282,7 @@ def run_restore(
restore_arguments.archive,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
)
@ -288,6 +292,7 @@ def run_restore(
location,
storage,
local_borg_version,
global_arguments,
local_path,
remote_path,
)

View File

@ -12,6 +12,7 @@ def run_rinfo(
storage,
local_borg_version,
rinfo_arguments,
global_arguments,
local_path,
remote_path,
):
@ -31,6 +32,7 @@ def run_rinfo(
storage,
local_borg_version,
rinfo_arguments=rinfo_arguments,
global_arguments=global_arguments,
local_path=local_path,
remote_path=remote_path,
)

View File

@ -12,6 +12,7 @@ def run_rlist(
storage,
local_borg_version,
rlist_arguments,
global_arguments,
local_path,
remote_path,
):
@ -31,6 +32,7 @@ def run_rlist(
storage,
local_borg_version,
rlist_arguments=rlist_arguments,
global_arguments=global_arguments,
local_path=local_path,
remote_path=remote_path,
)

View File

@ -24,6 +24,7 @@ def run_transfer(
storage,
local_borg_version,
transfer_arguments,
global_arguments,
local_path=local_path,
remote_path=remote_path,
)

View File

@ -10,13 +10,14 @@ def break_lock(
repository_path,
storage_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
):
'''
Given a local or remote repository path, a storage configuration dict, the local Borg version,
and optional local and remote Borg paths, break any repository and cache locks leftover from Borg
aborting.
an argparse.Namespace of global arguments, and optional local and remote Borg paths, break any
repository and cache locks leftover from Borg aborting.
'''
umask = storage_config.get('umask', None)
lock_wait = storage_config.get('lock_wait', None)
@ -25,6 +26,7 @@ def break_lock(
(local_path, 'break-lock')
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())

View File

@ -259,6 +259,7 @@ def check_archives(
storage_config,
consistency_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
progress=None,
@ -283,6 +284,7 @@ def check_archives(
storage_config,
local_borg_version,
argparse.Namespace(json=True),
global_arguments,
local_path,
remote_path,
)
@ -317,6 +319,7 @@ def check_archives(
+ (('--repair',) if repair else ())
+ make_check_flags(local_borg_version, storage_config, checks, check_last, prefix)
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ verbosity_flags
+ (('--progress',) if progress else ())
@ -340,6 +343,12 @@ def check_archives(
if 'extract' in checks:
extract.extract_last_archive_dry_run(
storage_config, local_borg_version, repository_path, lock_wait, local_path, remote_path
storage_config,
local_borg_version,
global_arguments,
repository_path,
lock_wait,
local_path,
remote_path,
)
write_check_time(make_check_time_path(location_config, borg_repository_id, 'extract'))

View File

@ -11,6 +11,7 @@ def compact_segments(
repository_path,
storage_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
progress=False,
@ -29,6 +30,7 @@ def compact_segments(
(local_path, 'compact')
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--progress',) if progress else ())
+ (('--cleanup-commits',) if cleanup_commits else ())

View File

@ -326,6 +326,7 @@ def create_archive(
location_config,
storage_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
progress=False,
@ -438,6 +439,7 @@ def create_archive(
+ (('--files-cache', files_cache) if files_cache else ())
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (
('--list', '--filter', list_filter_flags)

View File

@ -15,6 +15,7 @@ def export_tar_archive(
destination_path,
storage_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
tar_filter=None,
@ -38,6 +39,7 @@ def export_tar_archive(
(local_path, 'export-tar')
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ (('--list',) if list_files else ())

View File

@ -12,6 +12,7 @@ logger = logging.getLogger(__name__)
def extract_last_archive_dry_run(
storage_config,
local_borg_version,
global_arguments,
repository_path,
lock_wait=None,
local_path='borg',
@ -21,8 +22,6 @@ def extract_last_archive_dry_run(
Perform an extraction dry-run of the most recent archive. If there are no archives, skip the
dry-run.
'''
remote_path_flags = ('--remote-path', remote_path) if remote_path else ()
lock_wait_flags = ('--lock-wait', str(lock_wait)) if lock_wait else ()
verbosity_flags = ()
if logger.isEnabledFor(logging.DEBUG):
verbosity_flags = ('--debug', '--show-rc')
@ -31,7 +30,13 @@ def extract_last_archive_dry_run(
try:
last_archive_name = rlist.resolve_archive_name(
repository_path, 'latest', storage_config, local_borg_version, local_path, remote_path
repository_path,
'latest',
storage_config,
local_borg_version,
global_arguments,
local_path,
remote_path,
)
except ValueError:
logger.warning('No archives found. Skipping extract consistency check.')
@ -41,8 +46,9 @@ def extract_last_archive_dry_run(
borg_environment = environment.make_environment(storage_config)
full_extract_command = (
(local_path, 'extract', '--dry-run')
+ remote_path_flags
+ lock_wait_flags
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ verbosity_flags
+ list_flag
+ flags.make_repository_archive_flags(
@ -63,6 +69,7 @@ def extract_archive(
location_config,
storage_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
destination_path=None,
@ -72,9 +79,9 @@ def extract_archive(
):
'''
Given a dry-run flag, a local or remote repository path, an archive name, zero or more paths to
restore from the archive, the local Borg version string, location/storage configuration dicts,
optional local and remote Borg paths, and an optional destination path to extract to, extract
the archive into the current directory.
restore from the archive, the local Borg version string, an argparse.Namespace of global
arguments, location/storage configuration dicts, optional local and remote Borg paths, and an
optional destination path to extract to, extract the archive into the current directory.
If extract to stdout is True, then start the extraction streaming to stdout, and return that
extract process as an instance of subprocess.Popen.
@ -102,6 +109,7 @@ def extract_archive(
+ (('--remote-path', remote_path) if remote_path else ())
+ numeric_ids_flags
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ (('--debug', '--list', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())

View File

@ -12,13 +12,14 @@ def display_archives_info(
storage_config,
local_borg_version,
info_arguments,
global_arguments,
local_path='borg',
remote_path=None,
):
'''
Given a local or remote repository path, a storage config dict, the local Borg version, and the
arguments to the info action, display summary information for Borg archives in the repository or
return JSON summary information.
Given a local or remote repository path, a storage config dict, the local Borg version, global
arguments as an argparse.Namespace, and the arguments to the info action, display summary
information for Borg archives in the repository or return JSON summary information.
'''
borgmatic.logger.add_custom_log_levels()
lock_wait = storage_config.get('lock_wait', None)
@ -36,6 +37,7 @@ def display_archives_info(
else ()
)
+ flags.make_flags('remote-path', remote_path)
+ flags.make_flags('log-json', global_arguments.log_json)
+ flags.make_flags('lock-wait', lock_wait)
+ (
(

View File

@ -25,6 +25,7 @@ def make_list_command(
storage_config,
local_borg_version,
list_arguments,
global_arguments,
local_path='borg',
remote_path=None,
):
@ -48,6 +49,7 @@ def make_list_command(
else ()
)
+ flags.make_flags('remote-path', remote_path)
+ flags.make_flags('log-json', global_arguments.log_json)
+ flags.make_flags('lock-wait', lock_wait)
+ flags.make_flags_from_arguments(list_arguments, excludes=MAKE_FLAGS_EXCLUDES)
+ (
@ -90,14 +92,16 @@ def capture_archive_listing(
archive,
storage_config,
local_borg_version,
global_arguments,
list_path=None,
local_path='borg',
remote_path=None,
):
'''
Given a local or remote repository path, an archive name, a storage config dict, the local Borg
version, the archive path in which to list files, and local and remote Borg paths, capture the
output of listing that archive and return it as a list of file paths.
version, global arguments as an argparse.Namespace, the archive path in which to list files, and
local and remote Borg paths, capture the output of listing that archive and return it as a list
of file paths.
'''
borg_environment = environment.make_environment(storage_config)
@ -115,6 +119,7 @@ def capture_archive_listing(
json=None,
format='{path}{NL}', # noqa: FS003
),
global_arguments,
local_path,
remote_path,
),
@ -130,15 +135,17 @@ def list_archive(
storage_config,
local_borg_version,
list_arguments,
global_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
the files of a Borg archive (or return JSON output). If list_arguments.find_paths are given,
list the files by searching across multiple archives. If neither find_paths nor archive name
are given, instead list the archives in the given repository.
Given a local or remote repository path, a storage config dict, the local Borg version, global
arguments as an argparse.Namespace, the arguments to the list action as an argparse.Namespace,
and local and remote Borg paths, display the output of listing the files of a Borg archive (or
return JSON output). If list_arguments.find_paths are given, list the files by searching across
multiple archives. If neither find_paths nor archive name are given, instead list the archives
in the given repository.
'''
borgmatic.logger.add_custom_log_levels()
@ -164,6 +171,7 @@ def list_archive(
storage_config,
local_borg_version,
rlist_arguments,
global_arguments,
local_path,
remote_path,
)
@ -205,6 +213,7 @@ def list_archive(
storage_config,
local_borg_version,
rlist_arguments,
global_arguments,
local_path,
remote_path,
),
@ -233,6 +242,7 @@ def list_archive(
storage_config,
local_borg_version,
archive_arguments,
global_arguments,
local_path,
remote_path,
) + make_find_paths(list_arguments.find_paths)

View File

@ -15,14 +15,15 @@ def mount_archive(
options,
storage_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
):
'''
Given a local or remote repository path, an optional archive name, a filesystem mount point,
zero or more paths to mount from the archive, extra Borg mount options, a storage configuration
dict, the local Borg version, and optional local and remote Borg paths, mount the archive onto
the mount point.
dict, the local Borg version, global arguments as an argparse.Namespace instance, and optional
local and remote Borg paths, mount the archive onto the mount point.
'''
umask = storage_config.get('umask', None)
lock_wait = storage_config.get('lock_wait', None)
@ -31,6 +32,7 @@ def mount_archive(
(local_path, 'mount')
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())

View File

@ -53,6 +53,7 @@ def prune_archives(
storage_config,
retention_config,
local_borg_version,
global_arguments,
local_path='borg',
remote_path=None,
stats=False,
@ -73,6 +74,7 @@ def prune_archives(
+ make_prune_flags(storage_config, retention_config, local_borg_version)
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--umask', str(umask)) if umask else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--stats',) if stats and not dry_run else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())

View File

@ -16,6 +16,7 @@ def create_repository(
repository_path,
storage_config,
local_borg_version,
global_arguments,
encryption_mode,
source_repository=None,
copy_crypt_key=False,
@ -37,6 +38,7 @@ def create_repository(
storage_config,
local_borg_version,
argparse.Namespace(json=True),
global_arguments,
local_path,
remote_path,
)
@ -46,6 +48,7 @@ def create_repository(
if error.returncode != RINFO_REPOSITORY_NOT_FOUND_EXIT_CODE:
raise
lock_wait = storage_config.get('lock_wait')
extra_borg_options = storage_config.get('extra_borg_options', {}).get('rcreate', '')
rcreate_command = (
@ -63,6 +66,8 @@ def create_repository(
+ (('--make-parent-dirs',) if make_parent_dirs else ())
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ (('--debug',) if logger.isEnabledFor(logging.DEBUG) else ())
+ (('--log-json',) if global_arguments.log_json else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--remote-path', remote_path) if remote_path else ())
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
+ flags.make_repository_flags(repository_path, local_borg_version)

View File

@ -12,13 +12,14 @@ def display_repository_info(
storage_config,
local_borg_version,
rinfo_arguments,
global_arguments,
local_path='borg',
remote_path=None,
):
'''
Given a local or remote repository path, a storage config dict, the local Borg version, and the
arguments to the rinfo action, display summary information for the Borg repository or return
JSON summary information.
Given a local or remote repository path, a storage config dict, the local Borg version, the
arguments to the rinfo action, and global arguments as an argparse.Namespace, display summary
information for the Borg repository or return JSON summary information.
'''
borgmatic.logger.add_custom_log_levels()
lock_wait = storage_config.get('lock_wait', None)
@ -41,6 +42,7 @@ def display_repository_info(
else ()
)
+ flags.make_flags('remote-path', remote_path)
+ flags.make_flags('log-json', global_arguments.log_json)
+ flags.make_flags('lock-wait', lock_wait)
+ (('--json',) if rinfo_arguments.json else ())
+ flags.make_repository_flags(repository_path, local_borg_version)

View File

@ -12,28 +12,29 @@ def resolve_archive_name(
archive,
storage_config,
local_borg_version,
global_arguments,
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, return the archive name. But if the archive name is "latest",
then instead introspect the repository for the latest archive and return its name.
Given a local or remote repository path, an archive name, a storage config dict, the local Borg
version, global arguments as an argparse.Namespace, a local Borg path, and a remote Borg path,
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',
)
+ flags.make_flags('remote-path', remote_path)
+ flags.make_flags('lock-wait', lock_wait)
+ flags.make_flags('log-json', global_arguments.log_json)
+ flags.make_flags('lock-wait', storage_config.get('lock_wait'))
+ flags.make_flags('last', 1)
+ ('--short',)
+ flags.make_repository_flags(repository_path, local_borg_version)
@ -61,16 +62,15 @@ def make_rlist_command(
storage_config,
local_borg_version,
rlist_arguments,
global_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.
arguments to the rlist action, global arguments as an argparse.Namespace instance, 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,
@ -87,7 +87,8 @@ def make_rlist_command(
else ()
)
+ flags.make_flags('remote-path', remote_path)
+ flags.make_flags('lock-wait', lock_wait)
+ flags.make_flags('log-json', global_arguments.log_json)
+ flags.make_flags('lock-wait', storage_config.get('lock_wait'))
+ (
(
flags.make_flags('match-archives', f'sh:{rlist_arguments.prefix}*')
@ -113,13 +114,15 @@ def list_repository(
storage_config,
local_borg_version,
rlist_arguments,
global_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).
arguments to the list action, global arguments as an argparse.Namespace instance, and local and
remote Borg paths, display the output of listing Borg archives in the given repository (or
return JSON output).
'''
borgmatic.logger.add_custom_log_levels()
borg_environment = environment.make_environment(storage_config)
@ -129,6 +132,7 @@ def list_repository(
storage_config,
local_borg_version,
rlist_arguments,
global_arguments,
local_path,
remote_path,
)

View File

@ -13,12 +13,14 @@ def transfer_archives(
storage_config,
local_borg_version,
transfer_arguments,
global_arguments,
local_path='borg',
remote_path=None,
):
'''
Given a dry-run flag, a local or remote repository path, a storage config dict, the local Borg
version, and the arguments to the transfer action, transfer archives to the given repository.
version, the arguments to the transfer action, and global arguments as an argparse.Namespace
instance, transfer archives to the given repository.
'''
borgmatic.logger.add_custom_log_levels()
@ -27,6 +29,7 @@ def transfer_archives(
+ (('--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('log-json', global_arguments.log_json)
+ flags.make_flags('lock-wait', storage_config.get('lock_wait', None))
+ (
flags.make_flags_from_arguments(

View File

@ -187,6 +187,11 @@ def make_parsers():
type=str,
help='Log format string used for log messages written to the log file',
)
global_group.add_argument(
'--log-json',
action='store_true',
help='Write log messages and console output as one JSON object per log line instead of formatted text',
)
global_group.add_argument(
'--override',
metavar='SECTION.OPTION=VALUE',

View File

@ -398,7 +398,8 @@ def run_actions(
repository,
storage,
local_borg_version,
arguments['mount'],
action_arguments,
global_arguments,
local_path,
remote_path,
)
@ -420,6 +421,7 @@ def run_actions(
storage,
local_borg_version,
action_arguments,
global_arguments,
local_path,
remote_path,
)
@ -429,6 +431,7 @@ def run_actions(
storage,
local_borg_version,
action_arguments,
global_arguments,
local_path,
remote_path,
)
@ -438,6 +441,7 @@ def run_actions(
storage,
local_borg_version,
action_arguments,
global_arguments,
local_path,
remote_path,
)
@ -447,6 +451,7 @@ def run_actions(
storage,
local_borg_version,
action_arguments,
global_arguments,
local_path,
remote_path,
)
@ -455,7 +460,8 @@ def run_actions(
repository,
storage,
local_borg_version,
arguments['break-lock'],
action_arguments,
global_arguments,
local_path,
remote_path,
)
@ -465,6 +471,7 @@ def run_actions(
storage,
local_borg_version,
action_arguments,
global_arguments,
local_path,
remote_path,
)

View File

@ -1,3 +1,4 @@
import argparse
import copy
from flexmock import flexmock
@ -58,7 +59,12 @@ def test_transfer_archives_command_does_not_duplicate_flags_or_raise():
continue
borgmatic.borg.transfer.transfer_archives(
False, 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
False,
'repo',
{},
'2.3.4',
fuzz_argument(arguments, argument_name),
global_arguments=flexmock(log_json=False),
)
@ -70,7 +76,11 @@ def test_make_list_command_does_not_duplicate_flags_or_raise():
continue
command = borgmatic.borg.list.make_list_command(
'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
'repo',
{},
'2.3.4',
fuzz_argument(arguments, argument_name),
argparse.Namespace(log_json=False),
)
assert_command_does_not_duplicate_flags(command)
@ -84,7 +94,11 @@ def test_make_rlist_command_does_not_duplicate_flags_or_raise():
continue
command = borgmatic.borg.rlist.make_rlist_command(
'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
'repo',
{},
'2.3.4',
fuzz_argument(arguments, argument_name),
global_arguments=flexmock(log_json=True),
)
assert_command_does_not_duplicate_flags(command)
@ -104,5 +118,9 @@ def test_display_archives_info_command_does_not_duplicate_flags_or_raise():
continue
borgmatic.borg.info.display_archives_info(
'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
'repo',
{},
'2.3.4',
fuzz_argument(arguments, argument_name),
argparse.Namespace(log_json=False),
)

View File

@ -16,6 +16,7 @@ def test_run_borg_does_not_raise():
repository={'path': 'repos'},
storage={},
local_borg_version=None,
global_arguments=flexmock(log_json=False),
borg_arguments=borg_arguments,
local_path=None,
remote_path=None,

View File

@ -14,6 +14,7 @@ def test_run_break_lock_does_not_raise():
storage={},
local_borg_version=None,
break_lock_arguments=break_lock_arguments,
global_arguments=flexmock(),
local_path=None,
remote_path=None,
)

View File

@ -18,6 +18,7 @@ def test_run_info_does_not_raise():
storage={},
local_borg_version=None,
info_arguments=info_arguments,
global_arguments=flexmock(log_json=False),
local_path=None,
remote_path=None,
)

View File

@ -18,6 +18,7 @@ def test_run_list_does_not_raise():
storage={},
local_borg_version=None,
list_arguments=list_arguments,
global_arguments=flexmock(log_json=False),
local_path=None,
remote_path=None,
)

View File

@ -21,6 +21,7 @@ def test_run_mount_does_not_raise():
storage={},
local_borg_version=None,
mount_arguments=mount_arguments,
global_arguments=flexmock(log_json=False),
local_path=None,
remote_path=None,
)

View File

@ -72,6 +72,7 @@ def test_collect_archive_database_names_parses_archive_paths():
location={'borgmatic_source_directory': '.borgmatic'},
storage=flexmock(),
local_borg_version=flexmock(),
global_arguments=flexmock(log_json=False),
local_path=flexmock(),
remote_path=flexmock(),
)
@ -97,6 +98,7 @@ def test_collect_archive_database_names_parses_directory_format_archive_paths():
location={'borgmatic_source_directory': '.borgmatic'},
storage=flexmock(),
local_borg_version=flexmock(),
global_arguments=flexmock(log_json=False),
local_path=flexmock(),
remote_path=flexmock(),
)
@ -118,6 +120,7 @@ def test_collect_archive_database_names_skips_bad_archive_paths():
location={'borgmatic_source_directory': '.borgmatic'},
storage=flexmock(),
local_borg_version=flexmock(),
global_arguments=flexmock(log_json=False),
local_path=flexmock(),
remote_path=flexmock(),
)

View File

@ -15,6 +15,7 @@ def test_run_rinfo_does_not_raise():
storage={},
local_borg_version=None,
rinfo_arguments=rinfo_arguments,
global_arguments=flexmock(log_json=False),
local_path=None,
remote_path=None,
)

View File

@ -15,6 +15,7 @@ def test_run_rlist_does_not_raise():
storage={},
local_borg_version=None,
rlist_arguments=rlist_arguments,
global_arguments=flexmock(),
local_path=None,
remote_path=None,
)

View File

@ -24,6 +24,7 @@ def test_break_lock_calls_borg_with_required_flags():
repository_path='repo',
storage_config={},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),
)
@ -35,6 +36,7 @@ def test_break_lock_calls_borg_with_remote_path_flags():
repository_path='repo',
storage_config={},
local_borg_version='1.2.3',
global_arguments=flexmock(log_json=False),