Browse Source

When using the "numeric_owner" option, tailor the flags passed to Borg depending on the Borg version (#394).

Dan Helfman 3 years ago
parent
commit
7e7209322a
4 changed files with 20 additions and 18 deletions
  1. 2 2
      NEWS
  2. 6 1
      borgmatic/borg/create.py
  3. 2 0
      borgmatic/borg/feature.py
  4. 10 15
      tests/unit/borg/test_create.py

+ 2 - 2
NEWS

@@ -2,8 +2,8 @@
  * #394: Compact repository segments and free space with new "borgmatic compact" action. Borg 1.2+
  * #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
    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.
    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.
  * #480, #482: Fix traceback when a YAML validation error occurs.
 
 
 1.5.22
 1.5.22

+ 6 - 1
borgmatic/borg/create.py

@@ -237,6 +237,11 @@ def create_archive(
     else:
     else:
         noflags_flags = ('--nobsdflags',) if location_config.get('bsd_flags') is False 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 = (
     full_command = (
         tuple(local_path.split(' '))
         tuple(local_path.split(' '))
         + ('create',)
         + ('create',)
@@ -251,7 +256,7 @@ def create_archive(
             if location_config.get('one_file_system') or stream_processes
             if location_config.get('one_file_system') or stream_processes
             else ()
             else ()
         )
         )
-        + (('--numeric-owner',) if location_config.get('numeric_owner') else ())
+        + numeric_ids_flags
         + atime_flags
         + atime_flags
         + (('--noctime',) if location_config.get('ctime') is False else ())
         + (('--noctime',) if location_config.get('ctime') is False else ())
         + (('--nobirthtime',) if location_config.get('birthtime') is False else ())
         + (('--nobirthtime',) if location_config.get('birthtime') is False else ())

+ 2 - 0
borgmatic/borg/feature.py

@@ -7,12 +7,14 @@ class Feature(Enum):
     COMPACT = 1
     COMPACT = 1
     ATIME = 2
     ATIME = 2
     NOFLAGS = 3
     NOFLAGS = 3
+    NUMERIC_IDS = 4
 
 
 
 
 FEATURE_TO_MINIMUM_BORG_VERSION = {
 FEATURE_TO_MINIMUM_BORG_VERSION = {
     Feature.COMPACT: parse_version('1.2.0a2'),  # borg compact
     Feature.COMPACT: parse_version('1.2.0a2'),  # borg compact
     Feature.ATIME: parse_version('1.2.0a7'),  # borg create --atime
     Feature.ATIME: parse_version('1.2.0a7'),  # borg create --atime
     Feature.NOFLAGS: parse_version('1.2.0a8'),  # borg create --noflags
     Feature.NOFLAGS: parse_version('1.2.0a8'),  # borg create --noflags
+    Feature.NUMERIC_IDS: parse_version('1.2.0b3'),  # borg create/extract/mount --numeric-ids
 }
 }
 
 
 
 

+ 10 - 15
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('borgmatic_source_directories').and_return([])
     flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar'))
     flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar'))
     flexmock(module).should_receive('map_directories_to_devices').and_return({})
     flexmock(module).should_receive('map_directories_to_devices').and_return({})
     flexmock(module).should_receive('_expand_directories').and_return(())
     flexmock(module).should_receive('_expand_directories').and_return(())
     flexmock(module).should_receive('_expand_home_directories').and_return(())
     flexmock(module).should_receive('_expand_home_directories').and_return(())
     flexmock(module).should_receive('_write_pattern_file').and_return(None)
     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_pattern_flags').and_return(())
     flexmock(module).should_receive('_make_exclude_flags').and_return(())
     flexmock(module).should_receive('_make_exclude_flags').and_return(())
     flexmock(module).should_receive('execute_command').with_args(
     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_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         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_directories').and_return(())
     flexmock(module).should_receive('_expand_home_directories').and_return(())
     flexmock(module).should_receive('_expand_home_directories').and_return(())
     flexmock(module).should_receive('_write_pattern_file').and_return(None)
     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_pattern_flags').and_return(())
     flexmock(module).should_receive('_make_exclude_flags').and_return(())
     flexmock(module).should_receive('_make_exclude_flags').and_return(())
     flexmock(module).should_receive('execute_command').with_args(
     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_directories').and_return(())
     flexmock(module).should_receive('_expand_home_directories').and_return(())
     flexmock(module).should_receive('_expand_home_directories').and_return(())
     flexmock(module).should_receive('_write_pattern_file').and_return(None)
     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_pattern_flags').and_return(())
     flexmock(module).should_receive('_make_exclude_flags').and_return(())
     flexmock(module).should_receive('_make_exclude_flags').and_return(())
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(