浏览代码

Add "--repository" flag to common actions (where it makes sense) (#652).

Reviewed-on: https://projects.torsion.org/borgmatic-collective/borgmatic/pulls/652
Dan Helfman 2 年之前
父节点
当前提交
7a784b8eba

+ 6 - 0
borgmatic/actions/check.py

@@ -1,6 +1,7 @@
 import logging
 
 import borgmatic.borg.check
+import borgmatic.config.validate
 import borgmatic.hooks.command
 
 logger = logging.getLogger(__name__)
@@ -23,6 +24,11 @@ def run_check(
     '''
     Run the "check" action for the given repository.
     '''
+    if check_arguments.repository and not borgmatic.config.validate.repositories_match(
+        repository, check_arguments.repository
+    ):
+        return
+
     borgmatic.hooks.command.execute_hook(
         hooks.get('before_check'),
         hooks.get('umask'),

+ 6 - 0
borgmatic/actions/compact.py

@@ -2,6 +2,7 @@ import logging
 
 import borgmatic.borg.compact
 import borgmatic.borg.feature
+import borgmatic.config.validate
 import borgmatic.hooks.command
 
 logger = logging.getLogger(__name__)
@@ -24,6 +25,11 @@ def run_compact(
     '''
     Run the "compact" action for the given repository.
     '''
+    if compact_arguments.repository and not borgmatic.config.validate.repositories_match(
+        repository, compact_arguments.repository
+    ):
+        return
+
     borgmatic.hooks.command.execute_hook(
         hooks.get('before_compact'),
         hooks.get('umask'),

+ 6 - 0
borgmatic/actions/create.py

@@ -2,6 +2,7 @@ import json
 import logging
 
 import borgmatic.borg.create
+import borgmatic.config.validate
 import borgmatic.hooks.command
 import borgmatic.hooks.dispatch
 import borgmatic.hooks.dump
@@ -28,6 +29,11 @@ def run_create(
 
     If create_arguments.json is True, yield the JSON output from creating the archive.
     '''
+    if create_arguments.repository and not borgmatic.config.validate.repositories_match(
+        repository, create_arguments.repository
+    ):
+        return
+
     borgmatic.hooks.command.execute_hook(
         hooks.get('before_backup'),
         hooks.get('umask'),

+ 6 - 0
borgmatic/actions/prune.py

@@ -1,6 +1,7 @@
 import logging
 
 import borgmatic.borg.prune
+import borgmatic.config.validate
 import borgmatic.hooks.command
 
 logger = logging.getLogger(__name__)
@@ -23,6 +24,11 @@ def run_prune(
     '''
     Run the "prune" action for the given repository.
     '''
+    if prune_arguments.repository and not borgmatic.config.validate.repositories_match(
+        repository, prune_arguments.repository
+    ):
+        return
+
     borgmatic.hooks.command.execute_hook(
         hooks.get('before_prune'),
         hooks.get('umask'),

+ 16 - 0
borgmatic/commands/arguments.py

@@ -333,6 +333,10 @@ def make_parsers():
         add_help=False,
     )
     prune_group = prune_parser.add_argument_group('prune arguments')
+    prune_group.add_argument(
+        '--repository',
+        help='Path of specific existing repository to prune (must be already specified in a borgmatic configuration file)',
+    )
     prune_group.add_argument(
         '--stats',
         dest='stats',
@@ -353,6 +357,10 @@ def make_parsers():
         add_help=False,
     )
     compact_group = compact_parser.add_argument_group('compact arguments')
+    compact_group.add_argument(
+        '--repository',
+        help='Path of specific existing repository to compact (must be already specified in a borgmatic configuration file)',
+    )
     compact_group.add_argument(
         '--progress',
         dest='progress',
@@ -385,6 +393,10 @@ def make_parsers():
         add_help=False,
     )
     create_group = create_parser.add_argument_group('create arguments')
+    create_group.add_argument(
+        '--repository',
+        help='Path of specific existing repository to backup to (must be already specified in a borgmatic configuration file)',
+    )
     create_group.add_argument(
         '--progress',
         dest='progress',
@@ -415,6 +427,10 @@ def make_parsers():
         add_help=False,
     )
     check_group = check_parser.add_argument_group('check arguments')
+    check_group.add_argument(
+        '--repository',
+        help='Path of specific existing repository to check (must be already specified in a borgmatic configuration file)',
+    )
     check_group.add_argument(
         '--progress',
         dest='progress',

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

@@ -254,13 +254,6 @@ def test_parse_arguments_allows_init_and_create():
     module.parse_arguments('--config', 'myconfig', 'init', '--encryption', 'repokey', 'create')
 
 
-def test_parse_arguments_disallows_repository_unless_action_consumes_it():
-    flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
-
-    with pytest.raises(SystemExit):
-        module.parse_arguments('--config', 'myconfig', '--repository', 'test.borg')
-
-
 def test_parse_arguments_allows_repository_with_extract():
     flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
 

+ 66 - 3
tests/unit/actions/test_check.py

@@ -3,15 +3,78 @@ from flexmock import flexmock
 from borgmatic.actions import check as module
 
 
-def test_run_check_calls_hooks():
+def test_run_check_calls_hooks_for_configured_repository():
     flexmock(module.logger).answer = lambda message: None
     flexmock(module.borgmatic.config.checks).should_receive(
         'repository_enabled_for_checks'
     ).and_return(True)
-    flexmock(module.borgmatic.borg.check).should_receive('check_archives')
+    flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()
+    flexmock(module.borgmatic.borg.check).should_receive('check_archives').once()
     flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
     check_arguments = flexmock(
-        progress=flexmock(), repair=flexmock(), only=flexmock(), force=flexmock()
+        repository=None, progress=flexmock(), repair=flexmock(), only=flexmock(), force=flexmock(),
+    )
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    module.run_check(
+        config_filename='test.yaml',
+        repository='repo',
+        location={'repositories': ['repo']},
+        storage={},
+        consistency={},
+        hooks={},
+        hook_context={},
+        local_borg_version=None,
+        check_arguments=check_arguments,
+        global_arguments=global_arguments,
+        local_path=None,
+        remote_path=None,
+    )
+
+
+def test_run_check_runs_with_select_repository():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(True)
+    flexmock(module.borgmatic.borg.check).should_receive('check_archives').once()
+    check_arguments = flexmock(
+        repository=flexmock(),
+        progress=flexmock(),
+        repair=flexmock(),
+        only=flexmock(),
+        force=flexmock(),
+    )
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    module.run_check(
+        config_filename='test.yaml',
+        repository=flexmock(),
+        location={'repositories': ['repo']},
+        storage={},
+        consistency={},
+        hooks={},
+        hook_context={},
+        local_borg_version=None,
+        check_arguments=check_arguments,
+        global_arguments=global_arguments,
+        local_path=None,
+        remote_path=None,
+    )
+
+
+def test_run_check_bails_if_repository_does_not_match():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(False)
+    flexmock(module.borgmatic.borg.check).should_receive('check_archives').never()
+    check_arguments = flexmock(
+        repository=flexmock(),
+        progress=flexmock(),
+        repair=flexmock(),
+        only=flexmock(),
+        force=flexmock(),
     )
     global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
 

+ 60 - 3
tests/unit/actions/test_compact.py

@@ -3,13 +3,70 @@ from flexmock import flexmock
 from borgmatic.actions import compact as module
 
 
-def test_compact_actions_calls_hooks():
+def test_compact_actions_calls_hooks_for_configured_repository():
     flexmock(module.logger).answer = lambda message: None
     flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.borg.compact).should_receive('compact_segments')
+    flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()
+    flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').once()
     flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
     compact_arguments = flexmock(
-        progress=flexmock(), cleanup_commits=flexmock(), threshold=flexmock()
+        repository=None, progress=flexmock(), cleanup_commits=flexmock(), threshold=flexmock()
+    )
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    module.run_compact(
+        config_filename='test.yaml',
+        repository='repo',
+        storage={},
+        retention={},
+        hooks={},
+        hook_context={},
+        local_borg_version=None,
+        compact_arguments=compact_arguments,
+        global_arguments=global_arguments,
+        dry_run_label='',
+        local_path=None,
+        remote_path=None,
+    )
+
+
+def test_compact_runs_with_select_repository():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(True)
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
+    flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').once()
+    compact_arguments = flexmock(
+        repository=flexmock(), progress=flexmock(), cleanup_commits=flexmock(), threshold=flexmock()
+    )
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    module.run_compact(
+        config_filename='test.yaml',
+        repository='repo',
+        storage={},
+        retention={},
+        hooks={},
+        hook_context={},
+        local_borg_version=None,
+        compact_arguments=compact_arguments,
+        global_arguments=global_arguments,
+        dry_run_label='',
+        local_path=None,
+        remote_path=None,
+    )
+
+
+def test_compact_bails_if_repository_does_not_match():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(False)
+    flexmock(module.borgmatic.borg.compact).should_receive('compact_segments').never()
+    compact_arguments = flexmock(
+        repository=flexmock(), progress=flexmock(), cleanup_commits=flexmock(), threshold=flexmock()
     )
     global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
 

+ 74 - 3
tests/unit/actions/test_create.py

@@ -3,16 +3,87 @@ from flexmock import flexmock
 from borgmatic.actions import create as module
 
 
-def test_run_create_executes_and_calls_hooks():
+def test_run_create_executes_and_calls_hooks_for_configured_repository():
     flexmock(module.logger).answer = lambda message: None
-    flexmock(module.borgmatic.borg.create).should_receive('create_archive')
+    flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()
+    flexmock(module.borgmatic.borg.create).should_receive('create_archive').once()
     flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
     flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return({})
     flexmock(module.borgmatic.hooks.dispatch).should_receive(
         'call_hooks_even_if_unconfigured'
     ).and_return({})
     create_arguments = flexmock(
-        progress=flexmock(), stats=flexmock(), json=flexmock(), list_files=flexmock()
+        repository=None,
+        progress=flexmock(),
+        stats=flexmock(),
+        json=flexmock(),
+        list_files=flexmock(),
+    )
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    list(
+        module.run_create(
+            config_filename='test.yaml',
+            repository='repo',
+            location={},
+            storage={},
+            hooks={},
+            hook_context={},
+            local_borg_version=None,
+            create_arguments=create_arguments,
+            global_arguments=global_arguments,
+            dry_run_label='',
+            local_path=None,
+            remote_path=None,
+        )
+    )
+
+
+def test_run_create_runs_with_select_repository():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(True)
+    flexmock(module.borgmatic.borg.create).should_receive('create_archive').once()
+    create_arguments = flexmock(
+        repository=flexmock(),
+        progress=flexmock(),
+        stats=flexmock(),
+        json=flexmock(),
+        list_files=flexmock(),
+    )
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    list(
+        module.run_create(
+            config_filename='test.yaml',
+            repository='repo',
+            location={},
+            storage={},
+            hooks={},
+            hook_context={},
+            local_borg_version=None,
+            create_arguments=create_arguments,
+            global_arguments=global_arguments,
+            dry_run_label='',
+            local_path=None,
+            remote_path=None,
+        )
+    )
+
+
+def test_run_create_bails_if_repository_does_not_match():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(False)
+    flexmock(module.borgmatic.borg.create).should_receive('create_archive').never()
+    create_arguments = flexmock(
+        repository=flexmock(),
+        progress=flexmock(),
+        stats=flexmock(),
+        json=flexmock(),
+        list_files=flexmock(),
     )
     global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
 

+ 54 - 3
tests/unit/actions/test_prune.py

@@ -3,11 +3,62 @@ from flexmock import flexmock
 from borgmatic.actions import prune as module
 
 
-def test_run_prune_calls_hooks():
+def test_run_prune_calls_hooks_of_configured_repository():
     flexmock(module.logger).answer = lambda message: None
-    flexmock(module.borgmatic.borg.prune).should_receive('prune_archives')
+    flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()
+    flexmock(module.borgmatic.borg.prune).should_receive('prune_archives').once()
     flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
-    prune_arguments = flexmock(stats=flexmock(), list_archives=flexmock())
+    prune_arguments = flexmock(repository=None, stats=flexmock(), list_archives=flexmock())
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    module.run_prune(
+        config_filename='test.yaml',
+        repository='repo',
+        storage={},
+        retention={},
+        hooks={},
+        hook_context={},
+        local_borg_version=None,
+        prune_arguments=prune_arguments,
+        global_arguments=global_arguments,
+        dry_run_label='',
+        local_path=None,
+        remote_path=None,
+    )
+
+
+def test_run_prune_runs_with_select_repository():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(True)
+    flexmock(module.borgmatic.borg.prune).should_receive('prune_archives').once()
+    prune_arguments = flexmock(repository=flexmock(), stats=flexmock(), list_archives=flexmock())
+    global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
+
+    module.run_prune(
+        config_filename='test.yaml',
+        repository='repo',
+        storage={},
+        retention={},
+        hooks={},
+        hook_context={},
+        local_borg_version=None,
+        prune_arguments=prune_arguments,
+        global_arguments=global_arguments,
+        dry_run_label='',
+        local_path=None,
+        remote_path=None,
+    )
+
+
+def test_run_prune_bails_if_repository_does_not_match():
+    flexmock(module.logger).answer = lambda message: None
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'repositories_match'
+    ).once().and_return(False)
+    flexmock(module.borgmatic.borg.prune).should_receive('prune_archives').never()
+    prune_arguments = flexmock(repository=flexmock(), stats=flexmock(), list_archives=flexmock())
     global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
 
     module.run_prune(