浏览代码

Fix error with "info --match-archives" and fix "--match-archives" overriding logic (#666).

Dan Helfman 2 年之前
父节点
当前提交
616eb6b6da

+ 5 - 0
NEWS

@@ -1,3 +1,8 @@
+1.7.12.dev0
+ * #666: Fix error when running the "info" action with the "--match-archives" flag. Also fix the
+   "--match-archives" flag to correctly override the "match_archives" configuration option for
+   the "transfer", "list", "rlist", and "info" actions.
+
 1.7.11
  * #479, #588: BREAKING: Automatically use the "archive_name_format" option to filter which archives
    get used for borgmatic actions that operate on multiple archives. Override this behavior with the

+ 4 - 7
borgmatic/borg/info.py

@@ -46,21 +46,18 @@ def display_archives_info(
             if info_arguments.prefix
             else (
                 flags.make_match_archives_flags(
-                    storage_config.get('match_archives'),
+                    info_arguments.match_archives
+                    or info_arguments.archive
+                    or storage_config.get('match_archives'),
                     storage_config.get('archive_name_format'),
                     local_borg_version,
                 )
             )
         )
         + flags.make_flags_from_arguments(
-            info_arguments, excludes=('repository', 'archive', 'prefix')
+            info_arguments, excludes=('repository', 'archive', 'prefix', 'match_archives')
         )
         + flags.make_repository_flags(repository_path, local_borg_version)
-        + (
-            flags.make_flags('match-archives', info_arguments.archive)
-            if feature.available(feature.Feature.MATCH_ARCHIVES, local_borg_version)
-            else flags.make_flags('glob-archives', info_arguments.archive)
-        )
     )
 
     if info_arguments.json:

+ 2 - 2
borgmatic/borg/rlist.py

@@ -52,7 +52,7 @@ def resolve_archive_name(
     return latest_archive
 
 
-MAKE_FLAGS_EXCLUDES = ('repository', 'prefix')
+MAKE_FLAGS_EXCLUDES = ('repository', 'prefix', 'match_archives')
 
 
 def make_rlist_command(
@@ -96,7 +96,7 @@ def make_rlist_command(
             if rlist_arguments.prefix
             else (
                 flags.make_match_archives_flags(
-                    storage_config.get('match_archives'),
+                    rlist_arguments.match_archives or storage_config.get('match_archives'),
                     storage_config.get('archive_name_format'),
                     local_borg_version,
                 )

+ 3 - 7
borgmatic/borg/transfer.py

@@ -28,12 +28,6 @@ def transfer_archives(
         + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
         + flags.make_flags('remote-path', remote_path)
         + flags.make_flags('lock-wait', storage_config.get('lock_wait', None))
-        + (('--progress',) if transfer_arguments.progress else ())
-        + (
-            flags.make_flags(
-                'match-archives', transfer_arguments.match_archives or transfer_arguments.archive
-            )
-        )
         + (
             flags.make_flags_from_arguments(
                 transfer_arguments,
@@ -41,7 +35,9 @@ def transfer_archives(
             )
             or (
                 flags.make_match_archives_flags(
-                    storage_config.get('match_archives'),
+                    transfer_arguments.match_archives
+                    or transfer_arguments.archive
+                    or storage_config.get('match_archives'),
                     storage_config.get('archive_name_format'),
                     local_borg_version,
                 )

+ 16 - 4
borgmatic/commands/arguments.py

@@ -652,7 +652,7 @@ def make_parsers():
         '--json', default=False, action='store_true', help='Output results as JSON'
     )
     rlist_group.add_argument(
-        '-P', '--prefix', help='Only list archive names starting with this prefix'
+        '-P', '--prefix', help='Deprecated. Only list archive names starting with this prefix'
     )
     rlist_group.add_argument(
         '-a',
@@ -707,7 +707,7 @@ def make_parsers():
         '--json', default=False, action='store_true', help='Output results as JSON'
     )
     list_group.add_argument(
-        '-P', '--prefix', help='Only list archive names starting with this prefix'
+        '-P', '--prefix', help='Deprecated. Only list archive names starting with this prefix'
     )
     list_group.add_argument(
         '-a',
@@ -779,7 +779,9 @@ def make_parsers():
         '--json', dest='json', default=False, action='store_true', help='Output results as JSON'
     )
     info_group.add_argument(
-        '-P', '--prefix', help='Only show info for archive names starting with this prefix'
+        '-P',
+        '--prefix',
+        help='Deprecated. Only show info for archive names starting with this prefix',
     )
     info_group.add_argument(
         '-a',
@@ -877,7 +879,17 @@ def parse_arguments(*unparsed_arguments):
         and arguments['transfer'].match_archives
     ):
         raise ValueError(
-            'With the transfer action, only one of --archive and --glob-archives flags can be used.'
+            'With the transfer action, only one of --archive and --match-archives flags can be used.'
+        )
+
+    if 'list' in arguments and (arguments['list'].prefix and arguments['list'].match_archives):
+        raise ValueError(
+            'With the list action, only one of --prefix or --match-archives flags can be used.'
+        )
+
+    if 'rlist' in arguments and (arguments['rlist'].prefix and arguments['rlist'].match_archives):
+        raise ValueError(
+            'With the rlist action, only one of --prefix or --match-archives flags can be used.'
         )
 
     if 'info' in arguments and (

+ 6 - 2
docs/how-to/make-per-application-backups.md

@@ -128,13 +128,17 @@ documentation](https://borgbackup.readthedocs.io/en/stable/usage/help.html#borg-
 for more information. For Borg 2.x, see the [match archives
 documentation](https://borgbackup.readthedocs.io/en/2.0.0b5/usage/help.html#borg-help-match-archives).
 
+Some borgmatic command-line actions also have a `--match-archives` flag that
+overrides both the auto-matching behavior and the `match_archives`
+configuration option.
+
 <span class="minilink minilink-addedin">Prior to 1.7.11</span> The way to
 limit the archives used for the `prune` action was a `prefix` option in the
 `retention` section for matching against the start of archive names. And the
 option for limiting the archives used for the `check` action was a separate
 `prefix` in the `consistency` section. Both of these options are deprecated in
-favor of the auto-matching behavior (or `match_archives`) in newer versions of
-borgmatic.
+favor of the auto-matching behavior (or `match_archives`/`--match-archives`)
+in newer versions of borgmatic.
 
 
 ## Configuration includes

+ 1 - 1
setup.py

@@ -1,6 +1,6 @@
 from setuptools import find_packages, setup
 
-VERSION = '1.7.11'
+VERSION = '1.7.12.dev0'
 
 
 setup(

+ 104 - 0
tests/integration/borg/test_commands.py

@@ -0,0 +1,104 @@
+import copy
+
+import flexmock
+
+import borgmatic.borg.info
+import borgmatic.borg.list
+import borgmatic.borg.rlist
+import borgmatic.borg.transfer
+import borgmatic.commands.arguments
+
+
+def assert_command_does_not_duplicate_flags(command, *args, **kwargs):
+    '''
+    Assert that the given Borg command sequence does not contain any duplicated flags, e.g.
+    "--match-archives" twice anywhere in the command.
+    '''
+    flag_counts = {}
+
+    for flag_name in command:
+        if not flag_name.startswith('--'):
+            continue
+
+        if flag_name in flag_counts:
+            flag_counts[flag_name] += 1
+        else:
+            flag_counts[flag_name] = 1
+
+    assert flag_counts == {
+        flag_name: 1 for flag_name in flag_counts
+    }, f"Duplicate flags found in: {' '.join(command)}"
+
+
+def fuzz_argument(arguments, argument_name):
+    '''
+    Given an argparse.Namespace instance of arguments and an argument name in it, copy the arguments
+    namespace and set the argument name in the copy with a fake value. Return the copied arguments.
+
+    This is useful for "fuzzing" a unit under test by passing it each possible argument in turn,
+    making sure it doesn't blow up or duplicate Borg arguments.
+    '''
+    arguments_copy = copy.copy(arguments)
+    value = getattr(arguments_copy, argument_name)
+    setattr(arguments_copy, argument_name, not value if isinstance(value, bool) else 'value')
+
+    return arguments_copy
+
+
+def test_transfer_archives_command_does_not_duplicate_flags_or_raise():
+    arguments = borgmatic.commands.arguments.parse_arguments(
+        'transfer', '--source-repository', 'foo'
+    )['transfer']
+    flexmock(borgmatic.borg.transfer).should_receive('execute_command').replace_with(
+        assert_command_does_not_duplicate_flags
+    )
+
+    for argument_name in dir(arguments):
+        if argument_name.startswith('_'):
+            continue
+
+        borgmatic.borg.transfer.transfer_archives(
+            False, 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
+        )
+
+
+def test_make_list_command_does_not_duplicate_flags_or_raise():
+    arguments = borgmatic.commands.arguments.parse_arguments('list')['list']
+
+    for argument_name in dir(arguments):
+        if argument_name.startswith('_'):
+            continue
+
+        borgmatic.borg.list.make_list_command(
+            'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
+        )
+
+
+def test_make_rlist_command_does_not_duplicate_flags_or_raise():
+    arguments = borgmatic.commands.arguments.parse_arguments('rlist')['rlist']
+
+    for argument_name in dir(arguments):
+        if argument_name.startswith('_'):
+            continue
+
+        borgmatic.borg.rlist.make_rlist_command(
+            'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
+        )
+
+
+def test_display_archives_info_command_does_not_duplicate_flags_or_raise():
+    arguments = borgmatic.commands.arguments.parse_arguments('info')['info']
+    flexmock(borgmatic.borg.info).should_receive('execute_command_and_capture_output').replace_with(
+        assert_command_does_not_duplicate_flags
+    )
+    flexmock(borgmatic.borg.info).should_receive('execute_command').replace_with(
+        assert_command_does_not_duplicate_flags
+    )
+
+    for argument_name in dir(arguments):
+        if argument_name.startswith('_'):
+            continue
+
+        borgmatic.borg.info.display_archives_info(
+            'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name)
+        )

+ 14 - 0
tests/integration/commands/test_arguments.py

@@ -465,6 +465,20 @@ def test_parse_arguments_disallows_transfer_with_both_archive_and_match_archives
         )
 
 
+def test_parse_arguments_disallows_list_with_both_prefix_and_match_archives():
+    flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
+
+    with pytest.raises(ValueError):
+        module.parse_arguments('list', '--prefix', 'foo', '--match-archives', 'sh:*bar')
+
+
+def test_parse_arguments_disallows_rlist_with_both_prefix_and_match_archives():
+    flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
+
+    with pytest.raises(ValueError):
+        module.parse_arguments('rlist', '--prefix', 'foo', '--match-archives', 'sh:*bar')
+
+
 def test_parse_arguments_disallows_info_with_both_archive_and_match_archives():
     flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
 

+ 71 - 19
tests/unit/borg/test_info.py

@@ -29,7 +29,7 @@ def test_display_archives_info_calls_borg_with_parameters():
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None),
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
     )
 
 
@@ -54,7 +54,7 @@ def test_display_archives_info_with_log_info_calls_borg_with_info_parameter():
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None),
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
     )
 
 
@@ -77,7 +77,7 @@ def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_outpu
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=True, prefix=None),
+        info_arguments=flexmock(archive=None, json=True, prefix=None, match_archives=None),
     )
 
     assert json_output == '[]'
@@ -105,7 +105,7 @@ def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter():
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None),
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
     )
 
 
@@ -128,7 +128,7 @@ def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_outp
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=True, prefix=None),
+        info_arguments=flexmock(archive=None, json=True, prefix=None, match_archives=None),
     )
 
     assert json_output == '[]'
