forked from borgmatic-collective/borgmatic
Fix an error about the runtime directory getting excluded by tweaking its logic and lowering the error to a warning (#1211).
This commit is contained in:
parent
126b08b1ac
commit
ec8168af46
3 changed files with 97 additions and 44 deletions
2
NEWS
2
NEWS
|
|
@ -3,6 +3,8 @@
|
|||
"--database" flag specifies.
|
||||
* #1210: Fix an error when running the "spot" check or "extract" action with the "progress" option
|
||||
or "--progress" flag.
|
||||
* #1211: Fix an error about the runtime directory getting excluded by tweaking its logic and
|
||||
lowering the error to a warning.
|
||||
* #1212: Fix an error when restoring multiple directory-format database dumps at once.
|
||||
|
||||
2.0.13
|
||||
|
|
|
|||
|
|
@ -96,22 +96,36 @@ def validate_planned_backup_paths(
|
|||
if path_line and path_line.startswith(('- ', '+ '))
|
||||
)
|
||||
|
||||
include_pattern_paths = {
|
||||
pattern.path
|
||||
for pattern in patterns
|
||||
if pattern.type == borgmatic.borg.pattern.Pattern_type.INCLUDE
|
||||
}
|
||||
runtime_directory_root_patterns = tuple(
|
||||
pattern
|
||||
for pattern in patterns
|
||||
if any_parent_directories(pattern.path, (borgmatic_runtime_directory,))
|
||||
if pattern.type == borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
# Skip root patterns that have corresponding include patterns, because those will "punch
|
||||
# through" any subsequent excludes.
|
||||
if pattern.path not in include_pattern_paths
|
||||
)
|
||||
|
||||
if not dry_run and os.path.exists(borgmatic_runtime_directory):
|
||||
# If there are any root patterns in the runtime directory that are missing from the paths
|
||||
# Borg is planning to backup, then they must've gotten excluded, e.g. by user-configured
|
||||
# excludes. Error accordingly.
|
||||
for pattern in runtime_directory_root_patterns:
|
||||
if not any(any_parent_directories(path, (pattern.path,)) for path in paths):
|
||||
raise ValueError(
|
||||
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.',
|
||||
)
|
||||
# If all root patterns in the runtime directory are missing from the paths Borg is planning to
|
||||
# backup, then they must've gotten excluded, e.g. by user-configured excludes. Warn accordingly.
|
||||
if (
|
||||
not dry_run
|
||||
and os.path.exists(borgmatic_runtime_directory)
|
||||
and runtime_directory_root_patterns
|
||||
and not any(
|
||||
any_parent_directories(path, (pattern.path,))
|
||||
for pattern in runtime_directory_root_patterns
|
||||
for path in paths
|
||||
)
|
||||
):
|
||||
logger.warning(
|
||||
f'The runtime directory {os.path.normpath(borgmatic_runtime_directory)} overlaps with the configured excludes (or the snapshotted source directories are empty). Please ensure the runtime directory is not excluded.'
|
||||
)
|
||||
|
||||
# Return the subset of output paths *not* contained within the borgmatic runtime directory. The
|
||||
# intent is that any downstream checks using these paths should skip runtime paths that
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ def test_validate_planned_backup_paths_skips_borgmatic_runtime_directory():
|
|||
) == ('/foo', '/baz')
|
||||
|
||||
|
||||
def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_missing_from_paths_output_errors():
|
||||
def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_missing_from_paths_output_warns():
|
||||
flexmock(module.flags).should_receive('omit_flag').replace_with(
|
||||
lambda arguments, flag: arguments,
|
||||
)
|
||||
|
|
@ -136,26 +136,26 @@ def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_missing_
|
|||
flexmock(module).should_receive('any_parent_directories').replace_with(
|
||||
lambda path, candidates: any(path.startswith(parent) for parent in candidates)
|
||||
)
|
||||
flexmock(module.logger).should_receive('warning').once()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.validate_planned_backup_paths(
|
||||
dry_run=False,
|
||||
create_command=('borg', 'create'),
|
||||
config={},
|
||||
patterns=(
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/bar', module.borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
),
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
assert module.validate_planned_backup_paths(
|
||||
dry_run=False,
|
||||
create_command=('borg', 'create'),
|
||||
config={},
|
||||
patterns=(
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/bar', module.borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
),
|
||||
local_path=None,
|
||||
working_directory=None,
|
||||
borgmatic_runtime_directory='/run/borgmatic',
|
||||
)
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
),
|
||||
local_path=None,
|
||||
working_directory=None,
|
||||
borgmatic_runtime_directory='/run/borgmatic',
|
||||
) == ('/foo', '/bar', '/baz')
|
||||
|
||||
|
||||
def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_partially_excluded_from_paths_output_errors():
|
||||
def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_partially_excluded_from_paths_output_does_not_warn():
|
||||
flexmock(module.flags).should_receive('omit_flag').replace_with(
|
||||
lambda arguments, flag: arguments,
|
||||
)
|
||||
|
|
@ -172,26 +172,63 @@ def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_partiall
|
|||
flexmock(module).should_receive('any_parent_directories').replace_with(
|
||||
lambda path, candidates: any(path.startswith(parent) for parent in candidates)
|
||||
)
|
||||
flexmock(module.logger).should_receive('warning').never()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.validate_planned_backup_paths(
|
||||
dry_run=False,
|
||||
create_command=('borg', 'create'),
|
||||
config={},
|
||||
patterns=(
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/bar', module.borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
),
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/quux', module.borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
),
|
||||
assert module.validate_planned_backup_paths(
|
||||
dry_run=False,
|
||||
create_command=('borg', 'create'),
|
||||
config={},
|
||||
patterns=(
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/bar', module.borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
),
|
||||
local_path=None,
|
||||
working_directory=None,
|
||||
borgmatic_runtime_directory='/run/borgmatic',
|
||||
)
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/quux', module.borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
),
|
||||
),
|
||||
local_path=None,
|
||||
working_directory=None,
|
||||
borgmatic_runtime_directory='/run/borgmatic',
|
||||
) == ('/foo', '/baz')
|
||||
|
||||
|
||||
def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_with_corresponding_include_and_missing_from_paths_output_does_not_warn():
|
||||
flexmock(module.flags).should_receive('omit_flag').replace_with(
|
||||
lambda arguments, flag: arguments,
|
||||
)
|
||||
flexmock(module.flags).should_receive('omit_flag_and_value').replace_with(
|
||||
lambda arguments, flag: arguments,
|
||||
)
|
||||
flexmock(module.environment).should_receive('make_environment').and_return(None)
|
||||
flexmock(module).should_receive('execute_command_and_capture_output').and_return(
|
||||
'+ /foo\n- /bar\n- /baz',
|
||||
)
|
||||
flexmock(module.os.path).should_receive('exists').and_return(True)
|
||||
flexmock(module).should_receive('any_parent_directories').replace_with(
|
||||
lambda path, candidates: any(path.startswith(parent) for parent in candidates)
|
||||
)
|
||||
flexmock(module.logger).should_receive('warning').never()
|
||||
|
||||
assert module.validate_planned_backup_paths(
|
||||
dry_run=False,
|
||||
create_command=('borg', 'create'),
|
||||
config={},
|
||||
patterns=(
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/bar', module.borgmatic.borg.pattern.Pattern_type.ROOT
|
||||
),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/run/borgmatic/bar', module.borgmatic.borg.pattern.Pattern_type.INCLUDE
|
||||
),
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
),
|
||||
local_path=None,
|
||||
working_directory=None,
|
||||
borgmatic_runtime_directory='/run/borgmatic',
|
||||
) == ('/foo', '/bar', '/baz')
|
||||
|
||||
|
||||
def test_validate_planned_backup_paths_with_borgmatic_runtime_directory_missing_from_patterns_does_not_raise():
|
||||
|
|
|
|||
Loading…
Reference in a new issue