From 341bd4118d7707a5bb80571a285fefbe741c0eca Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Tue, 30 May 2023 16:53:55 -0700 Subject: [PATCH] Fix "--archive latest" on "list" and "info" actions only working on the first of multiple configured repositories (#706). --- NEWS | 2 ++ borgmatic/actions/arguments.py | 9 +++++++++ borgmatic/actions/info.py | 5 +++-- borgmatic/actions/list.py | 6 ++++-- tests/unit/actions/test_arguments.py | 10 ++++++++++ tests/unit/actions/test_info.py | 3 +++ tests/unit/actions/test_list.py | 3 +++ 7 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 borgmatic/actions/arguments.py create mode 100644 tests/unit/actions/test_arguments.py diff --git a/NEWS b/NEWS index f4e08d84..b4a92eab 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ or monitoring), so not even errors are shown. * #688: Tweak archive check probing logic to use the newest timestamp found when multiple exist. * #659: Add Borg 2 date-based matching flags to various actions for archive selection. + * #706: Fix "--archive latest" on "list" and "info" actions only working on the first of multiple + configured repositories. 1.7.13 * #375: Restore particular PostgreSQL schemas from a database dump via "borgmatic restore --schema" diff --git a/borgmatic/actions/arguments.py b/borgmatic/actions/arguments.py new file mode 100644 index 00000000..7fd77fc8 --- /dev/null +++ b/borgmatic/actions/arguments.py @@ -0,0 +1,9 @@ +import argparse + + +def update_arguments(arguments, **updates): + ''' + Given an argparse.Namespace instance of command-line arguments and one or more keyword argument + updates to perform, return a copy of the arguments with those updates applied. + ''' + return argparse.Namespace(**dict(vars(arguments), **updates)) diff --git a/borgmatic/actions/info.py b/borgmatic/actions/info.py index 91699623..0116fd70 100644 --- a/borgmatic/actions/info.py +++ b/borgmatic/actions/info.py @@ -1,6 +1,7 @@ import json import logging +import borgmatic.actions.arguments import borgmatic.borg.info import borgmatic.borg.rlist import borgmatic.config.validate @@ -29,7 +30,7 @@ def run_info( logger.answer( f'{repository.get("label", repository["path"])}: Displaying archive summary information' ) - info_arguments.archive = borgmatic.borg.rlist.resolve_archive_name( + archive_name = borgmatic.borg.rlist.resolve_archive_name( repository['path'], info_arguments.archive, storage, @@ -42,7 +43,7 @@ def run_info( repository['path'], storage, local_borg_version, - info_arguments, + borgmatic.actions.arguments.update_arguments(info_arguments, archive=archive_name), global_arguments, local_path, remote_path, diff --git a/borgmatic/actions/list.py b/borgmatic/actions/list.py index 720fab1c..667062d8 100644 --- a/borgmatic/actions/list.py +++ b/borgmatic/actions/list.py @@ -1,6 +1,7 @@ import json import logging +import borgmatic.actions.arguments import borgmatic.borg.list import borgmatic.config.validate @@ -29,7 +30,8 @@ def run_list( logger.answer(f'{repository.get("label", repository["path"])}: Searching archives') elif not list_arguments.archive: logger.answer(f'{repository.get("label", repository["path"])}: Listing archives') - list_arguments.archive = borgmatic.borg.rlist.resolve_archive_name( + + archive_name = borgmatic.borg.rlist.resolve_archive_name( repository['path'], list_arguments.archive, storage, @@ -42,7 +44,7 @@ def run_list( repository['path'], storage, local_borg_version, - list_arguments, + borgmatic.actions.arguments.update_arguments(list_arguments, archive=archive_name), global_arguments, local_path, remote_path, diff --git a/tests/unit/actions/test_arguments.py b/tests/unit/actions/test_arguments.py new file mode 100644 index 00000000..988cbede --- /dev/null +++ b/tests/unit/actions/test_arguments.py @@ -0,0 +1,10 @@ +from borgmatic.actions import arguments as module + + +def test_update_arguments_copies_and_updates_without_modifying_original(): + original = module.argparse.Namespace(foo=1, bar=2, baz=3) + + result = module.update_arguments(original, bar=7, baz=8) + + assert original == module.argparse.Namespace(foo=1, bar=2, baz=3) + assert result == module.argparse.Namespace(foo=1, bar=7, baz=8) diff --git a/tests/unit/actions/test_info.py b/tests/unit/actions/test_info.py index 97161968..748d866f 100644 --- a/tests/unit/actions/test_info.py +++ b/tests/unit/actions/test_info.py @@ -9,6 +9,9 @@ def test_run_info_does_not_raise(): flexmock(module.borgmatic.borg.rlist).should_receive('resolve_archive_name').and_return( flexmock() ) + flexmock(module.borgmatic.actions.arguments).should_receive('update_arguments').and_return( + flexmock() + ) flexmock(module.borgmatic.borg.info).should_receive('display_archives_info') info_arguments = flexmock(repository=flexmock(), archive=flexmock(), json=flexmock()) diff --git a/tests/unit/actions/test_list.py b/tests/unit/actions/test_list.py index 5ee72251..07a1a58c 100644 --- a/tests/unit/actions/test_list.py +++ b/tests/unit/actions/test_list.py @@ -9,6 +9,9 @@ def test_run_list_does_not_raise(): flexmock(module.borgmatic.borg.rlist).should_receive('resolve_archive_name').and_return( flexmock() ) + flexmock(module.borgmatic.actions.arguments).should_receive('update_arguments').and_return( + flexmock() + ) flexmock(module.borgmatic.borg.list).should_receive('list_archive') list_arguments = flexmock(repository=flexmock(), archive=flexmock(), json=flexmock())