@@ -152,7 +152,7 @@ def test_display_archives_info_with_json_calls_borg_with_json_parameter():
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=True, prefix=None),
+        info_arguments=flexmock(archive=None, json=True, prefix=None, match_archives=None),
     )
 
     assert json_output == '[]'
@@ -162,17 +162,14 @@ def test_display_archives_info_with_archive_calls_borg_with_match_archives_param
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
-    flexmock(module.flags).should_receive('make_flags').with_args(
-        'match-archives', 'archive'
-    ).and_return(('--match-archives', 'archive'))
     flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
-        None, None, '2.3.4'
-    ).and_return(())
+        'archive', None, '2.3.4'
+    ).and_return(('--match-archives', 'archive'))
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'info', '--repo', 'repo', '--match-archives', 'archive'),
+        ('borg', 'info', '--match-archives', 'archive', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
         borg_local_path='borg',
         extra_environment=None,
@@ -182,7 +179,7 @@ def test_display_archives_info_with_archive_calls_borg_with_match_archives_param
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive='archive', json=False, prefix=None),
+        info_arguments=flexmock(archive='archive', json=False, prefix=None, match_archives=None),
     )
 
 
@@ -207,7 +204,7 @@ def test_display_archives_info_with_local_path_calls_borg_via_local_path():
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None),
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
         local_path='borg1',
     )
 
