From 7e7209322a4549fdc8baeb3bc4925d46e15018db Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Thu, 10 Feb 2022 09:51:13 -0800 Subject: [PATCH] When using the "numeric_owner" option, tailor the flags passed to Borg depending on the Borg version (#394). --- NEWS | 4 ++-- borgmatic/borg/create.py | 7 ++++++- borgmatic/borg/feature.py | 2 ++ tests/unit/borg/test_create.py | 25 ++++++++++--------------- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index ecd7361f3..0df93cb38 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" or "bsd_flags" options, tailor the flags passed to Borg depending on - the Borg version. + * #394: When using the "atime", "bsd_flags", or "numeric_owner" 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 675a0671f..9bf62d6ea 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -237,6 +237,11 @@ def create_archive( else: noflags_flags = ('--nobsdflags',) if location_config.get('bsd_flags') is False else () + if feature.available(feature.Feature.NUMERIC_IDS, local_borg_version): + numeric_ids_flags = ('--numeric-ids',) if location_config.get('numeric_owner') else () + else: + numeric_ids_flags = ('--numeric-owner',) if location_config.get('numeric_owner') else () + full_command = ( tuple(local_path.split(' ')) + ('create',) @@ -251,7 +256,7 @@ def create_archive( if location_config.get('one_file_system') or stream_processes else () ) - + (('--numeric-owner',) if location_config.get('numeric_owner') else ()) + + numeric_ids_flags + atime_flags + (('--noctime',) if location_config.get('ctime') is False else ()) + (('--nobirthtime',) if location_config.get('birthtime') is False else ()) diff --git a/borgmatic/borg/feature.py b/borgmatic/borg/feature.py index e8706e732..386e97326 100644 --- a/borgmatic/borg/feature.py +++ b/borgmatic/borg/feature.py @@ -7,12 +7,14 @@ class Feature(Enum): COMPACT = 1 ATIME = 2 NOFLAGS = 3 + NUMERIC_IDS = 4 FEATURE_TO_MINIMUM_BORG_VERSION = { Feature.COMPACT: parse_version('1.2.0a2'), # borg compact 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 } diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index 1150e7313..79f958b9d 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -699,18 +699,23 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par ) -def test_create_archive_with_numeric_owner_calls_borg_with_numeric_owner_parameter(): +@pytest.mark.parametrize( + '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 +): 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', '--numeric-owner') + ARCHIVE_WITH_PATHS, + ('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, output_file=None, borg_local_path='borg', @@ -817,12 +822,7 @@ def test_create_archive_with_atime_option_calls_borg_with_corresponding_paramete 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').with_args( - module.feature.Feature.ATIME, '1.2.3' - ).and_return(feature_available) - flexmock(module.feature).should_receive('available').with_args( - module.feature.Feature.NOFLAGS, '1.2.3' - ).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( @@ -864,12 +864,7 @@ def test_create_archive_with_bsd_flags_option_calls_borg_with_corresponding_para 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').with_args( - module.feature.Feature.ATIME, '1.2.3' - ).and_return(True) - flexmock(module.feature).should_receive('available').with_args( - module.feature.Feature.NOFLAGS, '1.2.3' - ).and_return(feature_available) + 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(