diff --git a/dvc/command/diff.py b/dvc/command/diff.py index 4a784b705..c48905fe5 100644 --- a/dvc/command/diff.py +++ b/dvc/command/diff.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import dvc.logger as logger from dvc.exceptions import DvcException from dvc.command.base import CmdBase +from dvc.utils.collections import compact class CmdDiff(CmdBase): @@ -16,20 +17,18 @@ class CmdDiff(CmdBase): ) self._show(msg) except DvcException: - msg = "failed to get diff " - if self.args.target: - msg += self.args.target + " " - if self.args.a_ref: - msg += self.args.a_ref + " " - if self.args.b_ref: - msg += self.args.b_ref + " " + msg = "failed to get 'diff " + msg += " ".join( + compact([self.args.target, self.args.a_ref, self.args.b_ref]) + ) + msg += "'" logger.error(msg) return 0 def add_parser(subparsers, parent_parser): description = ( - "show diff of a data file or a directory that " + "Show diff of a data file or a directory that " "is under DVC control. Some basic statistics " "summary, how many files were deleted/changed." ) @@ -43,7 +42,8 @@ def add_parser(subparsers, parent_parser): default=None, help=( "Source path to a data file or directory. Default None," - "if None shows the diff between all DVC tracked files/directories" + "If not specified, compares all files and directories " + "that are under DVC control in the current working space." ), ) diff_parser.add_argument( diff --git a/dvc/repo/diff.py b/dvc/repo/diff.py index 7b1af6bd6..cd34a8cba 100644 --- a/dvc/repo/diff.py +++ b/dvc/repo/diff.py @@ -8,7 +8,15 @@ import inflect from dvc.scm.base import FileNotInCommitError -def _extract_output(self, output): +def _extract_dir(self, output): + """Extract the content of dvc tree file + Args: + self(object) - Repo class instance + output(object) - OutputLOCAL class instance + Returns: + dict - dictionary with keys - paths to file in .dvc/cache + values -checksums for that files + """ lst = output.dir_cache return {i["relpath"]: i["md5"] for i in lst} @@ -81,12 +89,12 @@ def _diff_dir(self, target, diff_dct): msg += "-{} with md5 {}\n".format( target, diff_dct["a_output"].checksum ) - a_entries = _extract_output(self, diff_dct["a_output"]) + a_entries = _extract_dir(self, diff_dct["a_output"]) if not diff_dct["deleted_file"]: msg += "+{} with md5 {}\n".format( target, diff_dct["b_output"].checksum ) - b_entries = _extract_output(self, diff_dct["b_output"]) + b_entries = _extract_dir(self, diff_dct["b_output"]) msg += "\n" result = _get_tree_changes(self, a_entries, b_entries) msg += f"{result['ident']} " + engine.plural("file", result["ident"]) @@ -139,9 +147,9 @@ def _diff_file(self, target, diff_dct): def _diff_royal(self, target, diff_dct): - msg = "diff for " + target + "\n" + msg = "diff for '" + target + "'\n" if diff_dct["is_dir"]: - return _diff_dir(self, target, diff_dct) + return msg + _diff_dir(self, target, diff_dct) return msg + _diff_file(self, target, diff_dct) diff --git a/dvc/scm/git/__init__.py b/dvc/scm/git/__init__.py index 39b153eb2..f850aae68 100644 --- a/dvc/scm/git/__init__.py +++ b/dvc/scm/git/__init__.py @@ -236,15 +236,14 @@ class Git(Base): def get_tree(self, rev): return GitTree(self.git, rev) - def _get_diff_trees(self, a_ref, **kwargs): + def _get_diff_trees(self, a_ref, b_ref): from gitdb.exc import BadObject, BadName trees = {"a_tree": None, "b_tree": None} commits = [] try: - if "b_ref" in kwargs and kwargs["b_ref"] is not None: - b_ref = kwargs["b_ref"] + if b_ref is not None: a_commit = self.git.commit(a_ref) b_commit = self.git.commit(b_ref) commits.append(str(a_commit)) @@ -263,7 +262,7 @@ class Git(Base): raise SCMError("git problem", cause=e) return trees, commits - def get_diff_trees(self, a_ref, **kwargs): + def get_diff_trees(self, a_ref, b_ref=None): """Method for getting two repo trees between two git tag commits returns the dvc hash names of changed file/directory @@ -275,7 +274,7 @@ class Git(Base): dict - dictionary with keys: (a_tree, b_tree, a_ref, b_ref, equal) """ diff_dct = {"equal": False} - trees, commit_refs = self._get_diff_trees(a_ref, **kwargs) + trees, commit_refs = self._get_diff_trees(a_ref, b_ref) diff_dct["a_ref"] = commit_refs[0] diff_dct["b_ref"] = commit_refs[1] if commit_refs[0] == commit_refs[1]: diff --git a/dvc/utils/collections.py b/dvc/utils/collections.py new file mode 100644 index 000000000..46d8c9d44 --- /dev/null +++ b/dvc/utils/collections.py @@ -0,0 +1,6 @@ +from __future__ import unicode_literals + + +# just simple check for Nones and emtpy strings +def compact(args): + return list(filter(bool, args)) diff --git a/setup.py b/setup.py index 07fe236ba..e01c045d5 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,8 @@ install_requires = [ "distro>=1.3.0", "appdirs>=1.4.3", "treelib>=1.5.5", + "inflect>=2.1.0", + "humanize>=0.5.1", ] # Extra dependencies for remote integrations diff --git a/tests/test_diff.py b/tests/test_diff.py index 8e823b815..f1ce66993 100644 --- a/tests/test_diff.py +++ b/tests/test_diff.py @@ -35,7 +35,7 @@ class TestDiffRepo(TestDiff): new_ref = self.git.head.commit msg = self.dvc.diff(self.new_file, a_ref=self.a_ref) test_msg = "dvc diff from {} to {}\n\n".format(new_ref, self.a_ref) - test_msg += "diff for {}\n".format(self.new_file) + test_msg += "diff for '{}'\n".format(self.new_file) test_msg += "-new_file with md5 25fa8325e4e0eb8180445e42558e60bd\n" test_msg += "deleted file with size -8 Bytes" self.assertEqual(test_msg, msg) @@ -77,6 +77,7 @@ class TestDiffDirRepo(TestDiffDir): msg = self.dvc.diff(self.DATA_DIR, a_ref=self.a_ref) test_msg = "dvc diff from ".format(self.DATA_DIR) test_msg += "{} to {}\n\n".format(new_ref, self.a_ref) + test_msg += "diff for '{}'\n".format(self.DATA_DIR) test_msg += "-data_dir with md5 d5782f3072167ad3a53ee80b92b30718.dir\n" test_msg += ( "+data_dir with md5 bff5a787d16460f32e9f2e62b183b1cc.dir\n\n"