소스 검색

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

Dan Helfman 3 년 전
부모
커밋
7e7209322a
4개의 변경된 파일20개의 추가작업 그리고 18개의 파일을 삭제
  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(