Repository: iterative/dvc

Issue:
diff: Stats reported by dvc not correct
# Description

When tracking a directory using DVC, the stats reported by `dvc diff` are not correct. For example, in a small test repository, the directory `test` is being tracked by DVC. When running `dvc diff` between two commits, the following is reported:

```
$ dvc diff f722af7 91cdc34

dvc diff from f722af74ec372073d04847a3c77ff7e7a154a21b to 91cdc345625ded08cb50f5616f41cee73b198bb6

diff for 'test'
-test with md5 cd5a9abdb72acc541fecb818c8280d5c.dir
+test with md5 3d681d1fe5b39802f663c9a82600d219.dir

0 files not changed, 0 files modified, 0 files added, 0 files deleted, size was increased by 3 Bytes
```

It should say that 1 file was modified, but instead only reports the size change correctly.

# Information about setup

```
$ dvc --version
0.35.5
```
DVC installed via pip.

```
$ python3 --version
Python 3.6.7
```
```
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.2 LTS
Release:	18.04
Codename:	bionic
```


Discussion:

Patch:
diff --git a/README.rst b/README.rst
index 4b2f75ccb..754879699 100644
--- a/README.rst
+++ b/README.rst
@@ -104,8 +104,8 @@ Please read `Get Started <https://dvc.org/doc/get-started>`_ for the full versio
 Installation
 ============
 
-Read this `instruction <https://dvc.org/doc/get-started/install>`_ to get more details. There are four
-options to install DVC: ``pip``, Homebrew, Conda (Anaconda) or an OS-specific package:
+Read this `instruction <https://dvc.org/doc/get-started/install>`_ to get more details. There are three
+options to install DVC: ``pip``, Homebrew, or an OS-specific package:
 
 pip (PyPI)
 ----------
@@ -137,15 +137,6 @@ or:
 .. code-block:: bash
 
    brew cask install iterative/homebrew-dvc/dvc
-   
-Conda (Anaconda)
-----------------
-
-.. code-block:: bash
-
-   conda install -c conda-forge dvc
-
-Currently, it supports only python version 2.7, 3.6 and 3.7.
 
 Package
 -------
diff --git a/dvc/command/diff.py b/dvc/command/diff.py
index 149d85451..ac8be0be7 100644
--- a/dvc/command/diff.py
+++ b/dvc/command/diff.py
@@ -39,7 +39,7 @@ class CmdDiff(CmdBase):
     def _get_dir_changes(cls, dct):
         engine = inflect.engine()
         changes_msg = (
-            "{} {} not changed, {} {} modified, {} {} added, "
+            "{} {} untouched, {} {} modified, {} {} added, "
             "{} {} deleted, size was {}"
         )
         changes_msg = changes_msg.format(
diff --git a/dvc/repo/diff.py b/dvc/repo/diff.py
index 6297560ee..f2ee3dc33 100644
--- a/dvc/repo/diff.py
+++ b/dvc/repo/diff.py
@@ -77,7 +77,7 @@ def _modified_files(self, a_entries, b_entries):
     modified_count = 0
     for key in keys:
         if a_entries[key] != b_entries[key]:
-            modified_count
+            modified_count += 1
             diff_size += os.path.getsize(
                 self.cache.local.get(b_entries[key])
             ) - os.path.getsize(self.cache.local.get(a_entries[key]))
diff --git a/scripts/ci/before_install.sh b/scripts/ci/before_install.sh
index bb7490a54..1411a4e4c 100644
--- a/scripts/ci/before_install.sh
+++ b/scripts/ci/before_install.sh
@@ -3,15 +3,13 @@
 set -x
 set -e
 
-scriptdir="$(dirname $0)"
-
 if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
     ulimit -a
     sudo sysctl -w kern.maxproc=2048
     sudo sysctl -w kern.maxprocperuid=2048
     echo '\nulimit -u 2048' >> ~/.bash_profile
     ulimit -a
-    $scriptdir/retry.sh brew update
+    brew update
     brew upgrade pyenv
     # NOTE: used to install and run our style checking tools
     osx_python_ver=3.6.2
@@ -49,6 +47,7 @@ if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then
     ssh 0.0.0.0 ls &> /dev/null
 fi
 
+scriptdir="$(dirname $0)"
 echo > env.sh
 
 if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]
