diff --git a/dvc/command/status.py b/dvc/command/status.py index 75bc4f2e4..1e38ed0d8 100644 --- a/dvc/command/status.py +++ b/dvc/command/status.py @@ -2,10 +2,11 @@ from __future__ import unicode_literals import dvc.logger as logger from dvc.command.data_sync import CmdDataBase +from dvc.utils.compat import str class CmdDataStatus(CmdDataBase): - STATUS_LEN = 10 + STATUS_LEN = 20 STATUS_INDENT = "\t" UP_TO_DATE_MSG = "Pipeline is up to date. Nothing to reproduce." @@ -17,13 +18,23 @@ class CmdDataStatus(CmdDataBase): def _show(self, status, indent=0): ind = indent * self.STATUS_INDENT + if isinstance(status, str): + logger.info("{}{}".format(ind, status)) + return + + if isinstance(status, list): + for entry in status: + self._show(entry, indent) + return + + assert isinstance(status, dict) + for key, value in status.items(): - if isinstance(value, dict): - logger.info("{}{}".format(ind, key)) + if isinstance(value, str): + logger.info("{}{}{}".format(ind, self._normalize(value), key)) + elif value: + logger.info("{}{}:".format(ind, key)) self._show(value, indent + 1) - else: - msg = "{}{}{}".format(ind, self._normalize(value), key) - logger.info(msg) def do_run(self, target=None): indent = 1 if self.args.cloud else 0 diff --git a/dvc/output/base.py b/dvc/output/base.py index e9cfd500a..9fb8bb1ca 100644 --- a/dvc/output/base.py +++ b/dvc/output/base.py @@ -111,15 +111,12 @@ class OutputBase(object): def exists(self): return self.remote.exists(self.path_info) - def changed(self): - if not self.exists: - return True - - if not self.use_cache: - return self.info != self.remote.save_info(self.path_info) - - return getattr(self.repo.cache, self.scheme).changed( - self.path_info, self.info + def changed_checksum(self): + return ( + self.checksum + != self.remote.save_info(self.path_info)[ + self.remote.PARAM_CHECKSUM + ] ) def changed_cache(self): @@ -131,11 +128,23 @@ class OutputBase(object): return cache.changed_cache(self.checksum) def status(self): - if self.changed(): - # FIXME better msgs - return {str(self): "changed"} + if self.checksum and self.use_cache and self.changed_cache(): + return {str(self): "not in cache"} + + if not self.exists: + return {str(self): "deleted"} + + if self.changed_checksum(): + return {str(self): "modified"} + + if not self.checksum: + return {str(self): "new"} + return {} + def changed(self): + return bool(self.status()) + def save(self): self.info = self.remote.save_info(self.path_info) diff --git a/dvc/stage.py b/dvc/stage.py index 6d12e55c5..187201f45 100644 --- a/dvc/stage.py +++ b/dvc/stage.py @@ -649,26 +649,33 @@ class Stage(object): out.checkout(force=force) @staticmethod - def _status(entries, name): + def _status(entries): ret = {} for entry in entries: ret.update(entry.status()) - if ret: - return {name: ret} - - return {} + return ret def status(self): - ret = {} + ret = [] if not self.locked: - ret.update(self._status(self.deps, "deps")) + deps_status = self._status(self.deps) + if deps_status: + ret.append({"changed deps": deps_status}) - ret.update(self._status(self.outs, "outs")) + outs_status = self._status(self.outs) + if outs_status: + ret.append({"changed outs": outs_status}) - if ret or self.changed_md5() or self.is_callback: + if self.changed_md5(): + ret.append("changed checksum") + + if self.is_callback: + ret.append("always changed") + + if ret: return {self.relpath: ret} return {}