From 80ec3e7d9744f8c99908e0e88ccc600bd700efd7 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Thu, 2 Jun 2022 20:35:39 -0700 Subject: [PATCH] Deprecate "borgmatic list --successful" flag, as listing only non-checkpoint (successful) archives is now the default in newer versions of Borg. --- NEWS | 4 ++ borgmatic/borg/list.py | 15 +------ borgmatic/commands/arguments.py | 5 +-- docs/how-to/extract-a-backup.md | 2 +- docs/how-to/monitor-your-backups.md | 29 ++----------- setup.py | 2 +- tests/integration/commands/test_arguments.py | 9 ---- tests/unit/borg/test_list.py | 44 ++++++-------------- 8 files changed, 25 insertions(+), 85 deletions(-) diff --git a/NEWS b/NEWS index 1a297d726..4a11fa90c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +1.6.3.dev0 + * Deprecate "borgmatic list --successful" flag, as listing only non-checkpoint (successful) + archives is now the default in newer versions of Borg. + 1.6.2 * #523: Reduce the default consistency check frequency and support configuring the frequency independently for each check. Also add "borgmatic check --force" flag to ignore configured diff --git a/borgmatic/borg/list.py b/borgmatic/borg/list.py index adc71b79a..f6038a8ef 100644 --- a/borgmatic/borg/list.py +++ b/borgmatic/borg/list.py @@ -6,17 +6,11 @@ from borgmatic.execute import execute_command logger = logging.getLogger(__name__) -# A hack to convince Borg to exclude archives ending in ".checkpoint". This assumes that a -# non-checkpoint archive name ends in a digit (e.g. from a timestamp). -BORG_EXCLUDE_CHECKPOINTS_GLOB = '*[0123456789]' - - 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 successful (non-checkpoint) - archive, and return its name. + "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. ''' @@ -31,7 +25,6 @@ def resolve_archive_name(repository, archive, storage_config, local_path='borg', + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + make_flags('remote-path', remote_path) + make_flags('lock-wait', lock_wait) - + make_flags('glob-archives', BORG_EXCLUDE_CHECKPOINTS_GLOB) + make_flags('last', 1) + ('--short', repository) ) @@ -54,8 +47,6 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg', if an archive name is given, listing the files in that archive. ''' lock_wait = storage_config.get('lock_wait', None) - if list_arguments.successful: - list_arguments.glob_archives = BORG_EXCLUDE_CHECKPOINTS_GLOB full_command = ( (local_path, 'list') @@ -71,9 +62,7 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg', ) + make_flags('remote-path', remote_path) + make_flags('lock-wait', lock_wait) - + make_flags_from_arguments( - list_arguments, excludes=('repository', 'archive', 'paths', 'successful') - ) + + make_flags_from_arguments(list_arguments, excludes=('repository', 'archive', 'paths')) + ( '::'.join((repository, list_arguments.archive)) if list_arguments.archive diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index 95f8a10f1..00fad70bb 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -573,7 +573,7 @@ def make_parsers(): '--successful', default=False, action='store_true', - help='Only list archive names of successful (non-checkpoint) backups', + help='Deprecated in favor of listing successful (non-checkpoint) backups by default in newer versions of Borg', ) list_group.add_argument( '--sort-by', metavar='KEYS', help='Comma-separated list of sorting keys' @@ -681,9 +681,6 @@ def parse_arguments(*unparsed_arguments): if 'init' in arguments and arguments['global'].dry_run: raise ValueError('The init action cannot be used with the --dry-run option') - if 'list' in arguments and arguments['list'].glob_archives and arguments['list'].successful: - raise ValueError('The --glob-archives and --successful options cannot be used together') - if ( 'list' in arguments and 'info' in arguments diff --git a/docs/how-to/extract-a-backup.md b/docs/how-to/extract-a-backup.md index 75949d1e3..ea641db16 100644 --- a/docs/how-to/extract-a-backup.md +++ b/docs/how-to/extract-a-backup.md @@ -116,7 +116,7 @@ Omit the `--archive` flag to mount all archives (lazy-loaded): borgmatic mount --mount-point /mnt ``` -Or use the "latest" value for the archive to mount the latest successful archive: +Or use the "latest" value for the archive to mount the latest archive: ```bash borgmatic mount --archive latest --mount-point /mnt diff --git a/docs/how-to/monitor-your-backups.md b/docs/how-to/monitor-your-backups.md index 725e5d168..167c36fa2 100644 --- a/docs/how-to/monitor-your-backups.md +++ b/docs/how-to/monitor-your-backups.md @@ -286,35 +286,12 @@ output only shows up at the console, and not in syslog. * [Borgmacator GNOME AppIndicator](https://github.com/N-Coder/borgmacator/) -### Successful backups - -`borgmatic list` includes support for a `--successful` flag that only lists -successful (non-checkpoint) backups. This flag works via a basic heuristic: It -assumes that non-checkpoint archive names end with a digit (e.g. from a -timestamp), while checkpoint archive names do not. This means that if you're -using custom archive names that do not end in a digit, the `--successful` flag -will not work as expected. - -Combined with a built-in Borg flag like `--last`, you can list the last -successful backup for use in your monitoring scripts. Here's an example -combined with `--json`: - -```bash -borgmatic list --successful --last 1 --json -``` - -Note that this particular combination will only work if you've got a single -backup "series" in your repository. If you're instead backing up, say, from -multiple different hosts into a single repository, then you'll need to get -fancier with your archive listing. See `borg list --help` for more flags. - - ### Latest backups All borgmatic actions that accept an "--archive" flag allow you to specify an -archive name of "latest". This lets you get the latest successful archive -without having to first run "borgmatic list" manually, which can be handy in -automated scripts. Here's an example: +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 +scripts. Here's an example: ```bash borgmatic info --archive latest diff --git a/setup.py b/setup.py index 0e29aec95..1e9a17cc8 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import find_packages, setup -VERSION = '1.6.2' +VERSION = '1.6.3.dev0' setup( diff --git a/tests/integration/commands/test_arguments.py b/tests/integration/commands/test_arguments.py index 0b190938b..e13a31b6b 100644 --- a/tests/integration/commands/test_arguments.py +++ b/tests/integration/commands/test_arguments.py @@ -296,15 +296,6 @@ def test_parse_arguments_disallows_init_and_dry_run(): ) -def test_parse_arguments_disallows_glob_archives_with_successful(): - flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default']) - - with pytest.raises(ValueError): - module.parse_arguments( - '--config', 'myconfig', 'list', '--glob-archives', '*glob*', '--successful' - ) - - def test_parse_arguments_disallows_repository_unless_action_consumes_it(): flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default']) diff --git a/tests/unit/borg/test_list.py b/tests/unit/borg/test_list.py index cf174c7aa..eb763c025 100644 --- a/tests/unit/borg/test_list.py +++ b/tests/unit/borg/test_list.py @@ -8,8 +8,6 @@ from borgmatic.borg import list as module from ..test_verbosity import insert_logging_mock BORG_LIST_LATEST_ARGUMENTS = ( - '--glob-archives', - module.BORG_EXCLUDE_CHECKPOINTS_GLOB, '--last', '1', '--short', @@ -116,7 +114,7 @@ def test_list_archives_calls_borg_with_parameters(): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=False), ) @@ -129,7 +127,7 @@ def test_list_archives_with_log_info_calls_borg_with_info_parameter(): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=False), ) @@ -142,7 +140,7 @@ def test_list_archives_with_log_info_and_json_suppresses_most_borg_output(): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=True, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=True), ) @@ -157,7 +155,7 @@ def test_list_archives_with_log_debug_calls_borg_with_debug_parameter(): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=False), ) @@ -170,7 +168,7 @@ def test_list_archives_with_log_debug_and_json_suppresses_most_borg_output(): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=True, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=True), ) @@ -185,7 +183,7 @@ def test_list_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): module.list_archives( repository='repo', storage_config=storage_config, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=False), ) @@ -198,7 +196,7 @@ def test_list_archives_with_archive_calls_borg_with_archive_parameter(): module.list_archives( repository='repo', storage_config=storage_config, - list_arguments=flexmock(archive='archive', paths=None, json=False, successful=False), + list_arguments=flexmock(archive='archive', paths=None, json=False), ) @@ -213,7 +211,7 @@ def test_list_archives_with_path_calls_borg_with_path_parameter(): module.list_archives( repository='repo', storage_config=storage_config, - list_arguments=flexmock(archive='archive', paths=['var/lib'], json=False, successful=False), + list_arguments=flexmock(archive='archive', paths=['var/lib'], json=False), ) @@ -225,7 +223,7 @@ def test_list_archives_with_local_path_calls_borg_via_local_path(): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=False), local_path='borg1', ) @@ -240,7 +238,7 @@ def test_list_archives_with_remote_path_calls_borg_with_remote_path_parameters() module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=False), remote_path='borg1', ) @@ -255,7 +253,7 @@ def test_list_archives_with_short_calls_borg_with_short_parameter(): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=False, short=True), + list_arguments=flexmock(archive=None, paths=None, json=False, short=True), ) @@ -283,23 +281,7 @@ def test_list_archives_passes_through_arguments_to_borg(argument_name): module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock( - archive=None, paths=None, json=False, successful=False, **{argument_name: 'value'} - ), - ) - - -def test_list_archives_with_successful_calls_borg_to_exclude_checkpoints(): - flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--glob-archives', module.BORG_EXCLUDE_CHECKPOINTS_GLOB, 'repo'), - output_log_level=logging.WARNING, - borg_local_path='borg', - ).and_return('[]') - - module.list_archives( - repository='repo', - storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=False, successful=True), + list_arguments=flexmock(archive=None, paths=None, json=False, **{argument_name: 'value'}), ) @@ -311,7 +293,7 @@ def test_list_archives_with_json_calls_borg_with_json_parameter(): json_output = module.list_archives( repository='repo', storage_config={}, - list_arguments=flexmock(archive=None, paths=None, json=True, successful=False), + list_arguments=flexmock(archive=None, paths=None, json=True), ) assert json_output == '[]'