We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Revisit dvc target from config in relation to phony stage files


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dvc/command/repro.py`
Content:
```
1 from dvc.command.common.base import CmdBase
2 
3 class CmdRepro(CmdBase):
4     def run(self):
5         recursive = not self.args.single_item
6         self.project.reproduce(self.args.targets,
7                                recursive=recursive,
8                                force=self.args.force)
9
```

Path: `dvc/project.py`
Content:
```
1 import os
2 import itertools
3 import networkx as nx
4 
5 from dvc.logger import Logger
6 from dvc.exceptions import DvcException
7 from dvc.stage import Stage, Output, Dependency
8 from dvc.config import Config
9 from dvc.state import State
10 from dvc.lock import Lock
11 from dvc.scm import SCM
12 from dvc.cache import Cache
13 from dvc.data_cloud import DataCloud
14 
15 
16 class PipelineError(DvcException):
17     pass
18 
19 
20 class StageNotInPipelineError(PipelineError):
21     pass
22 
23 
24 class StageNotFoundError(DvcException):
25     pass
26 
27 
28 class Pipeline(object):
29 
30     def __init__(self, project, G):
31         self.project = project
32         self.G = G
33 
34     def graph(self):
35         return self.G
36 
37     def stages(self):
38         return nx.get_node_attributes(self.G, 'stage')
39 
40     def changed(self, stage):
41         for node in nx.dfs_postorder_nodes(G, stage.path.relative_to(self.project.root_dir)):
42             if self.stages[node].changed():
43                 return True
44         return False
45 
46     def reproduce(self, stage):
47         if stage not in self.stages():
48             raise StageNotInPipelineError()
49 
50         if not self.changed(stage):
51             raise PipelineNotChangedError()
52 
53         for node in nx.dfs_postorder_nodes(G, stage.path.relative_to(self.project.root_dir)):
54             self.stages[node].reproduce()
55 
56         stage.reproduce()
57 
58 
59 class Project(object):
60     DVC_DIR = '.dvc'
61 
62     def __init__(self, root_dir):
63         self.root_dir = os.path.abspath(os.path.realpath(root_dir))
64         self.dvc_dir = os.path.join(self.root_dir, self.DVC_DIR)
65 
66         self.scm = SCM(self.root_dir)
67         self.lock = Lock(self.dvc_dir)
68         self.cache = Cache(self.dvc_dir)
69         self.state = State(self.root_dir, self.dvc_dir)
70         self.config = Config(self.dvc_dir)
71         self.logger = Logger()
72         self.cloud = DataCloud(self.config._config)
73 
74     @staticmethod
75     def init(root_dir):
76         """
77         Initiate dvc project in directory.
78 
79         Args:
80             root_dir: Path to project's root directory.
81 
82         Returns:
83             Project instance.
84 
85         Raises:
86             KeyError: Raises an exception.
87         """
88         root_dir = os.path.abspath(root_dir)
89         dvc_dir = os.path.join(root_dir, Project.DVC_DIR)
90         os.mkdir(dvc_dir)
91 
92         config = Config.init(dvc_dir)
93         cache = Cache.init(dvc_dir)
94         state = State.init(root_dir, dvc_dir)
95         lock = Lock(dvc_dir)
96 
97         scm = SCM(root_dir)
98         scm.ignore_list([cache.cache_dir,
99                          state.state_file,
100                          lock.lock_file])
101 
102         ignore_file = os.path.join(dvc_dir, scm.ignore_file())
103         scm.add([config.config_file, ignore_file])
104         scm.commit('DVC init')
105 
106         return Project(root_dir)
107 
108     def add(self, fname):
109         path = os.path.abspath(fname) + Stage.STAGE_FILE_SUFFIX
110         cwd = os.path.dirname(path)
111         outputs = [Output.loads(self, os.path.basename(fname), use_cache=True, cwd=cwd)]
112         stage = Stage(project=self,
113                       path=path,
114                       cmd=None,
115                       cwd=cwd,
116                       outs=outputs,
117                       deps=[],
118                       locked=True)
119         stage.save()
120         stage.dump()
121         return stage
122 
123     def remove(self, fname):
124         stages = []
125         output = Output.loads(self, fname)
126         for out in self.outs():
127             if out.path == output.path:
128                 stage = out.stage()
129                 stages.append(stage)
130 
131         if len(stages) == 0:
132             raise StageNotFoundError(fname) 
133 
134         for stage in stages:
135             stage.remove()
136 
137         return stages
138 
139     def run(self,
140             cmd=None,
141             deps=[],
142             outs=[],
143             outs_no_cache=[],
144             locked=False,
145             fname=Stage.STAGE_FILE,
146             cwd=os.curdir):
147         cwd = os.path.abspath(cwd)
148         path = os.path.join(cwd, fname)
149         outputs = Output.loads_from(self, outs, use_cache=True, cwd=cwd)
150         outputs += Output.loads_from(self, outs_no_cache, use_cache=False, cwd=cwd)
151         deps = Dependency.loads_from(self, deps, use_cache=False, cwd=cwd)
152 
153         stage = Stage(project=self,
154                       path=path,
155                       cmd=cmd,
156                       cwd=cwd,
157                       outs=outputs,
158                       deps=deps,
159                       locked=locked)
160         stage.run()
161         stage.dump()
162         return stage
163 
164     def reproduce(self, targets, recursive=True, force=False):
165         reproduced = []
166         stages = nx.get_node_attributes(self.graph(), 'stage')
167         for target in targets:
168             node = os.path.relpath(os.path.abspath(target), self.root_dir)
169             if node not in stages:
170                 raise StageNotFoundError(target)
171 
172             if recursive:
173                 for n in nx.dfs_postorder_nodes(self.graph(), node):
174                     stages[n].reproduce(force=force)
175                     stages[n].dump()
176                     reproduced.append(stages[n])
177 
178             stages[node].reproduce(force=force)
179             stages[node].dump()
180             reproduced.append(stages[node])
181 
182         return reproduced
183 
184     def checkout(self):
185         for stage in self.stages():
186             stage.checkout()
187 
188     def _used_cache(self):
189         clist = []
190         for stage in self.stages():
191             for entry in itertools.chain(stage.outs, stage.deps):
192                 if not entry.use_cache:
193                     continue
194                 if entry.cache not in clist:
195                     clist.append(entry.cache)
196         return clist
197 
198     def gc(self):
199         clist = self._used_cache()
200         for cache in self.cache.all():
201             if cache in clist:
202                 continue
203             os.unlink(cache)
204             self.logger.info('\'{}\' was removed'.format(cache))
205 
206     def push(self, jobs=1):
207         self.cloud.push(self._used_cache(), jobs)
208 
209     def pull(self, jobs=1):
210         self.cloud.pull(self._used_cache(), jobs)
211         for stage in self.stages():
212             for entry in itertools.chain(stage.outs, stage.deps):
213                 if entry.use_cache:
214                     entry.link()
215 
216     def status(self, jobs=1):
217         return self.cloud.status(self._used_cache(), jobs)
218 
219     def graph(self):
220         G = nx.DiGraph()
221 
222         for stage in self.stages():
223             node = os.path.relpath(stage.path, self.root_dir)
224             G.add_node(node, stage=stage)
225             for dep in stage.deps:
226                 dep_stage = dep.stage()
227                 if not dep_stage:
228                     continue
229                 dep_node = os.path.relpath(dep_stage.path, self.root_dir)
230                 G.add_node(dep_node, stage=dep_stage)
231                 G.add_edge(node, dep_node)
232 
233         return G
234 
235     def stages(self):
236         stages = []
237         for root, dirs, files in os.walk(self.root_dir):
238             for fname in files:
239                 path = os.path.join(root, fname)
240                 if not Stage.is_stage_file(path):
241                     continue
242                 stages.append(Stage.load(self, path))
243         return stages
244 
245     def outs(self):
246         outs = []
247         for stage in self.stages():
248             outs += stage.outs
249         return outs
250 
251     def pipelines(self):
252         pipelines = []
253         for G in nx.weakly_connected_component_subgraphs(self.graph()):
254             pipeline = Pipeline(self, G)
255             pipelines.append(pipeline)
256 
257         return pipelines
258
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/dvc/command/repro.py b/dvc/command/repro.py
--- a/dvc/command/repro.py
+++ b/dvc/command/repro.py
@@ -1,8 +1,16 @@
+from dvc.exceptions import DvcException
 from dvc.command.common.base import CmdBase
 
 class CmdRepro(CmdBase):
     def run(self):
         recursive = not self.args.single_item
