Переглянути джерело

Update borg action for Borg 2 support (#557).

Dan Helfman 2 роки тому
батько
коміт
30abd0e3de
3 змінених файлів з 99 додано та 31 видалено
  1. 23 16
      borgmatic/borg/borg.py
  2. 1 0
      borgmatic/commands/borgmatic.py
  3. 75 15
      tests/unit/borg/test_borg.py

+ 23 - 16
borgmatic/borg/borg.py

@@ -1,24 +1,29 @@
 import logging
 
-from borgmatic.borg import environment
-from borgmatic.borg.flags import make_flags
+from borgmatic.borg import environment, flags
 from borgmatic.execute import execute_command
 
 logger = logging.getLogger(__name__)
 
 
 REPOSITORYLESS_BORG_COMMANDS = {'serve', None}
-BORG_COMMANDS_WITH_SUBCOMMANDS = {'key', 'debug'}
-BORG_SUBCOMMANDS_WITHOUT_REPOSITORY = (('debug', 'info'), ('debug', 'convert-profile'))
+BORG_SUBCOMMANDS_WITH_SUBCOMMANDS = {'key', 'debug'}
+BORG_SUBCOMMANDS_WITHOUT_REPOSITORY = (('debug', 'info'), ('debug', 'convert-profile'), ())
 
 
 def run_arbitrary_borg(
-    repository, storage_config, options, archive=None, local_path='borg', remote_path=None
+    repository,
+    storage_config,
+    local_borg_version,
+    options,
+    archive=None,
+    local_path='borg',
+    remote_path=None,
 ):
     '''
-    Given a local or remote repository path, a storage config dict, a sequence of arbitrary
-    command-line Borg options, and an optional archive name, run an arbitrary Borg command on the
-    given repository/archive.
+    Given a local or remote repository path, a storage config dict, the local Borg version, a
+    sequence of arbitrary command-line Borg options, and an optional archive name, run an arbitrary
+    Borg command on the given repository/archive.
     '''
     lock_wait = storage_config.get('lock_wait', None)
 
@@ -26,7 +31,7 @@ def run_arbitrary_borg(
         options = options[1:] if options[0] == '--' else options
 
         # Borg commands like "key" have a sub-command ("export", etc.) that must follow it.
-        command_options_start_index = 2 if options[0] in BORG_COMMANDS_WITH_SUBCOMMANDS else 1
+        command_options_start_index = 2 if options[0] in BORG_SUBCOMMANDS_WITH_SUBCOMMANDS else 1
         borg_command = tuple(options[:command_options_start_index])
         command_options = tuple(options[command_options_start_index:])
     except IndexError:
@@ -34,21 +39,23 @@ def run_arbitrary_borg(
         command_options = ()
 
     if borg_command in BORG_SUBCOMMANDS_WITHOUT_REPOSITORY:
-        repository_archive = None
-    else:
-        repository_archive = (
-            '::'.join((repository, archive)) if repository and archive else repository
+        repository_archive_flags = ()
+    elif archive:
+        repository_archive_flags = flags.make_repository_archive_flags(
+            repository, archive, local_borg_version
         )
+    else:
+        repository_archive_flags = flags.make_repository_flags(repository, local_borg_version)
 
     full_command = (
         (local_path,)
         + borg_command
-        + ((repository_archive,) if borg_command and repository_archive else ())
+        + repository_archive_flags
         + command_options
         + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
         + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
-        + make_flags('remote-path', remote_path)
-        + make_flags('lock-wait', lock_wait)
+        + flags.make_flags('remote-path', remote_path)
+        + flags.make_flags('lock-wait', lock_wait)
     )
 
     return execute_command(

+ 1 - 0
borgmatic/commands/borgmatic.py

@@ -722,6 +722,7 @@ def run_actions(
             borg_borg.run_arbitrary_borg(
                 repository,
                 storage,
+                local_borg_version,
                 options=arguments['borg'].options,
                 archive=archive_name,
                 local_path=local_path,

+ 75 - 15
tests/unit/borg/test_borg.py

@@ -8,6 +8,8 @@ from ..test_verbosity import insert_logging_mock
 
 
 def test_run_arbitrary_borg_calls_borg_with_parameters():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo'),
@@ -17,11 +19,13 @@ def test_run_arbitrary_borg_calls_borg_with_parameters():
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['break-lock'],
+        repository='repo', storage_config={}, local_borg_version='1.2.3', options=['break-lock'],
     )
 
 
 def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--info'),
@@ -32,11 +36,13 @@ def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
     insert_logging_mock(logging.INFO)
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['break-lock'],
+        repository='repo', storage_config={}, local_borg_version='1.2.3', options=['break-lock'],
     )
 
 
 def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--debug', '--show-rc'),
@@ -47,12 +53,16 @@ def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
     insert_logging_mock(logging.DEBUG)
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['break-lock'],
+        repository='repo', storage_config={}, local_borg_version='1.2.3', options=['break-lock'],
     )
 
 
 def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters():
     storage_config = {'lock_wait': 5}
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(
+        ('--lock-wait', '5')
+    )
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--lock-wait', '5'),
@@ -62,12 +72,18 @@ def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters(
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config=storage_config, options=['break-lock'],
+        repository='repo',
+        storage_config=storage_config,
+        local_borg_version='1.2.3',
+        options=['break-lock'],
     )
 
 
 def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
-    storage_config = {}
+    flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
+        ('repo::archive',)
+    )
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo::archive'),
@@ -77,11 +93,17 @@ def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config=storage_config, options=['break-lock'], archive='archive',
+        repository='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        options=['break-lock'],
+        archive='archive',
     )
 
 
 def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg1', 'break-lock', 'repo'),
@@ -91,11 +113,19 @@ def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['break-lock'], local_path='borg1',
+        repository='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        options=['break-lock'],
+        local_path='borg1',
     )
 
 
 def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_parameters():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(
+        ('--remote-path', 'borg1')
+    ).and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--remote-path', 'borg1'),
@@ -105,11 +135,17 @@ def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_paramet
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['break-lock'], remote_path='borg1',
+        repository='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        options=['break-lock'],
+        remote_path='borg1',
     )
 
 
 def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo', '--progress'),