@@ -236,7 +233,7 @@ def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_para
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None),
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
         remote_path='borg1',
     )
 
@@ -266,7 +263,7 @@ def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_paramete
         repository_path='repo',
         storage_config=storage_config,
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None),
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
     )
 
 
@@ -347,11 +344,64 @@ def test_display_archives_info_transforms_archive_name_format_into_match_archive
         repository_path='repo',
         storage_config={'archive_name_format': 'bar-{now}'},  # noqa: FS003
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None),
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
+    )
+
+
+def test_display_archives_with_match_archives_option_calls_borg_with_match_archives_parameter():
+    flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
+    flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
+    flexmock(module.flags).should_receive('make_flags').and_return(())
+    flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
+        'sh:foo-*', 'bar-{now}', '2.3.4'  # noqa: FS003
+    ).and_return(('--match-archives', 'sh:foo-*'))
+    flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
+    flexmock(module.environment).should_receive('make_environment')
+    flexmock(module).should_receive('execute_command').with_args(
+        ('borg', 'info', '--match-archives', 'sh:foo-*', '--repo', 'repo'),
+        output_log_level=module.borgmatic.logger.ANSWER,
+        borg_local_path='borg',
+        extra_environment=None,
+    )
+
+    module.display_archives_info(
+        repository_path='repo',
+        storage_config={
+            'archive_name_format': 'bar-{now}',  # noqa: FS003
+            'match_archives': 'sh:foo-*',
+        },
+        local_borg_version='2.3.4',
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None),
+    )
+
+
+def test_display_archives_with_match_archives_flag_calls_borg_with_match_archives_parameter():
+    flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
+    flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
+    flexmock(module.flags).should_receive('make_flags').and_return(())
+    flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
+        'sh:foo-*', 'bar-{now}', '2.3.4'  # noqa: FS003
+    ).and_return(('--match-archives', 'sh:foo-*'))
+    flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
+    flexmock(module.environment).should_receive('make_environment')
+    flexmock(module).should_receive('execute_command').with_args(
+        ('borg', 'info', '--match-archives', 'sh:foo-*', '--repo', 'repo'),
+        output_log_level=module.borgmatic.logger.ANSWER,
+        borg_local_path='borg',
+        extra_environment=None,
+    )
+
+    module.display_archives_info(
+        repository_path='repo',
+        storage_config={'archive_name_format': 'bar-{now}'},  # noqa: FS003
+        local_borg_version='2.3.4',
+        info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives='sh:foo-*'),
     )
 
 
-@pytest.mark.parametrize('argument_name', ('match_archives', 'sort_by', 'first', 'last'))
+@pytest.mark.parametrize('argument_name', ('sort_by', 'first', 'last'))
 def test_display_archives_info_passes_through_arguments_to_borg(argument_name):
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
@@ -376,5 +426,7 @@ def test_display_archives_info_passes_through_arguments_to_borg(argument_name):
         repository_path='repo',
         storage_config={},
         local_borg_version='2.3.4',
-        info_arguments=flexmock(archive=None, json=False, prefix=None, **{argument_name: 'value'}),
+        info_arguments=flexmock(
+            archive=None, json=False, prefix=None, match_archives=None, **{argument_name: 'value'}
+        ),
     )

+ 61 - 20
tests/unit/borg/test_rlist.py

@@ -137,7 +137,9 @@ def test_make_rlist_command_includes_log_info():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=False, prefix=None, match_archives=None
+        ),
     )
 
     assert command == ('borg', 'list', '--info', 'repo')
@@ -156,7 +158,9 @@ def test_make_rlist_command_includes_json_but_not_info():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=True, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=True, prefix=None, match_archives=None
+        ),
     )
 
     assert command == ('borg', 'list', '--json', 'repo')
@@ -175,7 +179,9 @@ def test_make_rlist_command_includes_log_debug():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=False, prefix=None, match_archives=None
+        ),
     )
 
     assert command == ('borg', 'list', '--debug', '--show-rc', 'repo')
@@ -194,7 +200,9 @@ def test_make_rlist_command_includes_json_but_not_debug():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=True, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=True, prefix=None, match_archives=None
+        ),
     )
 
     assert command == ('borg', 'list', '--json', 'repo')
@@ -212,7 +220,9 @@ def test_make_rlist_command_includes_json():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=True, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=True, prefix=None, match_archives=None
+        ),
     )
 
     assert command == ('borg', 'list', '--json', 'repo')