-        self.project.reproduce(self.args.targets,
-                               recursive=recursive,
-                               force=self.args.force)
+        for target in self.args.targets:
+            try:
+                self.project.reproduce(target,
+                                       recursive=recursive,
+                                       force=self.args.force)
+            except DvcException as ex:
+                msg = 'Failed to reproduce {}: {}'.format(target, str(ex))
+                self.project.logger.error(msg)
+                return 1
+        return 0
diff --git a/dvc/project.py b/dvc/project.py
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -22,7 +22,9 @@
 
 
 class StageNotFoundError(DvcException):
-    pass
+    def __init__(self, path):
+        msg = 'Stage file {} does not exist'.format(path)
+        super(StageNotFoundError, self).__init__(msg)
 
 
 class Pipeline(object):
@@ -161,23 +163,22 @@
         stage.dump()
         return stage
 
-    def reproduce(self, targets, recursive=True, force=False):
+    def reproduce(self, target, recursive=True, force=False):
         reproduced = []
         stages = nx.get_node_attributes(self.graph(), 'stage')
-        for target in targets:
-            node = os.path.relpath(os.path.abspath(target), self.root_dir)
-            if node not in stages:
-                raise StageNotFoundError(target)
-
-            if recursive:
-                for n in nx.dfs_postorder_nodes(self.graph(), node):
-                    stages[n].reproduce(force=force)
-                    stages[n].dump()
-                    reproduced.append(stages[n])
-
-            stages[node].reproduce(force=force)
-            stages[node].dump()
-            reproduced.append(stages[node])
+        node = os.path.relpath(os.path.abspath(target), self.root_dir)
+        if node not in stages:
+            raise StageNotFoundError(target)
+
+        if recursive:
+            for n in nx.dfs_postorder_nodes(self.graph(), node):
+                stages[n].reproduce(force=force)
+                stages[n].dump()
+                reproduced.append(stages[n])
+
+        stages[node].reproduce(force=force)
+        stages[node].dump()
+        reproduced.append(stages[node])
 
         return reproduced

