Skip to content
Snippets Groups Projects
Commit c601f2d2 authored by Chris Lamb's avatar Chris Lamb :eyes:
Browse files

Add a machine-readable JSON output format. (Closes: #850791)


Signed-off-by: Chris Lamb's avatarChris Lamb <lamby@debian.org>
parent fabb7bca
No related branches found
No related tags found
No related merge requests found
......@@ -93,6 +93,8 @@ def create_parser():
'"disable" to disable JavaScript. When omitted '
'diffoscope will try to create a symlink to a system '
'installation. Known locations: %s' % ', '.join(JQUERY_SYSTEM_LOCATIONS))
group1.add_argument('--json', metavar='OUTPUT_FILE', dest='json_output',
help='Write JSON text output to given file (use - for stdout)')
group1.add_argument('--markdown', metavar='OUTPUT_FILE', dest='markdown_output',
help='Write Markdown text output to given file (use - for stdout)')
group1.add_argument('--restructured-text', metavar='OUTPUT_FILE',
......
# -*- coding: utf-8 -*-
#
# diffoscope: in-depth comparison of files, archives, and directories
#
# Copyright © 2017 Chris Lamb <lamby@debian.org>
#
# diffoscope is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# diffoscope is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
import json
from .base import Presenter
class JSONPresenter(Presenter):
def __init__(self, print_func):
self.root = []
self.current = self.root
self.print_func = print_func
super().__init__()
def visit(self, difference):
super().visit(difference)
if self.depth == 0:
self.print_func(json.dumps(self.root[0], indent=2, sort_keys=True))
def visit_difference(self, difference):
self.current.append({
'source1': difference.source1,
'source2': difference.source2,
'comments': [x for x in difference.comments],
'differences': [],
'unified_diff': difference.unified_diff,
})
self.current = self.current[-1]['differences']
......@@ -25,6 +25,7 @@ import contextlib
from ..profiling import profile
from .text import TextPresenter
from .json import JSONPresenter
from .html import output_html, output_html_directory
from .markdown import MarkdownTextPresenter
from .restructuredtext import RestructuredTextPresenter
......@@ -49,6 +50,10 @@ def output_all(difference, parsed_args, has_differences):
'fn': html,
'target': parsed_args.html_output,
},
'json': {
'klass': JSONPresenter,
'target': parsed_args.json_output,
},
'markdown': {
'klass': MarkdownTextPresenter,
'target': parsed_args.markdown_output,
......
{
"comments": [],
"differences": [
{
"comments": [],
"differences": [
{
"comments": [],
"differences": [
{
"comments": [
"symlink"
],
"differences": [],
"source1": "dir/link",
"source2": "dir/link",
"unified_diff": "@@ -1 +1 @@\n-destination: broken\n+destination: really-broken\n"
}
],
"source1": "dir/text",
"source2": "dir/text",
"unified_diff": "@@ -1,6 +1,12 @@\n+A common form of lorem ipsum reads:\n+\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis\n nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu\n fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in\n culpa qui officia deserunt mollit anim id est laborum.\n+\n+\"Lorem ipsum\" text is derived from sections 1.10.32--3 of Cicero's De finibus\n+bonorum et malorum (On the Ends of Goods and Evils, or alternatively [About]\n+The Purposes of Good and Evil).\n"
}
],
"source1": "file list",
"source2": "file list",
"unified_diff": "@@ -1,4 +1,4 @@\n-drwxr-xr-x 0 lunar (1000) lunar (1000) 0 2015-06-29 15:49:09.000000 dir/\n--rw-r--r-- 0 lunar (1000) lunar (1000) 446 2015-06-29 15:49:09.000000 dir/text\n-crw-r--r-- 0 root (0) root (0) 1, 3 2015-06-29 15:49:09.000000 dir/null\n-lrwxrwxrwx 0 lunar (1000) lunar (1000) 0 2015-06-29 15:49:09.000000 dir/link -> broken\n+drwxr-xr-x 0 lunar (1000) lunar (1000) 0 2015-06-29 15:49:41.000000 dir/\n+-rw-r--r-- 0 lunar (1000) lunar (1000) 671 2015-06-29 15:49:41.000000 dir/text\n+crw-r--r-- 0 root (0) root (0) 1, 3 2015-06-29 15:49:41.000000 dir/null\n+lrwxrwxrwx 0 lunar (1000) lunar (1000) 0 2015-06-29 15:49:41.000000 dir/link -> really-broken\n"
}
],
"source1": "test1.tar",
"source2": "test2.tar",
"unified_diff": null
}
......@@ -96,6 +96,14 @@ def test_restructuredtext(capsys):
assert out == data('output.rst')
def test_json(capsys):
out = run(capsys, '--json', '-')
with open('tests/data/output.json', 'w') as f:
f.write(out)
assert out == data('output.json')
def test_no_report_option(capsys):
out = run(capsys)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment