Fix the "spot" check, "extract" check, and all uses of the archive name "latest" to respect the "match_archives" and "archives_name_format" options (#1268).

This commit is contained in:
Dan Helfman
2026-04-05 09:58:54 -07:00
parent 9bb5791e9f
commit 3bcf592d53
4 changed files with 56 additions and 1 deletions
+3
View File
@@ -7,6 +7,9 @@
* #1264: Improve performance of the "info" and "repo-list" actions by eliminating a second "borg
info" call that supports a "no matching archives" warning. The warning still occurs; it's just
done now without the extra "borg info" call.
* #1268: Fix the "spot" check, "extract" check, and all uses of the archive name "latest" to
respect the "match_archives" and "archives_name_format" options. This means that borgmatic now
uses the "latest" archive that also matches those options instead of the latest archive overall.
* When Borg exits with a warning exit code, show a description of it, so you don't have to lookup
the code.
* Split out borgmatic installation documentation to its own page, so it's easier to find.
+7
View File
@@ -79,6 +79,13 @@ def get_latest_archive(
*flags.make_flags('umask', config.get('umask')),
*('--log-json',),
*flags.make_flags('lock-wait', config.get('lock_wait')),
*(
flags.make_match_archives_flags(
config.get('match_archives'),
config.get('archive_name_format'),
local_borg_version,
)
),
*(
flags.make_flags('consider-checkpoints', consider_checkpoints)
if not feature.available(feature.Feature.REPO_LIST, local_borg_version)
@@ -97,4 +97,3 @@ option for limiting the archives used for the `check` action was a separate
`prefix` in the `consistency` section. Both of these options are deprecated in
favor of the auto-matching behavior (or `match_archives`/`--match-archives`)
in newer versions of borgmatic.
+46
View File
@@ -115,6 +115,7 @@ def test_get_latest_archive_calls_borg_with_flags():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -144,6 +145,7 @@ def test_get_latest_archive_with_log_info_calls_borg_without_info_flag():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -174,6 +176,7 @@ def test_get_latest_archive_with_log_debug_calls_borg_without_debug_flag():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -204,6 +207,7 @@ def test_get_latest_archive_with_local_path_calls_borg_via_local_path():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -234,6 +238,7 @@ def test_get_latest_archive_with_exit_codes_calls_borg_using_them():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -267,6 +272,7 @@ def test_get_latest_archive_with_remote_path_calls_borg_with_remote_path_flags()
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -300,6 +306,7 @@ def test_get_latest_archive_with_umask_calls_borg_with_umask_flags():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -329,6 +336,7 @@ def test_get_latest_archive_without_archives_raises():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
flexmock(module).should_receive('execute_command_and_capture_output').with_args(
@@ -358,6 +366,7 @@ def test_get_latest_archive_with_lock_wait_calls_borg_with_lock_wait_flags():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -380,6 +389,38 @@ def test_get_latest_archive_with_lock_wait_calls_borg_with_lock_wait_flags():
)
def test_get_latest_archive_with_match_archives_calls_borg_with_match_archives_flags():
expected_archive = {'name': 'archive-name', 'id': 'd34db33f'}
flexmock(module.feature).should_receive('available').and_return(False)
flexmock(module.flags).should_receive('make_flags').and_return(())
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(
('--match-archives', 'foo')
)
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
flexmock(module).should_receive('execute_command_and_capture_output').with_args(
('borg', 'list', '--log-json', '--match-archives', 'foo', *BORG_LIST_LATEST_ARGUMENTS),
environment=None,
working_directory=None,
borg_local_path='borg',
borg_exit_codes=None,
).and_yield(json.dumps({'archives': [expected_archive]}))
assert (
module.get_latest_archive(
'repo',
config={'match_archives': 'foo'},
local_borg_version='1.2.3',
global_arguments=flexmock(),
)
== expected_archive
)
def test_get_latest_archive_calls_borg_with_list_extra_borg_options():
expected_archive = {'name': 'archive-name', 'id': 'd34db33f'}
flexmock(module.feature).should_receive('available').and_return(False)
@@ -387,6 +428,7 @@ def test_get_latest_archive_calls_borg_with_list_extra_borg_options():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -424,6 +466,7 @@ def test_get_latest_archive_with_feature_available_calls_borg_with_repo_list_ext
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -464,6 +507,7 @@ def test_get_latest_archive_with_consider_checkpoints_calls_borg_with_consider_c
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -497,6 +541,7 @@ def test_get_latest_archive_with_consider_checkpoints_and_feature_available_call
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
@@ -527,6 +572,7 @@ def test_get_latest_archive_calls_borg_with_working_directory():
flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return(
('--last', '1')
)
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
flexmock(module.environment).should_receive('make_environment')
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(