diff --git a/NEWS b/NEWS index 0df93cb3..1637c550 100644 --- a/NEWS +++ b/NEWS @@ -2,8 +2,8 @@ * #394: Compact repository segments and free space with new "borgmatic compact" action. Borg 1.2+ only. Also run "compact" by default when no actions are specified, as "prune" in Borg 1.2 no longer frees up space unless "compact" is run. - * #394: When using the "atime", "bsd_flags", or "numeric_owner" options, tailor the flags passed - to Borg depending on the Borg version. + * #394: When using the "atime", "bsd_flags", "numeric_owner", or "remote_rate_limit" options, + tailor the flags passed to Borg depending on the Borg version. * #480, #482: Fix traceback when a YAML validation error occurs. 1.5.22 diff --git a/borgmatic/borg/create.py b/borgmatic/borg/create.py index 9bf62d6e..23304843 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -242,6 +242,11 @@ def create_archive( else: numeric_ids_flags = ('--numeric-owner',) if location_config.get('numeric_owner') else () + if feature.available(feature.Feature.UPLOAD_RATELIMIT, local_borg_version): + upload_ratelimit_flags = ('--upload-ratelimit', str(remote_rate_limit)) if remote_rate_limit else () + else: + upload_ratelimit_flags = ('--remote-ratelimit', str(remote_rate_limit)) if remote_rate_limit else () + full_command = ( tuple(local_path.split(' ')) + ('create',) @@ -250,7 +255,7 @@ def create_archive( + (('--checkpoint-interval', str(checkpoint_interval)) if checkpoint_interval else ()) + (('--chunker-params', chunker_params) if chunker_params else ()) + (('--compression', compression) if compression else ()) - + (('--remote-ratelimit', str(remote_rate_limit)) if remote_rate_limit else ()) + + upload_ratelimit_flags + ( ('--one-file-system',) if location_config.get('one_file_system') or stream_processes diff --git a/borgmatic/borg/feature.py b/borgmatic/borg/feature.py index 386e9732..af87d309 100644 --- a/borgmatic/borg/feature.py +++ b/borgmatic/borg/feature.py @@ -8,6 +8,7 @@ class Feature(Enum): ATIME = 2 NOFLAGS = 3 NUMERIC_IDS = 4 + UPLOAD_RATELIMIT = 5 FEATURE_TO_MINIMUM_BORG_VERSION = { @@ -15,6 +16,7 @@ FEATURE_TO_MINIMUM_BORG_VERSION = { Feature.ATIME: parse_version('1.2.0a7'), # borg create --atime Feature.NOFLAGS: parse_version('1.2.0a8'), # borg create --noflags Feature.NUMERIC_IDS: parse_version('1.2.0b3'), # borg create/extract/mount --numeric-ids + Feature.UPLOAD_RATELIMIT: parse_version('1.2.0b3'), # borg create --upload-ratelimit } diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index 2a470d9d..66128b97 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -638,18 +638,21 @@ def test_create_archive_with_compression_calls_borg_with_compression_parameters( ) -def test_create_archive_with_remote_rate_limit_calls_borg_with_remote_ratelimit_parameters(): +@pytest.mark.parametrize( + 'feature_available,option_flag', ((True, '--upload-ratelimit'), (False, '--remote-ratelimit')), +) +def test_create_archive_with_remote_rate_limit_calls_borg_with_upload_ratelimit_parameters(feature_available, option_flag): flexmock(module).should_receive('borgmatic_source_directories').and_return([]) flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) flexmock(module).should_receive('map_directories_to_devices').and_return({}) flexmock(module).should_receive('_expand_directories').and_return(()) flexmock(module).should_receive('_expand_home_directories').and_return(()) flexmock(module).should_receive('_write_pattern_file').and_return(None) - flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.feature).should_receive('available').and_return(feature_available) flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--remote-ratelimit', '100') + ARCHIVE_WITH_PATHS, + ('borg', 'create', option_flag, '100') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, output_file=None, borg_local_path='borg', @@ -700,7 +703,7 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par @pytest.mark.parametrize( - 'feature_available,option_flag', ((True, '--numeric-ids'), (False, '--numeric-owner'),), + 'feature_available,option_flag', ((True, '--numeric-ids'), (False, '--numeric-owner')), ) def test_create_archive_with_numeric_owner_calls_borg_with_numeric_ids_parameter( feature_available, option_flag