Fix a borgmatic runtime directory error when running the "spot" check with a database hook enabled (#965).
All checks were successful
build / test (push) Successful in 5m56s
build / docs (push) Successful in 1m55s

This commit is contained in:
Dan Helfman 2025-01-12 09:36:24 -08:00
parent 8573660ff0
commit 5560f30aa6
3 changed files with 40 additions and 12 deletions

2
NEWS
View File

@ -4,6 +4,8 @@
* #960: Fix for archives storing relative source directory paths such that they contain the working
directory.
* #960: Fix the "spot" check to support relative source directory paths.
* #965: Fix a borgmatic runtime directory error when running the "spot" check with a database hook
enabled.
* Fix the "spot" check to no longer consider pipe files within an archive for file comparisons.
* Fix auto-excluding of special files (when databases are configured) to support relative source
directory paths.

View File

@ -161,6 +161,7 @@ def any_parent_directories(path, candidate_parents):
def collect_special_file_paths(
dry_run,
create_command,
config,
local_path,
@ -169,11 +170,11 @@ def collect_special_file_paths(
borgmatic_runtime_directory,
):
'''
Given a Borg create command as a tuple, a configuration dict, a local Borg path, a working
directory, a dict of environment variables to pass to Borg, and the borgmatic runtime directory,
collect the paths for any special files (character devices, block devices, and named pipes /
FIFOs) that Borg would encounter during a create. These are all paths that could cause Borg to
hang if its --read-special flag is used.
Given a dry-run flag, a Borg create command as a tuple, a configuration dict, a local Borg path,
a working directory, a dict of environment variables to pass to Borg, and the borgmatic runtime
directory, collect the paths for any special files (character devices, block devices, and named
pipes / FIFOs) that Borg would encounter during a create. These are all paths that could cause
Borg to hang if its --read-special flag is used.
Skip looking for special files in the given borgmatic runtime directory, as borgmatic creates
its own special files there for database dumps. And if the borgmatic runtime directory is
@ -204,9 +205,9 @@ def collect_special_file_paths(
path for path in paths if any_parent_directories(path, (borgmatic_runtime_directory,))
}
if not skip_paths:
if not skip_paths and not dry_run:
raise ValueError(
f'The runtime directory {os.path.normpath(borgmatic_runtime_directory)} overlaps with the configured excludes or patterns. Please remove it from excludes/patterns or change the runtime directory.'
f'The runtime directory {os.path.normpath(borgmatic_runtime_directory)} overlaps with the configured excludes or patterns with excludes. Please ensure the runtime directory is not excluded.'
)
return tuple(
@ -350,6 +351,7 @@ def make_base_create_command(
logger.debug(f'{repository_path}: Collecting special file paths')
special_file_paths = collect_special_file_paths(
dry_run,
create_flags + create_positional_arguments,
config,
local_path,

View File

@ -290,7 +290,8 @@ def test_collect_special_file_paths_parses_special_files_from_borg_dry_run_file_
flexmock(module).should_receive('any_parent_directories').never()
assert module.collect_special_file_paths(
('borg', 'create'),
dry_run=False,
create_command=('borg', 'create'),
config={},
local_path=None,
working_directory=None,
@ -316,7 +317,8 @@ def test_collect_special_file_paths_skips_borgmatic_runtime_directory():
).and_return(False)
assert module.collect_special_file_paths(
('borg', 'create'),
dry_run=False,
create_command=('borg', 'create'),
config={},
local_path=None,
working_directory=None,
@ -335,7 +337,8 @@ def test_collect_special_file_paths_with_borgmatic_runtime_directory_missing_fro
with pytest.raises(ValueError):
module.collect_special_file_paths(
('borg', 'create'),
dry_run=False,
create_command=('borg', 'create'),
config={},
local_path=None,
working_directory=None,
@ -344,6 +347,25 @@ def test_collect_special_file_paths_with_borgmatic_runtime_directory_missing_fro
)
def test_collect_special_file_paths_with_dry_run_and_borgmatic_runtime_directory_missing_from_paths_output_does_not_raise():
flexmock(module).should_receive('execute_command_and_capture_output').and_return(
'+ /foo\n- /bar\n- /baz'
)
flexmock(module).should_receive('special_file').and_return(True)
flexmock(module.os.path).should_receive('exists').and_return(True)
flexmock(module).should_receive('any_parent_directories').and_return(False)
assert module.collect_special_file_paths(
dry_run=True,
create_command=('borg', 'create'),
config={},
local_path=None,
working_directory=None,
borg_environment=None,
borgmatic_runtime_directory='/run/borgmatic',
) == ('/foo', '/bar', '/baz')
def test_collect_special_file_paths_excludes_non_special_files():
flexmock(module).should_receive('execute_command_and_capture_output').and_return(
'+ /foo\n+ /bar\n+ /baz'
@ -355,7 +377,8 @@ def test_collect_special_file_paths_excludes_non_special_files():
flexmock(module).should_receive('any_parent_directories').never()
assert module.collect_special_file_paths(
('borg', 'create'),
dry_run=False,
create_command=('borg', 'create'),
config={},
local_path=None,
working_directory=None,
@ -378,7 +401,8 @@ def test_collect_special_file_paths_omits_exclude_no_dump_flag_from_command():
flexmock(module).should_receive('any_parent_directories').never()
module.collect_special_file_paths(
('borg', 'create', '--exclude-nodump'),
dry_run=False,
create_command=('borg', 'create', '--exclude-nodump'),
config={},
local_path='borg',
working_directory=None,