{"golden_diff": "diff --git a/dvc/command/repro.py b/dvc/command/repro.py\n--- a/dvc/command/repro.py\n+++ b/dvc/command/repro.py\n@@ -1,8 +1,16 @@\n+from dvc.exceptions import DvcException\n from dvc.command.common.base import CmdBase\n \n class CmdRepro(CmdBase):\n     def run(self):\n         recursive = not self.args.single_item\n-        self.project.reproduce(self.args.targets,\n-                               recursive=recursive,\n-                               force=self.args.force)\n+        for target in self.args.targets:\n+            try:\n+                self.project.reproduce(target,\n+                                       recursive=recursive,\n+                                       force=self.args.force)\n+            except DvcException as ex:\n+                msg = 'Failed to reproduce {}: {}'.format(target, str(ex))\n+                self.project.logger.error(msg)\n+                return 1\n+        return 0\ndiff --git a/dvc/project.py b/dvc/project.py\n--- a/dvc/project.py\n+++ b/dvc/project.py\n@@ -22,7 +22,9 @@\n \n \n class StageNotFoundError(DvcException):\n-    pass\n+    def __init__(self, path):\n+        msg = 'Stage file {} does not exist'.format(path)\n+        super(StageNotFoundError, self).__init__(msg)\n \n \n class Pipeline(object):\n@@ -161,23 +163,22 @@\n         stage.dump()\n         return stage\n \n-    def reproduce(self, targets, recursive=True, force=False):\n+    def reproduce(self, target, recursive=True, force=False):\n         reproduced = []\n         stages = nx.get_node_attributes(self.graph(), 'stage')\n-        for target in targets:\n-            node = os.path.relpath(os.path.abspath(target), self.root_dir)\n-            if node not in stages:\n-                raise StageNotFoundError(target)\n-\n-            if recursive:\n-                for n in nx.dfs_postorder_nodes(self.graph(), node):\n-                    stages[n].reproduce(force=force)\n-                    stages[n].dump()\n-                    reproduced.append(stages[n])\n-\n-            stages[node].reproduce(force=force)\n-            stages[node].dump()\n-            reproduced.append(stages[node])\n+        node = os.path.relpath(os.path.abspath(target), self.root_dir)\n+        if node not in stages:\n+            raise StageNotFoundError(target)\n+\n+        if recursive:\n+            for n in nx.dfs_postorder_nodes(self.graph(), node):\n+                stages[n].reproduce(force=force)\n+                stages[n].dump()\n+                reproduced.append(stages[n])\n+\n+        stages[node].reproduce(force=force)\n+        stages[node].dump()\n+        reproduced.append(stages[node])\n \n         return reproduced\n", "issue": "Revisit dvc target from config in relation to phony stage files\n\n", "before_files": [{"content": "from dvc.command.common.base import CmdBase\n\nclass CmdRepro(CmdBase):\n    def run(self):\n        recursive = not self.args.single_item\n        self.project.reproduce(self.args.targets,\n                               recursive=recursive,\n                               force=self.args.force)\n", "path": "dvc/command/repro.py"}, {"content": "import os\nimport itertools\nimport networkx as nx\n\nfrom dvc.logger import Logger\nfrom dvc.exceptions import DvcException\nfrom dvc.stage import Stage, Output, Dependency\nfrom dvc.config import Config\nfrom dvc.state import State\nfrom dvc.lock import Lock\nfrom dvc.scm import SCM\nfrom dvc.cache import Cache\nfrom dvc.data_cloud import DataCloud\n\n\nclass PipelineError(DvcException):\n    pass\n\n\nclass StageNotInPipelineError(PipelineError):\n    pass\n\n\nclass StageNotFoundError(DvcException):\n    pass\n\n\nclass Pipeline(object):\n\n    def __init__(self, project, G):\n        self.project = project\n        self.G = G\n\n    def graph(self):\n        return self.G\n\n    def stages(self):\n        return nx.get_node_attributes(self.G, 'stage')\n\n    def changed(self, stage):\n        for node in nx.dfs_postorder_nodes(G, stage.path.relative_to(self.project.root_dir)):\n            if self.stages[node].changed():\n                return True\n        return False\n\n    def reproduce(self, stage):\n        if stage not in self.stages():\n            raise StageNotInPipelineError()\n\n        if not self.changed(stage):\n            raise PipelineNotChangedError()\n\n        for node in nx.dfs_postorder_nodes(G, stage.path.relative_to(self.project.root_dir)):\n            self.stages[node].reproduce()\n\n        stage.reproduce()\n\n\nclass Project(object):\n    DVC_DIR = '.dvc'\n\n    def __init__(self, root_dir):\n        self.root_dir = os.path.abspath(os.path.realpath(root_dir))\n        self.dvc_dir = os.path.join(self.root_dir, self.DVC_DIR)\n\n        self.scm = SCM(self.root_dir)\n        self.lock = Lock(self.dvc_dir)\n        self.cache = Cache(self.dvc_dir)\n        self.state = State(self.root_dir, self.dvc_dir)\n        self.config = Config(self.dvc_dir)\n        self.logger = Logger()\n        self.cloud = DataCloud(self.config._config)\n\n    @staticmethod\n    def init(root_dir):\n        \"\"\"\n        Initiate dvc project in directory.\n\n        Args:\n            root_dir: Path to project's root directory.\n\n        Returns:\n            Project instance.\n\n        Raises:\n            KeyError: Raises an exception.\n        \"\"\"\n        root_dir = os.path.abspath(root_dir)\n        dvc_dir = os.path.join(root_dir, Project.DVC_DIR)\n        os.mkdir(dvc_dir)\n\n        config = Config.init(dvc_dir)\n        cache = Cache.init(dvc_dir)\n        state = State.init(root_dir, dvc_dir)\n        lock = Lock(dvc_dir)\n\n        scm = SCM(root_dir)\n        scm.ignore_list([cache.cache_dir,\n                         state.state_file,\n                         lock.lock_file])\n\n        ignore_file = os.path.join(dvc_dir, scm.ignore_file())\n        scm.add([config.config_file, ignore_file])\n        scm.commit('DVC init')\n\n        return Project(root_dir)\n\n    def add(self, fname):\n        path = os.path.abspath(fname) + Stage.STAGE_FILE_SUFFIX\n        cwd = os.path.dirname(path)\n        outputs = [Output.loads(self, os.path.basename(fname), use_cache=True, cwd=cwd)]\n        stage = Stage(project=self,\n                      path=path,\n                      cmd=None,\n                      cwd=cwd,\n                      outs=outputs,\n                      deps=[],\n                      locked=True)\n        stage.save()\n        stage.dump()\n        return stage\n\n    def remove(self, fname):\n        stages = []\n        output = Output.loads(self, fname)\n        for out in self.outs():\n            if out.path == output.path:\n                stage = out.stage()\n                stages.append(stage)\n\n        if len(stages) == 0:\n            raise StageNotFoundError(fname) \n\n        for stage in stages:\n            stage.remove()\n\n        return stages\n\n    def run(self,\n            cmd=None,\n            deps=[],\n            outs=[],\n            outs_no_cache=[],\n            locked=False,\n            fname=Stage.STAGE_FILE,\n            cwd=os.curdir):\n        cwd = os.path.abspath(cwd)\n        path = os.path.join(cwd, fname)\n        outputs = Output.loads_from(self, outs, use_cache=True, cwd=cwd)\n        outputs += Output.loads_from(self, outs_no_cache, use_cache=False, cwd=cwd)\n        deps = Dependency.loads_from(self, deps, use_cache=False, cwd=cwd)\n\n        stage = Stage(project=self,\n                      path=path,\n                      cmd=cmd,\n                      cwd=cwd,\n                      outs=outputs,\n                      deps=deps,\n                      locked=locked)\n        stage.run()\n        stage.dump()\n        return stage\n\n    def reproduce(self, targets, recursive=True, force=False):\n        reproduced = []\n        stages = nx.get_node_attributes(self.graph(), 'stage')\n        for target in targets:\n            node = os.path.relpath(os.path.abspath(target), self.root_dir)\n            if node not in stages:\n                raise StageNotFoundError(target)\n\n            if recursive:\n                for n in nx.dfs_postorder_nodes(self.graph(), node):\n                    stages[n].reproduce(force=force)\n                    stages[n].dump()\n                    reproduced.append(stages[n])\n\n            stages[node].reproduce(force=force)\n            stages[node].dump()\n            reproduced.append(stages[node])\n\n        return reproduced\n\n    def checkout(self):\n        for stage in self.stages():\n            stage.checkout()\n\n    def _used_cache(self):\n        clist = []\n        for stage in self.stages():\n            for entry in itertools.chain(stage.outs, stage.deps):\n                if not entry.use_cache:\n                    continue\n                if entry.cache not in clist:\n                    clist.append(entry.cache)\n        return clist\n\n    def gc(self):\n        clist = self._used_cache()\n        for cache in self.cache.all():\n            if cache in clist:\n                continue\n            os.unlink(cache)\n            self.logger.info('\\'{}\\' was removed'.format(cache))\n\n    def push(self, jobs=1):\n        self.cloud.push(self._used_cache(), jobs)\n\n    def pull(self, jobs=1):\n        self.cloud.pull(self._used_cache(), jobs)\n        for stage in self.stages():\n            for entry in itertools.chain(stage.outs, stage.deps):\n                if entry.use_cache:\n                    entry.link()\n\n    def status(self, jobs=1):\n        return self.cloud.status(self._used_cache(), jobs)\n\n    def graph(self):\n        G = nx.DiGraph()\n\n        for stage in self.stages():\n            node = os.path.relpath(stage.path, self.root_dir)\n            G.add_node(node, stage=stage)\n            for dep in stage.deps:\n                dep_stage = dep.stage()\n                if not dep_stage:\n                    continue\n                dep_node = os.path.relpath(dep_stage.path, self.root_dir)\n                G.add_node(dep_node, stage=dep_stage)\n                G.add_edge(node, dep_node)\n\n        return G\n\n    def stages(self):\n        stages = []\n        for root, dirs, files in os.walk(self.root_dir):\n            for fname in files:\n                path = os.path.join(root, fname)\n                if not Stage.is_stage_file(path):\n                    continue\n                stages.append(Stage.load(self, path))\n        return stages\n\n    def outs(self):\n        outs = []\n        for stage in self.stages():\n            outs += stage.outs\n        return outs\n\n    def pipelines(self):\n        pipelines = []\n        for G in nx.weakly_connected_component_subgraphs(self.graph()):\n            pipeline = Pipeline(self, G)\n            pipelines.append(pipeline)\n\n        return pipelines\n", "path": "dvc/project.py"}], "after_files": [{"content": "from dvc.exceptions import DvcException\nfrom dvc.command.common.base import CmdBase\n\nclass CmdRepro(CmdBase):\n    def run(self):\n        recursive = not self.args.single_item\n        for target in self.args.targets:\n            try:\n                self.project.reproduce(target,\n                                       recursive=recursive,\n                                       force=self.args.force)\n            except DvcException as ex:\n                msg = 'Failed to reproduce {}: {}'.format(target, str(ex))\n                self.project.logger.error(msg)\n                return 1\n        return 0\n", "path": "dvc/command/repro.py"}, {"content": "import os\nimport itertools\nimport networkx as nx\n\nfrom dvc.logger import Logger\nfrom dvc.exceptions import DvcException\nfrom dvc.stage import Stage, Output, Dependency\nfrom dvc.config import Config\nfrom dvc.state import State\nfrom dvc.lock import Lock\nfrom dvc.scm import SCM\nfrom dvc.cache import Cache\nfrom dvc.data_cloud import DataCloud\n\n\nclass PipelineError(DvcException):\n    pass\n\n\nclass StageNotInPipelineError(PipelineError):\n    pass\n\n\nclass StageNotFoundError(DvcException):\n    def __init__(self, path):\n        msg = 'Stage file {} does not exist'.format(path)\n        super(StageNotFoundError, self).__init__(msg)\n\n\nclass Pipeline(object):\n\n    def __init__(self, project, G):\n        self.project = project\n        self.G = G\n\n    def graph(self):\n        return self.G\n\n    def stages(self):\n        return nx.get_node_attributes(self.G, 'stage')\n\n    def changed(self, stage):\n        for node in nx.dfs_postorder_nodes(G, stage.path.relative_to(self.project.root_dir)):\n            if self.stages[node].changed():\n                return True\n        return False\n\n    def reproduce(self, stage):\n        if stage not in self.stages():\n            raise StageNotInPipelineError()\n\n        if not self.changed(stage):\n            raise PipelineNotChangedError()\n\n        for node in nx.dfs_postorder_nodes(G, stage.path.relative_to(self.project.root_dir)):\n            self.stages[node].reproduce()\n\n        stage.reproduce()\n\n\nclass Project(object):\n    DVC_DIR = '.dvc'\n\n    def __init__(self, root_dir):\n        self.root_dir = os.path.abspath(os.path.realpath(root_dir))\n        self.dvc_dir = os.path.join(self.root_dir, self.DVC_DIR)\n\n        self.scm = SCM(self.root_dir)\n        self.lock = Lock(self.dvc_dir)\n        self.cache = Cache(self.dvc_dir)\n        self.state = State(self.root_dir, self.dvc_dir)\n        self.config = Config(self.dvc_dir)\n        self.logger = Logger()\n        self.cloud = DataCloud(self.config._config)\n\n    @staticmethod\n    def init(root_dir):\n        \"\"\"\n        Initiate dvc project in directory.\n\n        Args:\n            root_dir: Path to project's root directory.\n\n        Returns:\n            Project instance.\n\n        Raises:\n            KeyError: Raises an exception.\n        \"\"\"\n        root_dir = os.path.abspath(root_dir)\n        dvc_dir = os.path.join(root_dir, Project.DVC_DIR)\n        os.mkdir(dvc_dir)\n\n        config = Config.init(dvc_dir)\n        cache = Cache.init(dvc_dir)\n        state = State.init(root_dir, dvc_dir)\n        lock = Lock(dvc_dir)\n\n        scm = SCM(root_dir)\n        scm.ignore_list([cache.cache_dir,\n                         state.state_file,\n                         lock.lock_file])\n\n        ignore_file = os.path.join(dvc_dir, scm.ignore_file())\n        scm.add([config.config_file, ignore_file])\n        scm.commit('DVC init')\n\n        return Project(root_dir)\n\n    def add(self, fname):\n        path = os.path.abspath(fname) + Stage.STAGE_FILE_SUFFIX\n        cwd = os.path.dirname(path)\n        outputs = [Output.loads(self, os.path.basename(fname), use_cache=True, cwd=cwd)]\n        stage = Stage(project=self,\n                      path=path,\n                      cmd=None,\n                      cwd=cwd,\n                      outs=outputs,\n                      deps=[],\n                      locked=True)\n        stage.save()\n        stage.dump()\n        return stage\n\n    def remove(self, fname):\n        stages = []\n        output = Output.loads(self, fname)\n        for out in self.outs():\n            if out.path == output.path:\n                stage = out.stage()\n                stages.append(stage)\n\n        if len(stages) == 0:\n            raise StageNotFoundError(fname) \n\n        for stage in stages:\n            stage.remove()\n\n        return stages\n\n    def run(self,\n            cmd=None,\n            deps=[],\n            outs=[],\n            outs_no_cache=[],\n            locked=False,\n            fname=Stage.STAGE_FILE,\n            cwd=os.curdir):\n        cwd = os.path.abspath(cwd)\n        path = os.path.join(cwd, fname)\n        outputs = Output.loads_from(self, outs, use_cache=True, cwd=cwd)\n        outputs += Output.loads_from(self, outs_no_cache, use_cache=False, cwd=cwd)\n        deps = Dependency.loads_from(self, deps, use_cache=False, cwd=cwd)\n\n        stage = Stage(project=self,\n                      path=path,\n                      cmd=cmd,\n                      cwd=cwd,\n                      outs=outputs,\n                      deps=deps,\n                      locked=locked)\n        stage.run()\n        stage.dump()\n        return stage\n\n    def reproduce(self, target, recursive=True, force=False):\n        reproduced = []\n        stages = nx.get_node_attributes(self.graph(), 'stage')\n        node = os.path.relpath(os.path.abspath(target), self.root_dir)\n        if node not in stages:\n            raise StageNotFoundError(target)\n\n        if recursive:\n            for n in nx.dfs_postorder_nodes(self.graph(), node):\n                stages[n].reproduce(force=force)\n                stages[n].dump()\n                reproduced.append(stages[n])\n\n        stages[node].reproduce(force=force)\n        stages[node].dump()\n        reproduced.append(stages[node])\n\n        return reproduced\n\n    def checkout(self):\n        for stage in self.stages():\n            stage.checkout()\n\n    def _used_cache(self):\n        clist = []\n        for stage in self.stages():\n            for entry in itertools.chain(stage.outs, stage.deps):\n                if not entry.use_cache:\n                    continue\n                if entry.cache not in clist:\n                    clist.append(entry.cache)\n        return clist\n\n    def gc(self):\n        clist = self._used_cache()\n        for cache in self.cache.all():\n            if cache in clist:\n                continue\n            os.unlink(cache)\n            self.logger.info('\\'{}\\' was removed'.format(cache))\n\n    def push(self, jobs=1):\n        self.cloud.push(self._used_cache(), jobs)\n\n    def pull(self, jobs=1):\n        self.cloud.pull(self._used_cache(), jobs)\n        for stage in self.stages():\n            for entry in itertools.chain(stage.outs, stage.deps):\n                if entry.use_cache:\n                    entry.link()\n\n    def status(self, jobs=1):\n        return self.cloud.status(self._used_cache(), jobs)\n\n    def graph(self):\n        G = nx.DiGraph()\n\n        for stage in self.stages():\n            node = os.path.relpath(stage.path, self.root_dir)\n            G.add_node(node, stage=stage)\n            for dep in stage.deps:\n                dep_stage = dep.stage()\n                if not dep_stage:\n                    continue\n                dep_node = os.path.relpath(dep_stage.path, self.root_dir)\n                G.add_node(dep_node, stage=dep_stage)\n                G.add_edge(node, dep_node)\n\n        return G\n\n    def stages(self):\n        stages = []\n        for root, dirs, files in os.walk(self.root_dir):\n            for fname in files:\n                path = os.path.join(root, fname)\n                if not Stage.is_stage_file(path):\n                    continue\n                stages.append(Stage.load(self, path))\n        return stages\n\n    def outs(self):\n        outs = []\n        for stage in self.stages():\n            outs += stage.outs\n        return outs\n\n    def pipelines(self):\n        pipelines = []\n        for G in nx.weakly_connected_component_subgraphs(self.graph()):\n            pipeline = Pipeline(self, G)\n            pipelines.append(pipeline)\n\n        return pipelines\n", "path": "dvc/project.py"}]}