Explorar el Código

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

Dan Helfman hace 3 años
padre
commit
6bf6ac310b

+ 2 - 1
NEWS

@@ -2,7 +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 the "atime" option is used, tailor the flags passed to Borg depending on version.
+ * #394: When using the "atime" or "bsd_flags" 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

+ 7 - 3
borgmatic/borg/create.py

@@ -227,12 +227,16 @@ def create_archive(
     archive_name_format = storage_config.get('archive_name_format', DEFAULT_ARCHIVE_NAME_FORMAT)
     extra_borg_options = storage_config.get('extra_borg_options', {}).get('create', '')
 
-    atime_feature_available = feature.available(feature.Feature.ATIME, local_borg_version)
-    if atime_feature_available:
+    if feature.available(feature.Feature.ATIME, local_borg_version):
         atime_flags = ('--atime',) if location_config.get('atime') is True else ()
     else:
         atime_flags = ('--noatime',) if location_config.get('atime') is False else ()
 
+    if feature.available(feature.Feature.NOFLAGS, local_borg_version):
+        noflags_flags = ('--noflags',) if location_config.get('bsd_flags') is False else ()
+    else:
+        noflags_flags = ('--nobsdflags',) if location_config.get('bsd_flags') is False else ()
+
     full_command = (
         tuple(local_path.split(' '))
         + ('create',)
@@ -252,7 +256,7 @@ def create_archive(
         + (('--noctime',) if location_config.get('ctime') is False else ())
         + (('--nobirthtime',) if location_config.get('birthtime') is False else ())
         + (('--read-special',) if (location_config.get('read_special') or stream_processes) else ())
-        + (('--nobsdflags',) if location_config.get('bsd_flags') is False else ())
+        + noflags_flags
         + (('--files-cache', files_cache) if files_cache else ())
         + (('--remote-path', remote_path) if remote_path else ())
         + (('--umask', str(umask)) if umask else ())

+ 4 - 2
borgmatic/borg/feature.py

@@ -6,11 +6,13 @@ from pkg_resources import parse_version
 class Feature(Enum):
     COMPACT = 1
     ATIME = 2
+    NOFLAGS = 3
 
 
 FEATURE_TO_MINIMUM_BORG_VERSION = {
-    Feature.COMPACT: parse_version('1.2.0a2'),
-    Feature.ATIME: parse_version('1.2.0a7'),
+    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
 }
 
 

+ 4 - 4
borgmatic/config/schema.yaml

@@ -111,10 +111,10 @@ properties:
                     type: string
                 description: |
                     Any paths matching these patterns are included/excluded from
-                    backups. Globs are expanded. (Tildes are not.) Note that
-                    Borg considers this option experimental. See the output of
-                    "borg help patterns" for more details. Quote any value if it
-                    contains leading punctuation, so it parses correctly.
+                    backups. Globs are expanded. (Tildes are not.) See the
+                    output of "borg help patterns" for more details. Quote any
+                    value if it contains leading punctuation, so it parses
+                    correctly.
                 example:
                     - 'R /'
                     - '- /home/*/.cache'

+ 1 - 1
scripts/find-unsupported-borg-options

@@ -38,7 +38,7 @@ for sub_command in prune create check list info; do
             | grep -v '^--json$' \
             | grep -v '^--keep-last$' \
             | grep -v '^--list$' \
-            | grep -v '^--nobsdflags$' \
+            | grep -v '^--bsdflags$' \
             | grep -v '^--pattern$' \
             | grep -v '^--progress$' \
             | grep -v '^--stats$' \

+ 47 - 5
tests/unit/borg/test_create.py

@@ -768,11 +768,9 @@ def test_create_archive_with_read_special_calls_borg_with_read_special_parameter
         ('ctime', False),
         ('birthtime', True),
         ('birthtime', False),
-        ('bsd_flags', True),
-        ('bsd_flags', False),
     ),
 )
-def test_create_archive_with_option_calls_borg_without_corresponding_parameter(
+def test_create_archive_with_basic_option_calls_borg_with_corresponding_parameter(
     option_name, option_value
 ):
     option_flag = '--no' + option_name.replace('_', '') if option_value is False else None
@@ -815,7 +813,7 @@ def test_create_archive_with_option_calls_borg_without_corresponding_parameter(
         (False, False, '--noatime'),
     ),
 )
-def test_create_archive_with_atime_option_calls_borg_without_corresponding_parameter(
+def test_create_archive_with_atime_option_calls_borg_with_corresponding_parameter(
     option_value, feature_available, option_flag
 ):
     flexmock(module).should_receive('borgmatic_source_directories').and_return([])
@@ -824,7 +822,8 @@ def test_create_archive_with_atime_option_calls_borg_without_corresponding_param
     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(feature_available)
+    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).should_receive('_make_pattern_flags').and_return(())
     flexmock(module).should_receive('_make_exclude_flags').and_return(())
     flexmock(module).should_receive('execute_command').with_args(
@@ -848,6 +847,49 @@ def test_create_archive_with_atime_option_calls_borg_without_corresponding_param
     )
 
 
+@pytest.mark.parametrize(
+    'option_value,feature_available,option_flag',
+    (
+        (True, True, None),
+        (True, False, None),
+        (False, True, '--noflags'),
+        (False, False, '--nobsdflags'),
+    ),
+)
+def test_create_archive_with_bsd_flags_option_calls_borg_with_corresponding_parameter(
+    option_value, 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').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).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') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
+        output_log_level=logging.INFO,
+        output_file=None,
+        borg_local_path='borg',
+    )
+
+    module.create_archive(
+        dry_run=False,
+        repository='repo',
+        location_config={
+            'source_directories': ['foo', 'bar'],
+            'repositories': ['repo'],
+            'bsd_flags': option_value,
+            'exclude_patterns': None,
+        },
+        storage_config={},
+        local_borg_version='1.2.3',
+    )
+
+
 def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters():
     flexmock(module).should_receive('borgmatic_source_directories').and_return([])
     flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar'))