Display a nicer error message when running the "recreate" action on a leftover temporary archive from a prior recreate run (#1053).

This commit is contained in:
Dan Helfman
2025-04-08 10:13:04 -07:00
parent 2db023f785
commit a892a308bd
4 changed files with 86 additions and 15 deletions
+2
View File
@@ -1,6 +1,8 @@
2.0.2.dev0
* #1035: Document potential performance issues and workarounds with the ZFS, Btrfs, and LVM hooks:
https://torsion.org/borgmatic/docs/how-to/snapshot-your-filesystems/
* #1053: Display a nicer error message when running the "recreate" action on a leftover temporary
archive from a prior recreate run.
* #1059: Fix a regression in which soft failure exit codes in command hooks were not respected.
* #1060: Fix action command hooks getting run too many times when multiple borgmatic actions are
executed (implicitly or explicitly).
+22 -9
View File
@@ -1,6 +1,7 @@
import logging
import borgmatic.borg.recreate
import borgmatic.borg.repo_list
import borgmatic.config.validate
from borgmatic.actions.pattern import collect_patterns, process_patterns
@@ -32,17 +33,29 @@ def run_recreate(
collect_patterns(config), borgmatic.config.paths.get_working_directory(config)
)
archive = borgmatic.borg.repo_list.resolve_archive_name(
repository['path'],
recreate_arguments.archive,
config,
local_borg_version,
global_arguments,
local_path,
remote_path,
)
if archive and archive.endswith('.recreate'):
if recreate_arguments.archive == 'latest':
raise ValueError(
f'The latest archive "{archive}" is leftover from a prior recreate. Delete it first or select a different archive.'
)
else:
raise ValueError(
f'The archive "{recreate_arguments.archive}" is leftover from a prior recreate. Select a different archive.'
)
borgmatic.borg.recreate.recreate_archive(
repository['path'],
borgmatic.borg.repo_list.resolve_archive_name(
repository['path'],
recreate_arguments.archive,
config,
local_borg_version,
global_arguments,
local_path,
remote_path,
),
archive,
config,
local_borg_version,
recreate_arguments,
+1
View File
@@ -32,6 +32,7 @@ def recreate_archive(
exclude_flags = flags.make_exclude_flags(config)
compression = config.get('compression', None)
chunker_params = config.get('chunker_params', None)
# Available recompress MODES: "if-different", "always", "never" (default)
recompress = config.get('recompress', None)
+61 -6
View File
@@ -1,3 +1,4 @@
import pytest
from flexmock import flexmock
from borgmatic.actions import recreate as module
@@ -6,15 +7,19 @@ from borgmatic.actions import recreate as module
def test_run_recreate_does_not_raise():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
flexmock()
)
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
None
)
flexmock(module.borgmatic.borg.recreate).should_receive('recreate_archive')
recreate_arguments = flexmock(repository=flexmock(), archive=None)
module.run_recreate(
repository={'path': 'repo'},
config={},
local_borg_version=None,
recreate_arguments=recreate_arguments,
recreate_arguments=flexmock(repository=flexmock(), archive=None),
global_arguments=flexmock(),
local_path=None,
remote_path=None,
@@ -24,16 +29,66 @@ def test_run_recreate_does_not_raise():
def test_run_recreate_with_archive_does_not_raise():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
flexmock()
)
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
'test-archive'
)
flexmock(module.borgmatic.borg.recreate).should_receive('recreate_archive')
recreate_arguments = flexmock(repository=flexmock(), archive='test-archive')
module.run_recreate(
repository={'path': 'repo'},
config={},
local_borg_version=None,
recreate_arguments=recreate_arguments,
recreate_arguments=flexmock(repository=flexmock(), archive='test-archive'),
global_arguments=flexmock(),
local_path=None,
remote_path=None,
)
def test_run_recreate_with_leftover_recreate_archive_raises():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
flexmock()
)
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
'test-archive.recreate'
)
flexmock(module.borgmatic.borg.recreate).should_receive('recreate_archive')
with pytest.raises(ValueError):
module.run_recreate(
repository={'path': 'repo'},
config={},
local_borg_version=None,
recreate_arguments=flexmock(repository=flexmock(), archive='test-archive.recreate'),
global_arguments=flexmock(),
local_path=None,
remote_path=None,
)
def test_run_recreate_with_latest_archive_resolving_to_leftover_recreate_archive_raises():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').and_return(True)
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
flexmock()
)
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
'test-archive.recreate'
)
flexmock(module.borgmatic.borg.recreate).should_receive('recreate_archive')
with pytest.raises(ValueError):
module.run_recreate(
repository={'path': 'repo'},
config={},
local_borg_version=None,
recreate_arguments=flexmock(repository=flexmock(), archive='latest'),
global_arguments=flexmock(),
local_path=None,
remote_path=None,
)