diff --git a/NEWS b/NEWS index 98d2c8be..4633e45d 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ * #900: Fix for a potential traceback (TypeError) during the handling of another error. * #904: Clarify the configuration reference about the "spot" check options: https://torsion.org/borgmatic/docs/reference/configuration/ + * #905: Fix the "source_directories_must_exist" option to work with relative "source_directories" + paths when a "working_directory" is set. * Fix a regression in which the "color" option had no effect. * Add a recent contributors section to the documentation, because credit where credit's due! See: https://torsion.org/borgmatic/#recent-contributors diff --git a/borgmatic/borg/create.py b/borgmatic/borg/create.py index b39f72e3..0ed56261 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -306,15 +306,25 @@ def collect_special_file_paths( ) -def check_all_source_directories_exist(source_directories): +def check_all_source_directories_exist(source_directories, working_directory=None): ''' - Given a sequence of source directories, check that they all exist. If any do not, raise an - exception. + Given a sequence of source directories and an optional working directory to serve as a prefix + for each (if it's a relative directory), check that the source directories all exist. If any do + not, raise an exception. ''' missing_directories = [ source_directory for source_directory in source_directories - if not all([os.path.exists(directory) for directory in expand_directory(source_directory)]) + if not all( + [ + os.path.exists(directory) + for directory in expand_directory( + os.path.join(working_directory, source_directory) + if working_directory + else source_directory + ) + ] + ) ] if missing_directories: raise ValueError(f"Source directories do not exist: {', '.join(missing_directories)}") @@ -342,8 +352,15 @@ def make_base_create_command( (base Borg create command flags, Borg create command positional arguments, open pattern file handle, open exclude file handle). ''' + try: + working_directory = os.path.expanduser(config.get('working_directory')) + except TypeError: + working_directory = None + if config.get('source_directories_must_exist', False): - check_all_source_directories_exist(config.get('source_directories')) + check_all_source_directories_exist( + config.get('source_directories'), working_directory=working_directory + ) sources = deduplicate_directories( map_directories_to_devices( @@ -445,11 +462,6 @@ def make_base_create_command( logger.warning( f'{repository_path}: Ignoring configured "read_special" value of false, as true is needed for database hooks.' ) - try: - working_directory = os.path.expanduser(config.get('working_directory')) - except TypeError: - working_directory = None - borg_environment = environment.make_environment(config) logger.debug(f'{repository_path}: Collecting special file paths') diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index 9959919b..8e20dc63 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -1891,3 +1891,18 @@ def test_check_all_source_directories_exist_with_non_existent_directory_raises() with pytest.raises(ValueError): module.check_all_source_directories_exist(['foo']) + + +def test_check_all_source_directories_exist_with_working_directory_applies_to_relative_source_directories(): + flexmock(module).should_receive('expand_directory').with_args('/tmp/foo*').and_return( + ('/tmp/foo', '/tmp/food') + ) + flexmock(module).should_receive('expand_directory').with_args('/root/bar').and_return( + ('/root/bar',) + ) + flexmock(module.os.path).should_receive('exists').and_return(False) + flexmock(module.os.path).should_receive('exists').with_args('/tmp/foo').and_return(True) + flexmock(module.os.path).should_receive('exists').with_args('/tmp/food').and_return(True) + flexmock(module.os.path).should_receive('exists').with_args('/root/bar').and_return(True) + + module.check_all_source_directories_exist(['foo*', '/root/bar'], working_directory='/tmp')