dvc: speedup stage collection by not visiting output dirs of the stages
Right now dvc will walk through all directories and files in the repo to find dvc files. In cases when there are some giant directories, it vastly slows down every dvc command. Need to stop visiting those directories.
diff --git a/dvc/project.py b/dvc/project.py
index 98e58f59a..eb5dc80ff 100644
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -746,12 +746,28 @@ class Project(object):
 
     def stages(self):
         stages = []
+        outs = []
         for root, dirs, files in os.walk(self.root_dir):
             for fname in files:
                 path = os.path.join(root, fname)
                 if not Stage.is_stage_file(path):
                     continue
-                stages.append(Stage.load(self, path))
+                stage = Stage.load(self, path)
+                for out in stage.outs:
+                    outs.append(out.path + out.sep)
+                stages.append(stage)
+
+            def filter_dirs(dname):
+                path = os.path.join(root, dname)
+                if path == self.dvc_dir or path == self.scm.dir:
+                    return False
+                for out in outs:
+                    if path == os.path.normpath(out) or path.startswith(out):
+                        return False
+                return True
+
+            dirs[:] = list(filter(filter_dirs, dirs))
+
         return stages
 
     def active_stages(self):
diff --git a/dvc/scm.py b/dvc/scm.py
index eadaf9943..5ac1d16ca 100644
--- a/dvc/scm.py
+++ b/dvc/scm.py
@@ -99,6 +99,10 @@ class Git(Base):
         git_dir = os.path.join(root_dir, Git.GIT_DIR)
         return os.path.isdir(git_dir)
 
+    @property
+    def dir(self):
+        return self.repo.git_dir
+
     def ignore_file(self):
         return self.GITIGNORE
 
['dvc/project.py', 'dvc/scm.py']