diff --git a/borgmatic/borg/create.py b/borgmatic/borg/create.py index 200f77c21..2399592b9 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -213,6 +213,10 @@ def create_archive( ) ) + try: + working_directory = os.path.expanduser(location_config.get('working_directory')) + except TypeError: + working_directory = None pattern_file = _write_pattern_file(location_config.get('patterns')) exclude_file = _write_pattern_file( _expand_home_directories(location_config.get('exclude_patterns')) @@ -309,6 +313,13 @@ def create_archive( output_log_level, output_file, borg_local_path=local_path, + working_directory=working_directory, ) - return execute_command(full_command, output_log_level, output_file, borg_local_path=local_path) + return execute_command( + full_command, + output_log_level, + output_file, + borg_local_path=local_path, + working_directory=working_directory, + ) diff --git a/borgmatic/config/schema.yaml b/borgmatic/config/schema.yaml index c0999f1ef..43d5d1573 100644 --- a/borgmatic/config/schema.yaml +++ b/borgmatic/config/schema.yaml @@ -42,6 +42,14 @@ properties: example: - user@backupserver:sourcehostname.borg - "user@backupserver:{fqdn}" + working_directory: + type: string + description: | + Working directory for the "borg create" command. Tildes are + expanded. Useful for backing up using relative paths. See + http://borgbackup.readthedocs.io/en/stable/usage/create.html + for details. Defaults to not set. + example: /path/to/working/directory one_file_system: type: boolean description: | diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index c3e161095..c5f32b663 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -277,6 +277,7 @@ def test_create_archive_calls_borg_with_parameters(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -310,6 +311,7 @@ def test_create_archive_with_patterns_calls_borg_with_patterns(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -343,6 +345,7 @@ def test_create_archive_with_exclude_patterns_calls_borg_with_excludes(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -373,6 +376,7 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.INFO) @@ -404,6 +408,7 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output(): output_log_level=None, output_file=None, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.INFO) @@ -436,6 +441,7 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.DEBUG) @@ -467,6 +473,7 @@ def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output(): output_log_level=None, output_file=None, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.DEBUG) @@ -499,6 +506,7 @@ def test_create_archive_with_dry_run_calls_borg_with_dry_run_parameter(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -531,6 +539,7 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats_paramete output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.INFO) @@ -563,6 +572,7 @@ def test_create_archive_with_checkpoint_interval_calls_borg_with_checkpoint_inte output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -593,6 +603,7 @@ def test_create_archive_with_chunker_params_calls_borg_with_chunker_params_param output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -623,6 +634,7 @@ def test_create_archive_with_compression_calls_borg_with_compression_parameters( output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -658,6 +670,7 @@ def test_create_archive_with_remote_rate_limit_calls_borg_with_upload_ratelimit_ output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -688,6 +701,7 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -724,6 +738,7 @@ def test_create_archive_with_numeric_owner_calls_borg_with_numeric_ids_parameter output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -755,6 +770,7 @@ def test_create_archive_with_read_special_calls_borg_with_read_special_parameter output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -835,6 +851,7 @@ def test_create_archive_with_atime_option_calls_borg_with_corresponding_paramete output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -877,6 +894,7 @@ def test_create_archive_with_bsd_flags_option_calls_borg_with_corresponding_para output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -908,6 +926,7 @@ def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters( output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -939,6 +958,7 @@ def test_create_archive_with_local_path_calls_borg_via_local_path(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg1', + working_directory=None, ) module.create_archive( @@ -970,6 +990,7 @@ def test_create_archive_with_remote_path_calls_borg_with_remote_path_parameters( output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1001,6 +1022,7 @@ def test_create_archive_with_umask_calls_borg_with_umask_parameters(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1031,6 +1053,7 @@ def test_create_archive_with_lock_wait_calls_borg_with_lock_wait_parameters(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1061,6 +1084,7 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_warning_o output_log_level=logging.WARNING, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1092,6 +1116,7 @@ def test_create_archive_with_stats_and_log_info_calls_borg_with_stats_parameter_ output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.INFO) @@ -1124,6 +1149,7 @@ def test_create_archive_with_files_calls_borg_with_list_parameter_and_warning_ou output_log_level=logging.WARNING, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1155,6 +1181,7 @@ def test_create_archive_with_files_and_log_info_calls_borg_with_list_parameter_a output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.INFO) @@ -1187,6 +1214,7 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para output_log_level=logging.INFO, output_file=module.DO_NOT_CAPTURE, borg_local_path='borg', + working_directory=None, ) insert_logging_mock(logging.INFO) @@ -1219,6 +1247,7 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter(): output_log_level=logging.INFO, output_file=module.DO_NOT_CAPTURE, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1253,6 +1282,7 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr output_log_level=logging.INFO, output_file=module.DO_NOT_CAPTURE, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1285,6 +1315,7 @@ def test_create_archive_with_json_calls_borg_with_json_parameter(): output_log_level=None, output_file=None, borg_local_path='borg', + working_directory=None, ).and_return('[]') json_output = module.create_archive( @@ -1318,6 +1349,7 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_parameter() output_log_level=None, output_file=None, borg_local_path='borg', + working_directory=None, ).and_return('[]') json_output = module.create_archive( @@ -1352,6 +1384,7 @@ def test_create_archive_with_source_directories_glob_expands(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) flexmock(module.glob).should_receive('glob').with_args('foo*').and_return(['foo', 'food']) @@ -1383,6 +1416,7 @@ def test_create_archive_with_non_matching_source_directories_glob_passes_through output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) flexmock(module.glob).should_receive('glob').with_args('foo*').and_return([]) @@ -1414,6 +1448,7 @@ def test_create_archive_with_glob_calls_borg_with_expanded_directories(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1444,6 +1479,7 @@ def test_create_archive_with_archive_name_format_calls_borg_with_archive_name(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1474,6 +1510,7 @@ def test_create_archive_with_archive_name_format_accepts_borg_placeholders(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1504,6 +1541,7 @@ def test_create_archive_with_repository_accepts_borg_placeholders(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1534,6 +1572,7 @@ def test_create_archive_with_extra_borg_options_calls_borg_with_extra_options(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive( @@ -1566,6 +1605,7 @@ def test_create_archive_with_stream_processes_calls_borg_with_processes(): output_log_level=logging.INFO, output_file=None, borg_local_path='borg', + working_directory=None, ) module.create_archive(