Преглед на файлове

Fix broken "recreate" action with Borg 1.4 (#610).

Dan Helfman преди 2 месеца
родител
ревизия
8c907bb5a3
променени са 3 файла, в които са добавени 251 реда и са изтрити 78 реда
  1. 17 12
      borgmatic/borg/recreate.py
  2. 1 1
      borgmatic/commands/arguments.py
  3. 233 65
      tests/unit/borg/test_recreate.py

+ 17 - 12
borgmatic/borg/recreate.py

@@ -2,6 +2,7 @@ import logging
 import shlex
 
 import borgmatic.borg.environment
+import borgmatic.borg.feature
 import borgmatic.config.paths
 import borgmatic.execute
 from borgmatic.borg import flags
@@ -68,21 +69,25 @@ def recreate_archive(
         + (('--timestamp', recreate_arguments.timestamp) if recreate_arguments.timestamp else ())
         + (('--compression', compression) if compression else ())
         + (('--chunker-params', chunker_params) if chunker_params else ())
-        + (
-            flags.make_match_archives_flags(
-                recreate_arguments.match_archives or archive or config.get('match_archives'),
-                config.get('archive_name_format'),
-                local_borg_version,
-            )
-            if recreate_arguments.match_archives
-            else ()
-        )
         + (('--recompress', recompress) if recompress else ())
         + exclude_flags
         + (
-            flags.make_repository_archive_flags(repository, archive, local_borg_version)
-            if archive
-            else flags.make_repository_flags(repository, local_borg_version)
+            (
+                flags.make_repository_flags(repository, local_borg_version)
+                + flags.make_match_archives_flags(
+                    archive or config.get('match_archives'),
+                    config.get('archive_name_format'),
+                    local_borg_version,
+                )
+            )
+            if borgmatic.borg.feature.available(
+                borgmatic.borg.feature.Feature.SEPARATE_REPOSITORY_ARCHIVE, local_borg_version
+            )
+            else (
+                flags.make_repository_archive_flags(repository, archive, local_borg_version)
+                if archive
+                else flags.make_repository_flags(repository, local_borg_version)
+            )
         )
     )
 

+ 1 - 1
borgmatic/commands/arguments.py

@@ -1562,7 +1562,7 @@ def make_parsers():
         '--glob-archives',
         dest='match_archives',
         metavar='PATTERN',
-        help='Only consider archive names, hashes, or series matching this pattern',
+        help='Only consider archive names, hashes, or series matching this pattern [Borg 2.x+ only]',
     )
     recreate_group.add_argument(
         '-h', '--help', action='help', help='Show this help message and exit'

+ 233 - 65
tests/unit/borg/test_recreate.py

@@ -20,24 +20,20 @@ def insert_execute_command_mock(command, working_directory=None, borg_exit_codes
     ).once()
 
 
-def mock_dependencies():
-    flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
-    flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
-    flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
-    flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
-    flexmock(module.borgmatic.borg.flags).should_receive(
-        'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-
-
 def test_recreate_archive_dry_run_skips_execution():
     flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
     flexmock(module.borgmatic.execute).should_receive('execute_command').never()
 
     recreate_arguments = flexmock(
@@ -67,10 +63,16 @@ def test_recreate_calls_borg_with_required_flags():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -96,10 +98,16 @@ def test_recreate_with_remote_path():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--remote-path', 'borg1', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--remote-path', 'borg1', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -125,10 +133,16 @@ def test_recreate_with_lock_wait():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--lock-wait', '5', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--lock-wait', '5', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -153,10 +167,16 @@ def test_recreate_with_log_info():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--info', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--info', '--repo', 'repo'))
 
     insert_logging_mock(logging.INFO)
 
@@ -183,10 +203,16 @@ def test_recreate_with_log_debug():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--debug', '--show-rc', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--debug', '--show-rc', '--repo', 'repo'))
     insert_logging_mock(logging.DEBUG)
 
     module.recreate_archive(
@@ -212,10 +238,16 @@ def test_recreate_with_log_json():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--log-json', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--log-json', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -239,12 +271,18 @@ def test_recreate_with_list_filter_flags():
     flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
     flexmock(module).should_receive('make_list_filter_flags').and_return('AME+-')
     insert_execute_command_mock(
-        ('borg', 'recreate', '--list', '--filter', 'AME+-', 'repo::archive')
+        ('borg', 'recreate', '--list', '--filter', 'AME+-', '--repo', 'repo')
     )
 
     module.recreate_archive(
@@ -269,13 +307,19 @@ def test_recreate_with_patterns_from_flag():
     flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
     mock_patterns_file = flexmock(name='patterns_file')
     flexmock(module).should_receive('write_patterns_file').and_return(mock_patterns_file)
     insert_execute_command_mock(
-        ('borg', 'recreate', '--patterns-from', 'patterns_file', 'repo::archive')
+        ('borg', 'recreate', '--patterns-from', 'patterns_file', '--repo', 'repo')
     )
 
     module.recreate_archive(
@@ -300,11 +344,17 @@ def test_recreate_with_exclude_flags():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
     flexmock(module).should_receive('make_exclude_flags').and_return(('--exclude', 'pattern'))
-    insert_execute_command_mock(('borg', 'recreate', '--exclude', 'pattern', 'repo::archive'))
+    insert_execute_command_mock(('borg', 'recreate', '--exclude', 'pattern', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -329,10 +379,16 @@ def test_recreate_with_target_flag():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--target', 'new-archive', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--target', 'new-archive', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -357,11 +413,17 @@ def test_recreate_with_comment_flag():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
     insert_execute_command_mock(
-        ('borg', 'recreate', '--comment', shlex.quote('This is a test comment'), 'repo::archive')
+        ('borg', 'recreate', '--comment', shlex.quote('This is a test comment'), '--repo', 'repo')
     )
 
     module.recreate_archive(
@@ -387,11 +449,17 @@ def test_recreate_with_timestamp_flag():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
     insert_execute_command_mock(
-        ('borg', 'recreate', '--timestamp', '2023-10-01T12:00:00', 'repo::archive')
+        ('borg', 'recreate', '--timestamp', '2023-10-01T12:00:00', '--repo', 'repo')
     )
 
     module.recreate_archive(
@@ -417,10 +485,16 @@ def test_recreate_with_compression_flag():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--compression', 'lz4', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--compression', 'lz4', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -445,11 +519,17 @@ def test_recreate_with_chunker_params_flag():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
     insert_execute_command_mock(
-        ('borg', 'recreate', '--chunker-params', '19,23,21,4095', 'repo::archive')
+        ('borg', 'recreate', '--chunker-params', '19,23,21,4095', '--repo', 'repo')
     )
 
     module.recreate_archive(
@@ -475,10 +555,16 @@ def test_recreate_with_recompress_flag():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--recompress', 'always', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--recompress', 'always', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -503,10 +589,16 @@ def test_recreate_with_match_archives_star():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -531,10 +623,16 @@ def test_recreate_with_match_archives_regex():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -559,10 +657,16 @@ def test_recreate_with_match_archives_shell():
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
     flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', 'repo::archive'))
+    ).and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+    insert_execute_command_mock(('borg', 'recreate', '--repo', 'repo'))
 
     module.recreate_archive(
         repository='repo',
@@ -582,22 +686,58 @@ def test_recreate_with_match_archives_shell():
     )
 
 
-def test_recreate_with_glob_archives_flag():
+def test_recreate_with_match_archives_and_feature_available_calls_borg_with_match_archives():
     flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
-    flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(
-        ('--glob-archives', 'foo-*')
+    flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').with_args(
+        'foo-*', None, '1.2.3'
+    ).and_return(('--match-archives', 'foo-*'))
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
+    flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
+        ('--repo', 'repo')
+    )
+    flexmock(module.borgmatic.borg.flags).should_receive('make_repository_archive_flags').never()
+    insert_execute_command_mock(('borg', 'recreate', '--repo', 'repo', '--match-archives', 'foo-*'))
+
+    module.recreate_archive(
+        repository='repo',
+        archive=None,
+        config={'match_archives': 'foo-*'},
+        local_borg_version='1.2.3',
+        recreate_arguments=flexmock(
+            list=None,
+            target=None,
+            comment=None,
+            timestamp=None,
+            match_archives='foo-*',
+        ),
+        global_arguments=flexmock(dry_run=False, log_json=False),
+        local_path='borg',
+        patterns=None,
+    )
+
+
+def test_recreate_with_archives_flag_and_feature_available_calls_borg_with_match_archives():
+    flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
+    flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
+    flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').with_args(
+        'archive', None, '1.2.3'
+    ).and_return(('--match-archives', 'archive'))
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
+    flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
+        ('--repo', 'repo')
+    )
+    flexmock(module.borgmatic.borg.flags).should_receive('make_repository_archive_flags').never()
+    insert_execute_command_mock(
+        ('borg', 'recreate', '--repo', 'repo', '--match-archives', 'archive')
     )
-    flexmock(module.borgmatic.borg.flags).should_receive(
-        'make_repository_archive_flags'
-    ).and_return(('repo::archive',))
-    insert_execute_command_mock(('borg', 'recreate', '--glob-archives', 'foo-*', 'repo::archive'))
 
     module.recreate_archive(
         repository='repo',
         archive='archive',
-        config={},
+        config={'match_archives': 'foo-*'},
         local_borg_version='1.2.3',
         recreate_arguments=flexmock(
             list=None,
@@ -612,31 +752,59 @@ def test_recreate_with_glob_archives_flag():
     )
 
 
-def test_recreate_with_match_archives_flag():
+def test_recreate_with_match_archives_and_feature_not_available_calls_borg_without_match_archives():
     flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
     flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
     flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
-    flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(
-        ('--match-archives', 'sh:foo-*')
+    flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').never()
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(False)
+    flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
+        ('repo',)
+    )
+    flexmock(module.borgmatic.borg.flags).should_receive('make_repository_archive_flags').never()
+    insert_execute_command_mock(('borg', 'recreate', 'repo'))
+
+    module.recreate_archive(
+        repository='repo',
+        archive=None,
+        config={'match_archives': 'foo-*'},
+        local_borg_version='1.2.3',
+        recreate_arguments=flexmock(
+            list=None,
+            target=None,
+            comment=None,
+            timestamp=None,
+            match_archives='foo-*',
+        ),
+        global_arguments=flexmock(dry_run=False, log_json=False),
+        local_path='borg',
+        patterns=None,
     )
+
+
+def test_recreate_with_archives_flags_and_feature_not_available_calls_borg_with_combined_repo_and_archive():
+    flexmock(module.borgmatic.borg.create).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.borgmatic.borg.create).should_receive('write_patterns_file').and_return(None)
+    flexmock(module.borgmatic.borg.create).should_receive('make_list_filter_flags').and_return('')
+    flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').never()
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(False)
     flexmock(module.borgmatic.borg.flags).should_receive(
         'make_repository_archive_flags'
-    ).and_return(('--repo', 'repo', 'archive'))
-    insert_execute_command_mock(
-        ('borg', 'recreate', '--match-archives', 'sh:foo-*', '--repo', 'repo', 'archive')
-    )
+    ).and_return(('repo::archive',))
+    flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').never()
+    insert_execute_command_mock(('borg', 'recreate', 'repo::archive'))
 
     module.recreate_archive(
         repository='repo',
         archive='archive',
-        config={},
-        local_borg_version='2.0.0b3',
+        config={'match_archives': 'foo-*'},
+        local_borg_version='1.2.3',
         recreate_arguments=flexmock(
             list=None,
             target=None,
             comment=None,
             timestamp=None,
-            match_archives='sh:foo-*',
+            match_archives='foo-*',
         ),
         global_arguments=flexmock(dry_run=False, log_json=False),
         local_path='borg',