فهرست منبع

add support for `--info --json` (#83)

Thomas LÉVEIL 6 سال پیش
والد
کامیت
b714ffd48b

+ 1 - 1
AUTHORS

@@ -7,5 +7,5 @@ Michele Lazzeri: Custom archive names
 newtonne: Read encryption password from external file
 Robin `ypid` Schneider: Support additional options of Borg
 Scott Squires: Custom archive names
-Thomas LÉVEIL: Support for a keep_minutely prune option
+Thomas LÉVEIL: Support for a keep_minutely prune option. Support for the --json option
 Nick Whyte: Support prefix filtering for archive consistency checks

+ 7 - 3
borgmatic/borg/info.py

@@ -7,8 +7,9 @@ from borgmatic.verbosity import VERBOSITY_SOME, VERBOSITY_LOTS
 logger = logging.getLogger(__name__)
 
 
-def display_archives_info(verbosity, repository, storage_config, local_path='borg',
-                          remote_path=None):
+def display_archives_info(
+        verbosity, repository, storage_config, local_path='borg', remote_path=None, json=False
+):
     '''
     Given a verbosity flag, a local or remote repository path, and a storage config dict,
     display summary information for Borg archives in the repository.
@@ -19,6 +20,7 @@ def display_archives_info(verbosity, repository, storage_config, local_path='bor
         (local_path, 'info', repository)
         + (('--remote-path', remote_path) if remote_path else ())
         + (('--lock-wait', str(lock_wait)) if lock_wait else ())
+        + (('--json',) if json else ())
         + {
             VERBOSITY_SOME: ('--info',),
             VERBOSITY_LOTS: ('--debug',),
@@ -26,4 +28,6 @@ def display_archives_info(verbosity, repository, storage_config, local_path='bor
     )
 
     logger.debug(' '.join(full_command))
-    subprocess.check_call(full_command)
+
+    output = subprocess.check_output(full_command)
+    return output.decode() if output is not None else None

+ 3 - 1
borgmatic/borg/list.py

@@ -7,7 +7,9 @@ from borgmatic.verbosity import VERBOSITY_SOME, VERBOSITY_LOTS
 logger = logging.getLogger(__name__)
 
 
-def list_archives(verbosity, repository, storage_config, local_path='borg', remote_path=None, json=False):
+def list_archives(
+        verbosity, repository, storage_config, local_path='borg', remote_path=None, json=False
+):
     '''
     Given a verbosity flag, a local or remote repository path, and a storage config dict,
     list Borg archives in the repository.

+ 13 - 3
borgmatic/commands/borgmatic.py

@@ -97,8 +97,13 @@ def parse_arguments(*arguments):
 
     args = parser.parse_args(arguments)
 
-    if args.json and not args.list:
-        raise ValueError('The --json option can only be used with the --list option')
+    if args.json and not (args.list or args.info):
+        raise ValueError('The --json option can only be used with the --list or --info options')
+
+    if args.json and args.list and args.info:
+        raise ValueError(
+            'With the --json option, options --list and --info cannot be used together'
+        )
 
     # If any of the action flags are explicitly requested, leave them as-is. Otherwise, assume
     # defaults: Mutate the given arguments to enable the default actions.
@@ -205,13 +210,18 @@ def _run_commands_on_repository(
             sys.stdout.write(output)
     if args.info:
         logger.info('{}: Displaying summary info for archives'.format(repository))
-        borg_info.display_archives_info(
+        output = borg_info.display_archives_info(
             args.verbosity,
             repository,
             storage,
             local_path=local_path,
             remote_path=remote_path,
+            json=args.json,
         )
+        if args.json:
+            json_results.append(json.loads(output))
+        else:
+            sys.stdout.write(output)
 
 
 def main():  # pragma: no cover

+ 11 - 1
borgmatic/tests/integration/commands/test_borgmatic.py

@@ -90,6 +90,16 @@ def test_parse_arguments_with_invalid_arguments_exits():
         module.parse_arguments('--posix-me-harder')
 
 
-def test_parse_arguments_with_json_flag_but_no_list_flag_raises_value_error():
+def test_parse_arguments_with_json_flag_with_list_or_info_flag_does_not_raise_any_error():
+    module.parse_arguments('--list', '--json')
+    module.parse_arguments('--info', '--json')
+
+
+def test_parse_arguments_with_json_flag_but_no_list_or_info_flag_raises_value_error():
     with pytest.raises(ValueError):
         module.parse_arguments('--json')
+
+
+def test_parse_arguments_with_json_flag_and_both_list_and_info_flag_raises_value_error():
+    with pytest.raises(ValueError):
+        module.parse_arguments('--list', '--info', '--json')

+ 12 - 1
borgmatic/tests/unit/borg/test_info.py

@@ -8,7 +8,7 @@ from borgmatic.verbosity import VERBOSITY_SOME, VERBOSITY_LOTS
 
 def insert_subprocess_mock(check_call_command, **kwargs):
     subprocess = flexmock(module.subprocess)
-    subprocess.should_receive('check_call').with_args(check_call_command, **kwargs).once()
+    subprocess.should_receive('check_output').with_args(check_call_command, **kwargs).once()
 
 
 INFO_COMMAND = ('borg', 'info', 'repo')
@@ -44,6 +44,17 @@ def test_display_archives_info_with_verbosity_lots_calls_borg_with_debug_paramet
     )
 
 
+def test_display_archives_info_with_json_calls_borg_with_json_parameter():
+    insert_subprocess_mock(INFO_COMMAND + ('--json',))
+
+    module.display_archives_info(
+        verbosity=None,
+        repository='repo',
+        storage_config={},
+        json=True,
+    )
+
+
 def test_display_archives_info_with_local_path_calls_borg_via_local_path():
     insert_subprocess_mock(('borg1',) + INFO_COMMAND[1:])