diff --git a/scripts/ci/install.sh b/scripts/ci/install.sh
index 658bf1fd1..cefee81e3 100644
--- a/scripts/ci/install.sh
+++ b/scripts/ci/install.sh
@@ -3,14 +3,20 @@
 set -x
 set -e
 
-scriptdir="$(dirname $0)"
+N_RETRIES=3
+
+function retry {
+    for i in $(seq $N_RETRIES); do
+        $@ && break
+    done
+}
 
 # NOTE: it is not uncommon for pip to hang on travis for what seems to be
 # networking issues. Thus, let's retry a few times to see if it will eventially
 # work or not.
-$scriptdir/retry.sh pip install --upgrade pip setuptools wheel
-$scriptdir/retry.sh pip install .[all,tests]
-$scriptdir/retry.sh pip install psutil
+retry pip install --upgrade pip setuptools wheel
+retry pip install .[all,tests]
+retry pip install psutil
 
 git config --global user.email "dvctester@example.com"
 git config --global user.name "DVC Tester"
diff --git a/scripts/ci/retry.sh b/scripts/ci/retry.sh
deleted file mode 100755
index 490f92908..000000000
--- a/scripts/ci/retry.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-set -e
-
-N_RETRIES=3
-for i in $(seq $N_RETRIES); do
-    echo "Attempt #$i"
-    $@ && exit $?
-done
-
-exit $?


Test patch:
diff --git a/tests/func/test_diff.py b/tests/func/test_diff.py
index f4b148cfa..267288300 100644
--- a/tests/func/test_diff.py
+++ b/tests/func/test_diff.py
@@ -3,13 +3,8 @@ from __future__ import unicode_literals
 import os
 
 from dvc.main import main
-
-
 from dvc.scm.base import FileNotInCommitError
 import dvc.repo.diff as diff
-from dvc.command.diff import CmdDiff
-
-
 from tests.basic_env import TestDvcGit
 
 
@@ -68,26 +63,6 @@ class TestDiffCmdLine(TestDiff):
         self.assertEqual(ret, 0)
 
 
-class TestDiffCmdMessage(TestDiff):
-    maxDiff = None
-
-    def test(self):
-        msg = CmdDiff._show(self.test_dct)
-        test_msg = (
-            "dvc diff from {0} to {1}\n\n"
-            "diff for '{2}'\n"
-            "+{2} with md5 {3}\n\n"
-            "added file with size 13 Bytes"
-        )
-        test_msg = test_msg.format(
-            self.test_dct[diff.DIFF_A_REF],
-            self.test_dct[diff.DIFF_B_REF],
-            self.test_dct[diff.DIFF_LIST][0][diff.DIFF_TARGET],
-            self.test_dct[diff.DIFF_LIST][0][diff.DIFF_NEW_CHECKSUM],
-        )
-        self.assertEqual(test_msg, msg)
-
-
 class TestDiffDir(TestDvcGit):
     def setUp(self):
         super(TestDiffDir, self).setUp()
@@ -192,3 +167,109 @@ class TestDiffFileNotFound(TestDiffDir):
     def test(self):
         with self.assertRaises(FileNotInCommitError):
             self.dvc.diff(self.a_ref, target=self.unknown_file)
