diff --git a/dvc/command/diff.py b/dvc/command/diff.py index c754c1c586..53f4398399 100644 --- a/dvc/command/diff.py +++ b/dvc/command/diff.py @@ -97,20 +97,15 @@ def run(self): try: diff = self.repo.diff(self.args.a_rev, self.args.b_rev) - if not any(diff.values()): - return 0 - if not self.args.show_hash: for _, entries in diff.items(): for entry in entries: del entry["hash"] if self.args.show_json: - res = json.dumps(diff) - else: - res = self._format(diff) - - logger.info(res) + logger.info(json.dumps(diff)) + elif diff: + logger.info(self._format(diff)) except DvcException: logger.exception("failed to get diff") diff --git a/dvc/repo/diff.py b/dvc/repo/diff.py index 5a83ed8008..bdc886c542 100644 --- a/dvc/repo/diff.py +++ b/dvc/repo/diff.py @@ -71,7 +71,7 @@ def _exists(output): deleted = sorted(set(old) - set(new)) modified = sorted(set(old) & set(new)) - return { + ret = { "added": [{"path": path, "hash": new[path]} for path in added], "deleted": [{"path": path, "hash": old[path]} for path in deleted], "modified": [ @@ -80,3 +80,5 @@ def _exists(output): if old[path] != new[path] ], } + + return ret if any(ret.values()) else {} diff --git a/tests/func/test_diff.py b/tests/func/test_diff.py index 707b4936bd..69a06eb32c 100644 --- a/tests/func/test_diff.py +++ b/tests/func/test_diff.py @@ -209,3 +209,8 @@ def test_diff_dirty(tmp_dir, scm, dvc): } ], } + + +def test_no_changes(tmp_dir, scm, dvc): + tmp_dir.dvc_gen("file", "first", commit="add a file") + assert dvc.diff() == {} diff --git a/tests/unit/command/test_diff.py b/tests/unit/command/test_diff.py index c70feac7e9..72358dcff3 100644 --- a/tests/unit/command/test_diff.py +++ b/tests/unit/command/test_diff.py @@ -1,5 +1,6 @@ import collections import os +import logging from dvc.cli import parse_args @@ -86,3 +87,26 @@ def test_show_json_and_hash(mocker, caplog): assert '"added": [{"path": "file", "hash": "00000000"}]' in caplog.text assert '"deleted": []' in caplog.text assert '"modified": []' in caplog.text + + +def test_no_changes(mocker, caplog): + args = parse_args(["diff", "--show-json"]) + cmd = args.func(args) + mocker.patch("dvc.repo.Repo.diff", return_value={}) + + def info(): + return [ + msg + for name, level, msg in caplog.record_tuples + if name.startswith("dvc") and level == logging.INFO + ] + + assert 0 == cmd.run() + assert ["{}"] == info() + + caplog.clear() + + args = parse_args(["diff"]) + cmd = args.func(args) + assert 0 == cmd.run() + assert not info() diff --git a/tests/unit/test_plot.py b/tests/unit/test_plot.py index fcf2ce30b1..2cdf0383d5 100644 --- a/tests/unit/test_plot.py +++ b/tests/unit/test_plot.py @@ -1,3 +1,5 @@ +from collections import OrderedDict + import pytest from dvc.repo.plot.data import _apply_path, _lists, _find_data @@ -26,7 +28,7 @@ def test_parse_json(path, expected_result): ({}, []), ({"x": ["a", "b", "c"]}, [["a", "b", "c"]]), ( - {"x": {"y": ["a", "b"]}, "z": {"w": ["c", "d"]}}, + OrderedDict([("x", {"y": ["a", "b"]}), ("z", {"w": ["c", "d"]})]), [["a", "b"], ["c", "d"]], ), ],