Skip to content

Commit

Permalink
diff: add support for specifying a target
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr. Outis committed Jan 25, 2020
1 parent 576a276 commit 07abd1b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 13 deletions.
7 changes: 5 additions & 2 deletions dvc/repo/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def diff(self, a_ref="HEAD", b_ref=None, *, target=None):
By default, it compares the working tree with the last commit's tree.
When a `target` path is given, it only shows that file's comparison.
It will silently fail when `target` is not found in any of the trees.
This implementation differs from `git diff`, since DVC doesn't have
This implementation differs from `git diff` since DVC doesn't have
the concept of `index`, `dvc diff` would be the same as `dvc diff HEAD`.
"""
outs = {}
Expand All @@ -52,11 +53,13 @@ def diff(self, a_ref="HEAD", b_ref=None, *, target=None):
for stage in self.stages
for out in stage.outs
)

old = outs[a_ref]
new = outs[b_ref or "working tree"]
delta = old ^ new

if target:
delta = set(x for x in delta if x.filename == target)

if not delta:
return

Expand Down
50 changes: 39 additions & 11 deletions tests/func/test_diff.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import pytest
import hashlib


def _checksum(text):
return hashlib.md5(bytes(text, "utf-8")).hexdigest()


def test_no_scm(tmp_dir, dvc):
Expand All @@ -13,7 +18,7 @@ def test_added(tmp_dir, scm, dvc):
result = {
"file": {
"old": {},
"new": {"checksum": "1cb251ec0d568de6a929b520c4aed8d1", "size": 4},
"new": {"checksum": _checksum("text"), "size": 4},
"diff": {"status": "added", "size": 4},
}
}
Expand All @@ -27,7 +32,7 @@ def test_deleted(tmp_dir, scm, dvc):

result = {
"file": {
"old": {"checksum": "1cb251ec0d568de6a929b520c4aed8d1", "size": 4},
"old": {"checksum": _checksum("text"), "size": 4},
"new": {},
"diff": {"status": "deleted", "size": 4},
}
Expand All @@ -42,8 +47,8 @@ def test_modified(tmp_dir, scm, dvc):

result = {
"file": {
"old": {"checksum": "8b04d5e3775d298e78455efc5ca404d5", "size": 6},
"new": {"checksum": "a9f0e61a137d86aa9db53465e0801612", "size": 6},
"old": {"checksum": _checksum("first"), "size": 6},
"new": {"checksum": _checksum("second"), "size": 6},
"diff": {"status": "modified", "size": 0},
}
}
Expand All @@ -56,10 +61,27 @@ def test_refs(tmp_dir, scm, dvc):
tmp_dir.dvc_gen("file", "second", commit="second version")
tmp_dir.dvc_gen("file", "third", commit="third version")

# dvc.diff("HEAD~1") --> (third, second)
# dvc.diff("HEAD~1", "HEAD~2") --> (second, first)
# dvc.diff("missing") --> error
pytest.skip("TODO: define output structure")
HEAD_2 = _checksum("first")
HEAD_1 = _checksum("second")
HEAD = _checksum("third")

assert dvc.diff("HEAD~1") == {
"file": {
"old": {"checksum": HEAD_1, "size": 5},
"new": {"checksum": HEAD, "size": 5},
"diff": {"status": "modified", "size": 0},
}
}

assert dvc.diff("HEAD~1", "HEAD~2") == {
"file": {
"old": {"checksum": HEAD_2, "size": 5},
"new": {"checksum": HEAD_1, "size": 5},
"diff": {"status": "modified", "size": 0},
}
}

pytest.skip('TODO: test dvc.diff("missing")')


def test_target(tmp_dir, scm, dvc):
Expand All @@ -73,9 +95,15 @@ def test_target(tmp_dir, scm, dvc):
scm.add(["foo.dvc", "bar.dvc"])
scm.commit("uppercase")

# dvc.diff("HEAD~1", target="foo")
# dvc.diff("HEAD~1", target="missing") --> error
pytest.skip("TODO: define output structure")
assert dvc.diff("HEAD~1", target="foo") == {
"foo": {
"old": {"checksum": _checksum("foo"), "size": 3},
"new": {"checksum": _checksum("FOO"), "size": 3},
"diff": {"status": "modified", "size": 0},
}
}

assert not dvc.diff("HEAD~1", target="missing")


def test_directories(tmp_dir, scm, dvc):
Expand Down

0 comments on commit 07abd1b

Please sign in to comment.