+
+
+class TestDiffModifiedFile(TestDiff):
+    maxDiff = None
+
+    def setUp(self):
+        super(TestDiffModifiedFile, self).setUp()
+
+        self.old_checksum = _get_checksum(self.dvc, self.new_file)
+        self.new_file_content = "new_test_file_bigger_content_123456789"
+        self.diff_len = len(self.new_file) + len(self.new_file_content)
+        self.create(self.new_file, self.new_file_content)
+        self.dvc.add(self.new_file)
+        self.git.index.add([self.new_file + ".dvc"])
+        self.git.index.commit("change new_file content to be bigger")
+        self.new_checksum = _get_checksum(self.dvc, self.new_file)
+        self.b_ref = self.git.git.rev_parse(self.git.head.commit, short=True)
+
+    def test(self):
+        result = self.dvc.diff(
+            self.a_ref, b_ref=self.b_ref, target=self.new_file
+        )
+        test_dct = {
+            diff.DIFF_A_REF: self.git.git.rev_parse(self.a_ref, short=True),
+            diff.DIFF_B_REF: self.git.git.rev_parse(self.b_ref, short=True),
+            diff.DIFF_LIST: [
+                {
+                    diff.DIFF_NEW_CHECKSUM: self.new_checksum,
+                    diff.DIFF_NEW_FILE: self.new_file,
+                    diff.DIFF_TARGET: self.new_file,
+                    diff.DIFF_SIZE: self.diff_len,
+                }
+            ],
+        }
+        self.assertEqual(test_dct, result)
+
+
+class TestDiffDirWithFile(TestDiffDir):
+    maxDiff = None
+
+    def setUp(self):
+        super(TestDiffDirWithFile, self).setUp()
+
+        self.a_ref = self.git.git.rev_parse(self.git.head.commit, short=True)
+        self.old_checksum = _get_checksum(self.dvc, self.DATA_DIR)
+        self.new_file_content = "new_test_file_bigger_content_123456789"
+        self.diff_len = len(self.new_file_content)
+        self.create(self.new_file, self.new_file_content)
+        self.dvc.add(self.DATA_DIR)
+        self.git.index.add([self.DATA_DIR + ".dvc"])
+        self.git.index.commit(message="modify file in the data dir")
+        self.new_checksum = _get_checksum(self.dvc, self.DATA_DIR)
+        self.b_ref = self.git.git.rev_parse(self.git.head.commit, short=True)
+
+    def test(self):
+        result = self.dvc.diff(self.a_ref, target=self.DATA_DIR)
+        test_dct = {
+            diff.DIFF_A_REF: self.git.git.rev_parse(self.a_ref, short=True),
+            diff.DIFF_B_REF: self.git.git.rev_parse(self.b_ref, short=True),
+            diff.DIFF_LIST: [
+                {
+                    diff.DIFF_IDENT: 2,
+                    diff.DIFF_CHANGE: 1,
+                    diff.DIFF_DEL: 0,
+                    diff.DIFF_MOVE: 0,
+                    diff.DIFF_NEW: 0,
+                    diff.DIFF_IS_DIR: True,
+                    diff.DIFF_TARGET: self.DATA_DIR,
+                    diff.DIFF_NEW_FILE: self.DATA_DIR,
+                    diff.DIFF_NEW_CHECKSUM: self.new_checksum,
+                    diff.DIFF_OLD_FILE: self.DATA_DIR,
+                    diff.DIFF_OLD_CHECKSUM: self.old_checksum,
+                    diff.DIFF_SIZE: self.diff_len,
+                }
+            ],
+        }
+        self.assertEqual(test_dct, result)
+
+
+class TestDiffCmdMessage(TestDiff):
+    maxDiff = None
+
+    def test(self):
+        ret = main(
+            [
+                "diff",
+                self.test_dct[diff.DIFF_A_REF],
+                self.test_dct[diff.DIFF_B_REF],
+            ]
+        )
+        self.assertEqual(ret, 0)
+
+        msg1 = "dvc diff from {0} to {1}".format(
+            self.git.git.rev_parse(self.test_dct[diff.DIFF_A_REF], short=True),
+            self.git.git.rev_parse(self.test_dct[diff.DIFF_B_REF], short=True),
+        )
+        msg2 = "diff for '{0}'".format(
+            self.test_dct[diff.DIFF_LIST][0][diff.DIFF_TARGET]
+        )
+        msg3 = "+{0} with md5 {1}".format(
+            self.test_dct[diff.DIFF_LIST][0][diff.DIFF_TARGET],
+            self.test_dct[diff.DIFF_LIST][0][diff.DIFF_NEW_CHECKSUM],
+        )
+        msg4 = "added file with size 13 Bytes"
+        for m in [msg1, msg2, msg3, msg4]:
+            assert m in self._caplog.text