@@ -232,7 +242,9 @@ def test_make_rlist_command_includes_lock_wait():
         repository_path='repo',
         storage_config={'lock_wait': 5},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=False, prefix=None, match_archives=None
+        ),
     )
 
     assert command == ('borg', 'list', '--lock-wait', '5', 'repo')
@@ -250,7 +262,9 @@ def test_make_rlist_command_includes_local_path():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=False, prefix=None, match_archives=None
+        ),
         local_path='borg2',
     )
 
@@ -271,7 +285,9 @@ def test_make_rlist_command_includes_remote_path():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=False, prefix=None, match_archives=None
+        ),
         remote_path='borg2',
     )
 
@@ -328,7 +344,9 @@ def test_make_rlist_command_transforms_archive_name_format_into_match_archives()
         repository_path='repo',
         storage_config={'archive_name_format': 'bar-{now}'},  # noqa: FS003
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=False, prefix=None, match_archives=None
+        ),
     )
 
     assert command == ('borg', 'list', '--match-archives', 'sh:bar-*', 'repo')
@@ -346,7 +364,9 @@ def test_make_rlist_command_includes_short():
         repository_path='repo',
         storage_config={},
         local_borg_version='1.2.3',
-        rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None, short=True),
+        rlist_arguments=flexmock(
+            archive=None, paths=None, json=False, prefix=None, match_archives=None, short=True
+        ),
     )
 
     assert command == ('borg', 'list', '--short', 'repo')
@@ -354,16 +374,7 @@ def test_make_rlist_command_includes_short():
 
 @pytest.mark.parametrize(
     'argument_name',
-    (
-        'match_archives',
-        'sort_by',
-        'first',
-        'last',
-        'exclude',
-        'exclude_from',
-        'pattern',
-        'patterns_from',
-    ),
+    ('sort_by', 'first', 'last', 'exclude', 'exclude_from', 'pattern', 'patterns_from',),
 )
 def test_make_rlist_command_includes_additional_flags(argument_name):
     flexmock(module.flags).should_receive('make_flags').and_return(())
@@ -384,6 +395,7 @@ def test_make_rlist_command_includes_additional_flags(argument_name):
             paths=None,
             json=False,
             prefix=None,
+            match_archives=None,
             find_paths=None,
             format=None,
             **{argument_name: 'value'},
@@ -393,6 +405,35 @@ def test_make_rlist_command_includes_additional_flags(argument_name):
     assert command == ('borg', 'list', '--' + argument_name.replace('_', '-'), 'value', 'repo')
 
 
+def test_make_rlist_command_with_match_archives_calls_borg_with_match_archives_parameters():
+    flexmock(module.flags).should_receive('make_flags').and_return(())
+    flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
+        None, None, '1.2.3'
+    ).and_return(())
+    flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
+        'foo-*', None, '1.2.3',
+    ).and_return(('--match-archives', 'foo-*'))
+    flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+
+    command = module.make_rlist_command(
+        repository_path='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        rlist_arguments=flexmock(
+            archive=None,
+            paths=None,
+            json=False,
+            prefix=None,
+            match_archives='foo-*',
+            find_paths=None,
+            format=None,
+        ),
+    )
+
+    assert command == ('borg', 'list', '--match-archives', 'foo-*', 'repo')
+
+
 def test_list_repository_calls_borg_with_parameters():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER

+ 5 - 7
tests/unit/borg/test_transfer.py

@@ -124,10 +124,9 @@ def test_transfer_archives_with_archive_calls_borg_with_match_archives_flag():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
-    flexmock(module.flags).should_receive('make_flags').with_args(
-        'match-archives', 'archive'
+    flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
+        'archive', 'bar-{now}', '2.3.4'  # noqa: FS003
     ).and_return(('--match-archives', 'archive'))
-    flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
@@ -154,10 +153,9 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
-    flexmock(module.flags).should_receive('make_flags').with_args(
-        'match-archives', 'sh:foo*'
+    flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
+        'sh:foo*', 'bar-{now}', '2.3.4'  # noqa: FS003
     ).and_return(('--match-archives', 'sh:foo*'))
-    flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
@@ -304,7 +302,7 @@ def test_transfer_archives_with_progress_calls_borg_with_progress_flag():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
-    flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
+    flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--progress',))
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(