@@ -119,11 +155,16 @@ def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['list', '--progress'],
+        repository='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        options=['list', '--progress'],
     )
 
 
 def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo'),
@@ -133,22 +174,29 @@ def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['--', 'break-lock'],
+        repository='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        options=['--', 'break-lock'],
     )
 
 
 def test_run_arbitrary_borg_without_borg_specific_parameters_does_not_raise():
+    flexmock(module.flags).should_receive('make_repository_flags').never()
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg',), output_log_level=logging.WARNING, borg_local_path='borg', extra_environment=None,
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=[],
+        repository='repo', storage_config={}, local_borg_version='1.2.3', options=[],
     )
 
 
 def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'key', 'export', 'repo'),
@@ -158,11 +206,13 @@ def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['key', 'export'],
+        repository='repo', storage_config={}, local_borg_version='1.2.3', options=['key', 'export'],
     )
 
 
 def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository():
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'debug', 'dump-manifest', 'repo', 'path'),
@@ -172,11 +222,16 @@ def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository()
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['debug', 'dump-manifest', 'path'],
+        repository='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        options=['debug', 'dump-manifest', 'path'],
     )
 
 
 def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repository():
+    flexmock(module.flags).should_receive('make_repository_flags').never()
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'debug', 'info'),
@@ -186,11 +241,13 @@ def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repositor
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['debug', 'info'],
+        repository='repo', storage_config={}, local_borg_version='1.2.3', options=['debug', 'info'],
     )
 
 
 def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_borg_repository():
+    flexmock(module.flags).should_receive('make_repository_flags').never()
+    flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'debug', 'convert-profile', 'in', 'out'),
@@ -200,5 +257,8 @@ def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_bor
     )
 
     module.run_arbitrary_borg(
-        repository='repo', storage_config={}, options=['debug', 'convert-profile', 'in', 'out'],
+        repository='repo',
+        storage_config={},
+        local_borg_version='1.2.3',
+        options=['debug', 'convert-profile', 'in', 'out'],
     )