Fix the "source_directories_must_exist" option to support source directories relative to a "working_directory" (#1300).

This commit is contained in:
Dan Helfman
2026-04-25 13:49:55 -07:00
parent 468af1de0b
commit 5c7d03910b
4 changed files with 30 additions and 9 deletions
+2
View File
@@ -1,4 +1,6 @@
2.1.6.dev0
* #1300: Fix the "source_directories_must_exist" option to support source directories relative to a
"working_directory".
* Add the NEWS changelog file to release tarball (#1298).
* Enable reply by email on projects.torsion.org, so replies to notification emails get posted as
comments on tickets.
+3 -1
View File
@@ -180,7 +180,9 @@ def make_base_create_command( # noqa: PLR0912
open pattern file handle).
'''
if config.get('source_directories_must_exist', True):
borgmatic.borg.pattern.check_all_root_patterns_exist(patterns)
borgmatic.borg.pattern.check_all_root_patterns_exist(
patterns, borgmatic.config.paths.get_working_directory(config)
)
patterns_file = borgmatic.borg.pattern.write_patterns_file(
patterns,
+4 -4
View File
@@ -88,16 +88,16 @@ def write_patterns_file(patterns, borgmatic_runtime_directory, patterns_file=Non
return patterns_file
def check_all_root_patterns_exist(patterns):
def check_all_root_patterns_exist(patterns, working_directory):
'''
Given a sequence of Pattern instances, check that all root pattern paths exist. If any don't,
raise an exception.
Given a sequence of Pattern instances and the current working directory, check that all root
pattern paths exist. If any don't, raise an exception.
'''
missing_paths = [
pattern.path
for pattern in patterns
if pattern.type == Pattern_type.ROOT
if not os.path.exists(pattern.path)
if not os.path.exists(os.path.join(working_directory or '', pattern.path))
]
if missing_paths:
+21 -4
View File
@@ -34,19 +34,36 @@ def test_write_patterns_file_appends_to_existing():
def test_check_all_root_patterns_exist_with_existent_pattern_path_does_not_raise():
flexmock(module.os.path).should_receive('exists').and_return(True)
flexmock(module.os.path).should_receive('exists').with_args('foo').and_return(True)
module.check_all_root_patterns_exist([Pattern('foo')])
module.check_all_root_patterns_exist([Pattern('foo')], working_directory=None)
def test_check_all_root_patterns_exist_with_existent_relative_pattern_path_and_working_directory_does_not_raise():
flexmock(module.os.path).should_receive('exists').with_args('foo').never()
flexmock(module.os.path).should_receive('exists').with_args('/working/foo').and_return(True)
module.check_all_root_patterns_exist([Pattern('foo')], working_directory='/working')
def test_check_all_root_patterns_exist_with_non_root_pattern_skips_existence_check():
flexmock(module.os.path).should_receive('exists').never()
module.check_all_root_patterns_exist([Pattern('foo', Pattern_type.INCLUDE)])
module.check_all_root_patterns_exist(
[Pattern('foo', Pattern_type.INCLUDE)], working_directory=None
)
def test_check_all_root_patterns_exist_with_non_existent_pattern_path_raises():
flexmock(module.os.path).should_receive('exists').and_return(False)
with pytest.raises(ValueError):
module.check_all_root_patterns_exist([Pattern('foo')])
module.check_all_root_patterns_exist([Pattern('foo')], working_directory=None)
def test_check_all_root_patterns_exist_with_non_existent_relative_pattern_path_and_working_directory_raises():
flexmock(module.os.path).should_receive('exists').with_args('foo').never()
flexmock(module.os.path).should_receive('exists').with_args('/working/foo').and_return(False)
with pytest.raises(ValueError):
module.check_all_root_patterns_exist([Pattern('foo')], working_directory='/working')