Hello community, here is the log from the commit of package borgmatic for openSUSE:Factory checked in at 2020-07-28 17:27:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/borgmatic (Old) and /work/SRC/openSUSE:Factory/.borgmatic.new.3592 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "borgmatic" Tue Jul 28 17:27:50 2020 rev:23 rq:823146 version:1.5.9 Changes: -------- --- /work/SRC/openSUSE:Factory/borgmatic/borgmatic.changes 2020-07-15 15:03:16.291307727 +0200 +++ /work/SRC/openSUSE:Factory/.borgmatic.new.3592/borgmatic.changes 2020-07-28 17:29:23.762180962 +0200 @@ -1,0 +2,12 @@ +Tue Jul 28 06:57:42 UTC 2020 - Martin Rey <[email protected]> + +- Update to 1.5.9 +* #300: Add “borgmatic export-tar” action to export an archive to a + tar-formatted file or stream. +* #339: Fix for intermittent timing-related test failure of logging + function. +* Clarify database documentation about excluding named pipes and + character/block devices to prevent + hangs. + +------------------------------------------------------------------- Old: ---- borgmatic-1.5.8.tar.gz New: ---- borgmatic-1.5.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ borgmatic.spec ++++++ --- /var/tmp/diff_new_pack.Lcti5d/_old 2020-07-28 17:29:24.790182129 +0200 +++ /var/tmp/diff_new_pack.Lcti5d/_new 2020-07-28 17:29:24.790182129 +0200 @@ -17,7 +17,7 @@ Name: borgmatic -Version: 1.5.8 +Version: 1.5.9 Release: 0 Summary: Automation tool for borgbackup License: GPL-3.0-only ++++++ borgmatic-1.5.8.tar.gz -> borgmatic-1.5.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/NEWS new/borgmatic-1.5.9/NEWS --- old/borgmatic-1.5.8/NEWS 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/NEWS 2020-07-23 06:53:55.000000000 +0200 @@ -1,3 +1,11 @@ +1.5.9 + * #300: Add "borgmatic export-tar" action to export an archive to a tar-formatted file or stream. + * #339: Fix for intermittent timing-related test failure of logging function. + * Clarify database documentation about excluding named pipes and character/block devices to prevent + hangs. + * Add documentation on how to make backups redundant with multiple repositories: + https://torsion.org/borgmatic/docs/how-to/make-backups-redundant/ + 1.5.8 * #336: Fix for traceback when running Cronitor, Cronhub, and PagerDuty monitor hooks. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/README.md new/borgmatic-1.5.9/README.md --- old/borgmatic-1.5.8/README.md 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/README.md 2020-07-23 06:53:55.000000000 +0200 @@ -75,6 +75,7 @@ * [Set up backups with borgmatic](https://torsion.org/borgmatic/docs/how-to/set-up-backups/) ⬅ *Start here!* * [Make per-application backups](https://torsion.org/borgmatic/docs/how-to/make-per-application-backups/) + * [Make backups redundant](https://torsion.org/borgmatic/docs/how-to/make-backups-redundant/) * [Deal with very large backups](https://torsion.org/borgmatic/docs/how-to/deal-with-very-large-backups/) * [Inspect your backups](https://torsion.org/borgmatic/docs/how-to/inspect-your-backups/) * [Monitor your backups](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/borgmatic/borg/export_tar.py new/borgmatic-1.5.9/borgmatic/borg/export_tar.py --- old/borgmatic-1.5.8/borgmatic/borg/export_tar.py 1970-01-01 01:00:00.000000000 +0100 +++ new/borgmatic-1.5.9/borgmatic/borg/export_tar.py 2020-07-23 06:53:55.000000000 +0200 @@ -0,0 +1,64 @@ +import logging +import os + +from borgmatic.execute import DO_NOT_CAPTURE, execute_command + +logger = logging.getLogger(__name__) + + +def export_tar_archive( + dry_run, + repository, + archive, + paths, + destination_path, + storage_config, + local_path='borg', + remote_path=None, + tar_filter=None, + files=False, + strip_components=None, +): + ''' + Given a dry-run flag, a local or remote repository path, an archive name, zero or more paths to + export from the archive, a destination path to export to, a storage configuration dict, optional + local and remote Borg paths, an optional filter program, whether to include per-file details, + and an optional number of path components to strip, export the archive into the given + destination path as a tar-formatted file. + + If the destination path is "-", then stream the output to stdout instead of to a file. + ''' + umask = storage_config.get('umask', None) + lock_wait = storage_config.get('lock_wait', None) + + full_command = ( + (local_path, 'export-tar') + + (('--remote-path', remote_path) if remote_path else ()) + + (('--umask', str(umask)) if umask else ()) + + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + + (('--list',) if files else ()) + + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + + (('--dry-run',) if dry_run else ()) + + (('--tar-filter', tar_filter) if tar_filter else ()) + + (('--strip-components', str(strip_components)) if strip_components else ()) + + ('::'.join((repository if ':' in repository else os.path.abspath(repository), archive)),) + + (destination_path,) + + (tuple(paths) if paths else ()) + ) + + if files and logger.getEffectiveLevel() == logging.WARNING: + output_log_level = logging.WARNING + else: + output_log_level = logging.INFO + + if dry_run: + logging.info('{}: Skipping export to tar file (dry run)'.format(repository)) + return + + execute_command( + full_command, + output_file=DO_NOT_CAPTURE if destination_path == '-' else None, + output_log_level=output_log_level, + borg_local_path=local_path, + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/borgmatic/commands/arguments.py new/borgmatic-1.5.9/borgmatic/commands/arguments.py --- old/borgmatic-1.5.8/borgmatic/commands/arguments.py 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/borgmatic/commands/arguments.py 2020-07-23 06:53:55.000000000 +0200 @@ -9,6 +9,7 @@ 'create': ['--create', '-C'], 'check': ['--check', '-k'], 'extract': ['--extract', '-x'], + 'export-tar': ['--export-tar'], 'mount': ['--mount', '-m'], 'umount': ['--umount', '-u'], 'restore': ['--restore', '-r'], @@ -358,6 +359,52 @@ '-h', '--help', action='help', help='Show this help message and exit' ) + export_tar_parser = subparsers.add_parser( + 'export-tar', + aliases=SUBPARSER_ALIASES['export-tar'], + help='Export an archive to a tar-formatted file or stream', + description='Export an archive to a tar-formatted file or stream', + add_help=False, + ) + export_tar_group = export_tar_parser.add_argument_group('export-tar arguments') + export_tar_group.add_argument( + '--repository', + help='Path of repository to export from, defaults to the configured repository if there is only one', + ) + export_tar_group.add_argument( + '--archive', help='Name of archive to export (or "latest")', required=True + ) + export_tar_group.add_argument( + '--path', + metavar='PATH', + nargs='+', + dest='paths', + help='Paths to export from archive, defaults to the entire archive', + ) + export_tar_group.add_argument( + '--destination', + metavar='PATH', + dest='destination', + help='Path to destination export tar file, or "-" for stdout (but be careful about dirtying output with --verbosity or --files)', + required=True, + ) + export_tar_group.add_argument( + '--tar-filter', help='Name of filter program to pipe data through' + ) + export_tar_group.add_argument( + '--files', default=False, action='store_true', help='Show per-file details' + ) + export_tar_group.add_argument( + '--strip-components', + type=int, + metavar='NUMBER', + dest='strip_components', + help='Number of leading path components to remove from each exported path. Skip paths with fewer elements', + ) + export_tar_group.add_argument( + '-h', '--help', action='help', help='Show this help message and exit' + ) + mount_parser = subparsers.add_parser( 'mount', aliases=SUBPARSER_ALIASES['mount'], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/borgmatic/commands/borgmatic.py new/borgmatic-1.5.9/borgmatic/commands/borgmatic.py --- old/borgmatic-1.5.8/borgmatic/commands/borgmatic.py 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/borgmatic/commands/borgmatic.py 2020-07-23 06:53:55.000000000 +0200 @@ -12,6 +12,7 @@ from borgmatic.borg import check as borg_check from borgmatic.borg import create as borg_create from borgmatic.borg import environment as borg_environment +from borgmatic.borg import export_tar as borg_export_tar from borgmatic.borg import extract as borg_extract from borgmatic.borg import info as borg_info from borgmatic.borg import init as borg_init @@ -347,6 +348,30 @@ strip_components=arguments['extract'].strip_components, progress=arguments['extract'].progress, ) + if 'export-tar' in arguments: + if arguments['export-tar'].repository is None or validate.repositories_match( + repository, arguments['export-tar'].repository + ): + logger.info( + '{}: Exporting archive {} as tar file'.format( + repository, arguments['export-tar'].archive + ) + ) + borg_export_tar.export_tar_archive( + global_arguments.dry_run, + repository, + borg_list.resolve_archive_name( + repository, arguments['export-tar'].archive, storage, local_path, remote_path + ), + arguments['export-tar'].paths, + arguments['export-tar'].destination, + storage, + local_path=local_path, + remote_path=remote_path, + tar_filter=arguments['export-tar'].tar_filter, + files=arguments['export-tar'].files, + strip_components=arguments['export-tar'].strip_components, + ) if 'mount' in arguments: if arguments['mount'].repository is None or validate.repositories_match( repository, arguments['mount'].repository diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/borgmatic/config/schema.yaml new/borgmatic-1.5.9/borgmatic/config/schema.yaml --- old/borgmatic-1.5.8/borgmatic/config/schema.yaml 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/borgmatic/config/schema.yaml 2020-07-23 06:53:55.000000000 +0200 @@ -329,8 +329,8 @@ Retention policy for how many backups to keep in each category. See https://borgbackup.readthedocs.io/en/stable/usage/prune.html for details. At least one of the "keep" options is required for pruning - to work. See borgmatic documentation if you'd like to skip pruning - entirely. + to work. To skip pruning entirely, run "borgmatic create" or "check" + without the "prune" action. See borgmatic documentation for details. map: keep_within: type: str diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/borgmatic/execute.py new/borgmatic-1.5.9/borgmatic/execute.py --- old/borgmatic-1.5.8/borgmatic/execute.py 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/borgmatic/execute.py 2020-07-23 06:53:55.000000000 +0200 @@ -84,9 +84,14 @@ logger.log(output_log_level, line) + still_running = False + for process in processes: exit_code = process.poll() if output_buffers else process.wait() + if exit_code is None: + still_running = True + # If any process errors, then raise accordingly. if exit_code_indicates_error(process, exit_code, borg_local_path): # If an error occurs, include its output in the raised exception so that we don't @@ -108,7 +113,7 @@ exit_code, command_for_process(process), '\n'.join(last_lines) ) - if all(process.poll() is not None for process in processes): + if not still_running: break # Consume any remaining output that we missed (if any). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/docs/how-to/backup-to-a-removable-drive-or-an-intermittent-server.md new/borgmatic-1.5.9/docs/how-to/backup-to-a-removable-drive-or-an-intermittent-server.md --- old/borgmatic-1.5.8/docs/how-to/backup-to-a-removable-drive-or-an-intermittent-server.md 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/docs/how-to/backup-to-a-removable-drive-or-an-intermittent-server.md 2020-07-23 06:53:55.000000000 +0200 @@ -103,5 +103,6 @@ * [Set up backups with borgmatic](https://torsion.org/borgmatic/docs/how-to/set-up-backups/) * [Make per-application backups](https://torsion.org/borgmatic/docs/how-to/make-per-application-backups/) + * [Make backups redundant](https://torsion.org/borgmatic/docs/how-to/make-backups-redundant/) * [Add preparation and cleanup steps to backups](https://torsion.org/borgmatic/docs/how-to/add-preparation-and-cleanup-steps-to-backups/) * [Monitor your backups](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/docs/how-to/backup-your-databases.md new/borgmatic-1.5.9/docs/how-to/backup-your-databases.md --- old/borgmatic-1.5.8/docs/how-to/backup-your-databases.md 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/docs/how-to/backup-your-databases.md 2020-07-23 06:53:55.000000000 +0200 @@ -34,6 +34,7 @@ Also note that using a database hook implicitly enables both the `read_special` and `one_file_system` configuration settings (even if they're disabled in your configuration) to support this dump and restore streaming. +See Limitations below for more on this. Here's a more involved example that connects to remote databases: @@ -167,6 +168,12 @@ backups to avoid getting caught without a way to restore a database. 3. borgmatic does not currently support backing up or restoring multiple databases that share the exact same name on different hosts. +4. Because database hooks implicitly enable the `read_special` configuration +setting to support dump and restore streaming, you'll need to ensure that any +special files are excluded from backups (named pipes, block devices, and +character devices) to prevent hanging. Try a command like `find / -type c,b,p` +to find such files. Common directories to exclude are `/dev` and `/run`, but +that may not be exhaustive. ### Manual restoration @@ -205,6 +212,12 @@ options: "--single-transaction --quick" ``` +### borgmatic hangs during backup + +See Limitations above about `read_special`. You may need to exclude certain +paths with named pipes, block devices, or character devices on which borgmatic +is hanging. + ## Related documentation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/docs/how-to/make-backups-redundant.md new/borgmatic-1.5.9/docs/how-to/make-backups-redundant.md --- old/borgmatic-1.5.8/docs/how-to/make-backups-redundant.md 1970-01-01 01:00:00.000000000 +0100 +++ new/borgmatic-1.5.9/docs/how-to/make-backups-redundant.md 2020-07-23 06:53:55.000000000 +0200 @@ -0,0 +1,47 @@ +--- +title: How to make backups redundant +--- +## Multiple repositories + +If you really care about your data, you probably want more than one backup of +it. borgmatic supports this in its configuration by specifying multiple backup +repositories. Here's an example: + +```yaml +location: + # List of source directories to backup. + source_directories: + - /home + - /etc + + # Paths of local or remote repositories to backup to. + repositories: + - [email protected]:backups.borg + - [email protected]:repo + - /var/lib/backups/local.borg +``` + +When you run borgmatic with this configuration, it invokes Borg once for each +configured repository in sequence. (So, not in parallel.) That means—in each +repository—borgmatic creates a single new backup archive containing all of +your source directories. + +Here's a way of visualizing what borgmatic does with the above configuration: + +1. Backup `/home` and `/etc` to `[email protected]:backups.borg` +2. Backup `/home` and `/etc` to `[email protected]:repo` +3. Backup `/home` and `/etc` to `/var/lib/backups/local.borg` + +This gives you redundancy of your data across repositories and even +potentially across providers. + +See [Borg repository URLs +documentation](https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls) +for more information on how to specify local and remote repository paths. + + +## Related documentation + + * [Set up backups with borgmatic](https://torsion.org/borgmatic/docs/how-to/set-up-backups/) + * [Make per-application backups](https://torsion.org/borgmatic/docs/how-to/make-per-application-backups/) + * [Backup to a removable drive or an intermittent server](https://torsion.org/borgmatic/docs/how-to/backup-to-a-removable-drive-or-an-intermittent-server/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/docs/how-to/make-per-application-backups.md new/borgmatic-1.5.9/docs/how-to/make-per-application-backups.md --- old/borgmatic-1.5.8/docs/how-to/make-per-application-backups.md 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/docs/how-to/make-per-application-backups.md 2020-07-23 06:53:55.000000000 +0200 @@ -153,3 +153,4 @@ ## Related documentation * [Set up backups with borgmatic](https://torsion.org/borgmatic/docs/how-to/set-up-backups/) + * [Make backups redundant](https://torsion.org/borgmatic/docs/how-to/make-backups-redundant/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/docs/how-to/set-up-backups.md new/borgmatic-1.5.9/docs/how-to/set-up-backups.md --- old/borgmatic-1.5.8/docs/how-to/set-up-backups.md 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/docs/how-to/set-up-backups.md 2020-07-23 06:53:55.000000000 +0200 @@ -150,6 +150,13 @@ for more info. +### Redundancy + +If you'd like to configure your backups to go to multiple different +repositories, see the documentation on how to [make backups +redundant](https://torsion.org/borgmatic/docs/how-to/make-backups-redundant/). + + ### Validation If you'd like to validate that your borgmatic configuration is valid, the @@ -311,6 +318,7 @@ ## Related documentation * [Make per-application backups](https://torsion.org/borgmatic/docs/how-to/make-per-application-backups/) + * [Make backups redundant](https://torsion.org/borgmatic/docs/how-to/make-backups-redundant/) * [Deal with very large backups](https://torsion.org/borgmatic/docs/how-to/deal-with-very-large-backups/) * [Inspect your backups](https://torsion.org/borgmatic/docs/how-to/inspect-your-backups/) * [Monitor your backups](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/setup.py new/borgmatic-1.5.9/setup.py --- old/borgmatic-1.5.8/setup.py 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/setup.py 2020-07-23 06:53:55.000000000 +0200 @@ -1,6 +1,6 @@ from setuptools import find_packages, setup -VERSION = '1.5.8' +VERSION = '1.5.9' setup( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/tests/integration/test_execute.py new/borgmatic-1.5.9/tests/integration/test_execute.py --- old/borgmatic-1.5.8/tests/integration/test_execute.py 2020-07-01 06:47:34.000000000 +0200 +++ new/borgmatic-1.5.9/tests/integration/test_execute.py 2020-07-23 06:53:55.000000000 +0200 @@ -143,3 +143,16 @@ module.log_outputs( (process,), exclude_stdouts=(), output_log_level=logging.INFO, borg_local_path='borg' ) + + +def test_log_outputs_with_unfinished_process_re_polls(): + flexmock(module.logger).should_receive('log').never() + flexmock(module).should_receive('exit_code_indicates_error').and_return(False) + + process = subprocess.Popen(['true'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + flexmock(process).should_receive('poll').and_return(None).and_return(0).twice() + flexmock(module).should_receive('output_buffer_for_process').and_return(process.stdout) + + module.log_outputs( + (process,), exclude_stdouts=(), output_log_level=logging.INFO, borg_local_path='borg' + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.8/tests/unit/borg/test_export_tar.py new/borgmatic-1.5.9/tests/unit/borg/test_export_tar.py --- old/borgmatic-1.5.8/tests/unit/borg/test_export_tar.py 1970-01-01 01:00:00.000000000 +0100 +++ new/borgmatic-1.5.9/tests/unit/borg/test_export_tar.py 2020-07-23 06:53:55.000000000 +0200 @@ -0,0 +1,226 @@ +import logging + +from flexmock import flexmock + +from borgmatic.borg import export_tar as module + +from ..test_verbosity import insert_logging_mock + + +def insert_execute_command_mock( + command, output_log_level=logging.INFO, borg_local_path='borg', capture=True +): + flexmock(module).should_receive('execute_command').with_args( + command, + output_file=None if capture else module.DO_NOT_CAPTURE, + output_log_level=output_log_level, + borg_local_path=borg_local_path, + ).once() + + +def test_export_tar_archive_calls_borg_with_path_parameters(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', 'repo::archive', 'test.tar', 'path1', 'path2') + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=['path1', 'path2'], + destination_path='test.tar', + storage_config={}, + ) + + +def test_export_tar_archive_calls_borg_with_local_path_parameters(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg1', 'export-tar', 'repo::archive', 'test.tar'), borg_local_path='borg1' + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + local_path='borg1', + ) + + +def test_export_tar_archive_calls_borg_with_remote_path_parameters(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', '--remote-path', 'borg1', 'repo::archive', 'test.tar') + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + remote_path='borg1', + ) + + +def test_export_tar_archive_calls_borg_with_umask_parameters(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', '--umask', '0770', 'repo::archive', 'test.tar') + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={'umask': '0770'}, + ) + + +def test_export_tar_archive_calls_borg_with_lock_wait_parameters(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', '--lock-wait', '5', 'repo::archive', 'test.tar') + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={'lock_wait': '5'}, + ) + + +def test_export_tar_archive_with_log_info_calls_borg_with_info_parameter(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock(('borg', 'export-tar', '--info', 'repo::archive', 'test.tar')) + insert_logging_mock(logging.INFO) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + ) + + +def test_export_tar_archive_with_log_debug_calls_borg_with_debug_parameters(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', '--debug', '--show-rc', 'repo::archive', 'test.tar') + ) + insert_logging_mock(logging.DEBUG) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + ) + + +def test_export_tar_archive_calls_borg_with_dry_run_parameter(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + flexmock(module).should_receive('execute_command').never() + + module.export_tar_archive( + dry_run=True, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + ) + + +def test_export_tar_archive_calls_borg_with_tar_filter_parameters(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', '--tar-filter', 'bzip2', 'repo::archive', 'test.tar') + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + tar_filter='bzip2', + ) + + +def test_export_tar_archive_calls_borg_with_list_parameter(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', '--list', 'repo::archive', 'test.tar'), + output_log_level=logging.WARNING, + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + files=True, + ) + + +def test_export_tar_archive_calls_borg_with_strip_components_parameter(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock( + ('borg', 'export-tar', '--strip-components', '5', 'repo::archive', 'test.tar') + ) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + strip_components=5, + ) + + +def test_export_tar_archive_skips_abspath_for_remote_repository_parameter(): + flexmock(module.os.path).should_receive('abspath').never() + insert_execute_command_mock(('borg', 'export-tar', 'server:repo::archive', 'test.tar')) + + module.export_tar_archive( + dry_run=False, + repository='server:repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + ) + + +def test_export_tar_archive_calls_borg_with_stdout_destination_path(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock(('borg', 'export-tar', 'repo::archive', '-'), capture=False) + + module.export_tar_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + destination_path='-', + storage_config={}, + )
