mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
76 lines
2.0 KiB
Python
76 lines
2.0 KiB
Python
import os
|
|
import collections
|
|
|
|
from dvc.repo import locked
|
|
from dvc.compat import fspath
|
|
|
|
|
|
Diffable = collections.namedtuple("Diffable", "filename, checksum, size")
|
|
Diffable.__doc__ = "Common interface to compare outputs."
|
|
Diffable._asdict = lambda x: {"checksum": x.checksum, "size": x.size}
|
|
|
|
|
|
def diffable_from_output(output):
|
|
try:
|
|
size = os.path.getsize(fspath(output.path_info))
|
|
except FileNotFoundError:
|
|
size = None
|
|
|
|
return Diffable(filename=str(output), checksum=output.checksum, size=size)
|
|
|
|
|
|
def compare_states(old, new):
|
|
if old and new:
|
|
try:
|
|
size = new["size"] - old["size"]
|
|
except KeyError:
|
|
size = "unknown"
|
|
return {"status": "modified", "size": size}
|
|
|
|
if old and not new:
|
|
return {"status": "deleted", "size": old.get("size", "unknown")}
|
|
|
|
if not old and new:
|
|
return {"status": "added", "size": new.get("size", "unknown")}
|
|
|
|
|
|
@locked
|
|
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.
|
|
|
|
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 = {}
|
|
|
|
for branch in self.brancher(revs=[a_ref, b_ref]):
|
|
outs[branch] = set(
|
|
diffable_from_output(out)
|
|
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 not delta:
|
|
return
|
|
|
|
result = collections.defaultdict(dict)
|
|
|
|
for entry in delta:
|
|
states = result[entry.filename]
|
|
states.update(
|
|
old=states.get("old") or (entry._asdict() if entry in old else {}),
|
|
new=states.get("new") or (entry._asdict() if entry in new else {}),
|
|
)
|
|
|
|
for filename, entry in result.items():
|
|
entry.update({"diff": compare_states(entry["old"], entry["new"])})
|
|
|
|
return result
|