We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
run-cache: fails for params
```sh
$ echo "train: 1\nlr: 2" > params.yaml
$ dvc run  -n test -p train,lr -o params2.yaml "cat params.yaml > params2.yaml"
ERROR: failed to reproduce 'dvc.yaml': 'deps'
```
Verbose log:
```sh
------------------------------------------------------------
Traceback (most recent call last):
  File "/home/saugat/repos/iterative/dvc/dvc/main.py", line 48, in main
    ret = cmd.run()
  File "/home/saugat/repos/iterative/dvc/dvc/command/run.py", line 51, in run
    single_stage=self.args.single_stage,
  File "/home/saugat/repos/iterative/dvc/dvc/repo/__init__.py", line 25, in wrapper
    ret = f(repo, *args, **kwargs)
  File "/home/saugat/repos/iterative/dvc/dvc/repo/scm_context.py", line 4, in run
    result = method(repo, *args, **kw)
  File "/home/saugat/repos/iterative/dvc/dvc/repo/run.py", line 88, in run
    run_cache=kwargs.get("run_cache", True),
  File "/home/saugat/repos/iterative/dvc/.env/py36/lib/python3.6/site-packages/funcy/decorators.py", line 39, in wrapper
    return deco(call, *dargs, **dkwargs)
  File "/home/saugat/repos/iterative/dvc/dvc/stage/decorators.py", line 35, in rwlocked
    return call()
  File "/home/saugat/repos/iterative/dvc/.env/py36/lib/python3.6/site-packages/funcy/decorators.py", line 60, in __call__
    return self._func(*self._args, **self._kwargs)
  File "/home/saugat/repos/iterative/dvc/dvc/stage/__init__.py", line 417, in run
    self.save()
  File "/home/saugat/repos/iterative/dvc/dvc/stage/__init__.py", line 368, in save
    self.repo.stage_cache.save(self)
  File "/home/saugat/repos/iterative/dvc/dvc/stage/cache.py", line 130, in save
    for out in self._uncached_outs(stage, cache):
  File "/home/saugat/repos/iterative/dvc/dvc/stage/cache.py", line 107, in _uncached_outs
    cached_stage = self._create_stage(cache)
  File "/home/saugat/repos/iterative/dvc/dvc/stage/cache.py", line 88, in _create_stage
    deps=[dep["path"] for dep in cache["deps"]],
KeyError: 'deps'
```




--- 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/stage/cache.py`
Content:
```
1 import logging
2 import os
3 from contextlib import contextmanager
4 
5 import yaml
6 from funcy import first
7 from voluptuous import Invalid
8 
9 from dvc.schema import COMPILED_LOCK_FILE_STAGE_SCHEMA
10 from dvc.serialize import to_single_stage_lockfile
11 from dvc.stage.loader import StageLoader
12 from dvc.utils import dict_sha256, relpath
13 from dvc.utils.fs import makedirs
14 from dvc.utils.stage import dump_stage_file
15 
16 logger = logging.getLogger(__name__)
17 
18 
19 def _get_cache_hash(cache, key=False):
20     if key:
21         cache["outs"] = [out["path"] for out in cache.get("outs", [])]
22     return dict_sha256(cache)
23 
24 
25 def _get_stage_hash(stage):
26     if not (stage.cmd and stage.deps and stage.outs):
27         return None
28 
29     for dep in stage.deps:
30         if not (dep.scheme == "local" and dep.def_path and dep.get_checksum()):
31             return None
32 
33     for out in stage.outs:
34         if out.scheme != "local" or not out.def_path or out.persist:
35             return None
36 
37     return _get_cache_hash(to_single_stage_lockfile(stage), key=True)
38 
39 
40 class StageCache:
41     def __init__(self, repo):
42         self.repo = repo
43         self.cache_dir = os.path.join(repo.cache.local.cache_dir, "runs")
44 
45     def _get_cache_dir(self, key):
46         return os.path.join(self.cache_dir, key[:2], key)
47 
48     def _get_cache_path(self, key, value):
49         return os.path.join(self._get_cache_dir(key), value)
50 
51     def _load_cache(self, key, value):
52         path = self._get_cache_path(key, value)
53 
54         try:
55             with open(path) as fobj:
56                 return COMPILED_LOCK_FILE_STAGE_SCHEMA(yaml.safe_load(fobj))
57         except FileNotFoundError:
58             return None
59         except (yaml.error.YAMLError, Invalid):
60             logger.warning("corrupted cache file '%s'.", relpath(path))
61             os.unlink(path)
62             return None
63 
64     def _load(self, stage):
65         key = _get_stage_hash(stage)
66         if not key:
67             return None
68 
69         cache_dir = self._get_cache_dir(key)
70         if not os.path.exists(cache_dir):
71             return None
72 
73         for value in os.listdir(cache_dir):
74             cache = self._load_cache(key, value)
75             if cache:
76                 return cache
77 
78         return None
79 
80     def _create_stage(self, cache):
81         from dvc.stage import create_stage, PipelineStage
82 
83         stage = create_stage(
84             PipelineStage,
85             repo=self.repo,
86             path="dvc.yaml",
87             cmd=cache["cmd"],
88             deps=[dep["path"] for dep in cache["deps"]],
89             outs=[out["path"] for out in cache["outs"]],
90         )
91         StageLoader.fill_from_lock(stage, cache)
92         return stage
93 
94     @contextmanager
95     def _cache_type_copy(self):
96         cache_types = self.repo.cache.local.cache_types
97         self.repo.cache.local.cache_types = ["copy"]
98         try:
99             yield
100         finally:
101             self.repo.cache.local.cache_types = cache_types
102 
103     def _uncached_outs(self, stage, cache):
104         # NOTE: using temporary stage to avoid accidentally modifying original
105         # stage and to workaround `commit/checkout` not working for uncached
106         # outputs.
107         cached_stage = self._create_stage(cache)
108 
109         outs_no_cache = [
110             out.def_path for out in stage.outs if not out.use_cache
111         ]
112 
113         # NOTE: using copy link to make it look like a git-tracked file
114         with self._cache_type_copy():
115             for out in cached_stage.outs:
116                 if out.def_path in outs_no_cache:
117                     yield out
118 
119     def save(self, stage):
120         cache_key = _get_stage_hash(stage)
121         if not cache_key:
122             return
123 
124         cache = to_single_stage_lockfile(stage)
125         cache_value = _get_cache_hash(cache)
126 
127         existing_cache = self._load_cache(cache_key, cache_value)
128         cache = existing_cache or cache
129 
130         for out in self._uncached_outs(stage, cache):
131             out.commit()
132 
133         if existing_cache:
134             return
135 
136         # sanity check
137         COMPILED_LOCK_FILE_STAGE_SCHEMA(cache)
138 
139         path = self._get_cache_path(cache_key, cache_value)
140         dpath = os.path.dirname(path)
141         makedirs(dpath, exist_ok=True)
142         dump_stage_file(path, cache)
143 
144     def is_cached(self, stage):
145         return bool(self._load(stage))
146 
147     def restore(self, stage):
148         cache = self._load(stage)
149         if not cache:
150             return
151         StageLoader.fill_from_lock(stage, cache)
152 
153         for out in self._uncached_outs(stage, cache):
154             out.checkout()
155 
156     @staticmethod
157     def _transfer(func, from_remote, to_remote):
158         ret = []
159 
160         runs = from_remote.path_info / "runs"
161         if not from_remote.exists(runs):
162             return []
163 
164         for src in from_remote.walk_files(runs):
165             rel = src.relative_to(from_remote.path_info)
166             dst = to_remote.path_info / rel
167             key = dst.parent
168             # check if any build cache already exists for this key
169             if to_remote.exists(key) and first(to_remote.walk_files(key)):
170                 continue
171             func(src, dst)
172             ret.append((src.parent.name, src.name))
173 
174         return ret
175 
176     def push(self, remote):
177         remote = self.repo.cloud.get_remote(remote)
178         return self._transfer(remote.upload, self.repo.cache.local, remote)
179 
180     def pull(self, remote):
181         remote = self.repo.cloud.get_remote(remote)
182         return self._transfer(remote.download, remote, self.repo.cache.local)
183 
184     def get_used_cache(self, used_run_cache, *args, **kwargs):
185         from dvc.cache import NamedCache
186 
187         cache = NamedCache()
188 
189         for key, value in used_run_cache:
190             entry = self._load_cache(key, value)
191             if not entry:
192                 continue
193             stage = self._create_stage(entry)
194             cache.update(stage.get_used_cache(*args, **kwargs))
195         return cache
196
```
--- 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/stage/cache.py b/dvc/stage/cache.py
--- a/dvc/stage/cache.py
+++ b/dvc/stage/cache.py
@@ -80,12 +80,26 @@
     def _create_stage(self, cache):
         from dvc.stage import create_stage, PipelineStage
 
+        params = []
+        for param in cache.get("params", []):
+            if isinstance(param, str):
+                params.append(param)
+                continue
+
+            assert isinstance(param, dict)
+            assert len(param) == 1
+            path = list(param.keys())[0]
+            params_list = param[path]
+            assert isinstance(params_list, list)
+            params.append(f"{path}:" + ",".join(params_list))
+
         stage = create_stage(
             PipelineStage,
             repo=self.repo,
             path="dvc.yaml",
             cmd=cache["cmd"],
-            deps=[dep["path"] for dep in cache["deps"]],
+            params=params,
+            deps=[dep["path"] for dep in cache.get("deps", [])],
             outs=[out["path"] for out in cache["outs"]],
         )
         StageLoader.fill_from_lock(stage, cache)

{"golden_diff": "diff --git a/dvc/stage/cache.py b/dvc/stage/cache.py\n--- a/dvc/stage/cache.py\n+++ b/dvc/stage/cache.py\n@@ -80,12 +80,26 @@\n     def _create_stage(self, cache):\n         from dvc.stage import create_stage, PipelineStage\n \n+        params = []\n+        for param in cache.get(\"params\", []):\n+            if isinstance(param, str):\n+                params.append(param)\n+                continue\n+\n+            assert isinstance(param, dict)\n+            assert len(param) == 1\n+            path = list(param.keys())[0]\n+            params_list = param[path]\n+            assert isinstance(params_list, list)\n+            params.append(f\"{path}:\" + \",\".join(params_list))\n+\n         stage = create_stage(\n             PipelineStage,\n             repo=self.repo,\n             path=\"dvc.yaml\",\n             cmd=cache[\"cmd\"],\n-            deps=[dep[\"path\"] for dep in cache[\"deps\"]],\n+            params=params,\n+            deps=[dep[\"path\"] for dep in cache.get(\"deps\", [])],\n             outs=[out[\"path\"] for out in cache[\"outs\"]],\n         )\n         StageLoader.fill_from_lock(stage, cache)\n", "issue": "run-cache: fails for params\n```sh\r\n$ echo \"train: 1\\nlr: 2\" > params.yaml\r\n$ dvc run  -n test -p train,lr -o params2.yaml \"cat params.yaml > params2.yaml\"\r\nERROR: failed to reproduce 'dvc.yaml': 'deps'\r\n```\r\nVerbose log:\r\n```sh\r\n------------------------------------------------------------\r\nTraceback (most recent call last):\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/main.py\", line 48, in main\r\n    ret = cmd.run()\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/command/run.py\", line 51, in run\r\n    single_stage=self.args.single_stage,\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/repo/__init__.py\", line 25, in wrapper\r\n    ret = f(repo, *args, **kwargs)\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/repo/scm_context.py\", line 4, in run\r\n    result = method(repo, *args, **kw)\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/repo/run.py\", line 88, in run\r\n    run_cache=kwargs.get(\"run_cache\", True),\r\n  File \"/home/saugat/repos/iterative/dvc/.env/py36/lib/python3.6/site-packages/funcy/decorators.py\", line 39, in wrapper\r\n    return deco(call, *dargs, **dkwargs)\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/stage/decorators.py\", line 35, in rwlocked\r\n    return call()\r\n  File \"/home/saugat/repos/iterative/dvc/.env/py36/lib/python3.6/site-packages/funcy/decorators.py\", line 60, in __call__\r\n    return self._func(*self._args, **self._kwargs)\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/stage/__init__.py\", line 417, in run\r\n    self.save()\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/stage/__init__.py\", line 368, in save\r\n    self.repo.stage_cache.save(self)\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/stage/cache.py\", line 130, in save\r\n    for out in self._uncached_outs(stage, cache):\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/stage/cache.py\", line 107, in _uncached_outs\r\n    cached_stage = self._create_stage(cache)\r\n  File \"/home/saugat/repos/iterative/dvc/dvc/stage/cache.py\", line 88, in _create_stage\r\n    deps=[dep[\"path\"] for dep in cache[\"deps\"]],\r\nKeyError: 'deps'\r\n```\r\n\r\n\r\n\n", "before_files": [{"content": "import logging\nimport os\nfrom contextlib import contextmanager\n\nimport yaml\nfrom funcy import first\nfrom voluptuous import Invalid\n\nfrom dvc.schema import COMPILED_LOCK_FILE_STAGE_SCHEMA\nfrom dvc.serialize import to_single_stage_lockfile\nfrom dvc.stage.loader import StageLoader\nfrom dvc.utils import dict_sha256, relpath\nfrom dvc.utils.fs import makedirs\nfrom dvc.utils.stage import dump_stage_file\n\nlogger = logging.getLogger(__name__)\n\n\ndef _get_cache_hash(cache, key=False):\n    if key:\n        cache[\"outs\"] = [out[\"path\"] for out in cache.get(\"outs\", [])]\n    return dict_sha256(cache)\n\n\ndef _get_stage_hash(stage):\n    if not (stage.cmd and stage.deps and stage.outs):\n        return None\n\n    for dep in stage.deps:\n        if not (dep.scheme == \"local\" and dep.def_path and dep.get_checksum()):\n            return None\n\n    for out in stage.outs:\n        if out.scheme != \"local\" or not out.def_path or out.persist:\n            return None\n\n    return _get_cache_hash(to_single_stage_lockfile(stage), key=True)\n\n\nclass StageCache:\n    def __init__(self, repo):\n        self.repo = repo\n        self.cache_dir = os.path.join(repo.cache.local.cache_dir, \"runs\")\n\n    def _get_cache_dir(self, key):\n        return os.path.join(self.cache_dir, key[:2], key)\n\n    def _get_cache_path(self, key, value):\n        return os.path.join(self._get_cache_dir(key), value)\n\n    def _load_cache(self, key, value):\n        path = self._get_cache_path(key, value)\n\n        try:\n            with open(path) as fobj:\n                return COMPILED_LOCK_FILE_STAGE_SCHEMA(yaml.safe_load(fobj))\n        except FileNotFoundError:\n            return None\n        except (yaml.error.YAMLError, Invalid):\n            logger.warning(\"corrupted cache file '%s'.\", relpath(path))\n            os.unlink(path)\n            return None\n\n    def _load(self, stage):\n        key = _get_stage_hash(stage)\n        if not key:\n            return None\n\n        cache_dir = self._get_cache_dir(key)\n        if not os.path.exists(cache_dir):\n            return None\n\n        for value in os.listdir(cache_dir):\n            cache = self._load_cache(key, value)\n            if cache:\n                return cache\n\n        return None\n\n    def _create_stage(self, cache):\n        from dvc.stage import create_stage, PipelineStage\n\n        stage = create_stage(\n            PipelineStage,\n            repo=self.repo,\n            path=\"dvc.yaml\",\n            cmd=cache[\"cmd\"],\n            deps=[dep[\"path\"] for dep in cache[\"deps\"]],\n            outs=[out[\"path\"] for out in cache[\"outs\"]],\n        )\n        StageLoader.fill_from_lock(stage, cache)\n        return stage\n\n    @contextmanager\n    def _cache_type_copy(self):\n        cache_types = self.repo.cache.local.cache_types\n        self.repo.cache.local.cache_types = [\"copy\"]\n        try:\n            yield\n        finally:\n            self.repo.cache.local.cache_types = cache_types\n\n    def _uncached_outs(self, stage, cache):\n        # NOTE: using temporary stage to avoid accidentally modifying original\n        # stage and to workaround `commit/checkout` not working for uncached\n        # outputs.\n        cached_stage = self._create_stage(cache)\n\n        outs_no_cache = [\n            out.def_path for out in stage.outs if not out.use_cache\n        ]\n\n        # NOTE: using copy link to make it look like a git-tracked file\n        with self._cache_type_copy():\n            for out in cached_stage.outs:\n                if out.def_path in outs_no_cache:\n                    yield out\n\n    def save(self, stage):\n        cache_key = _get_stage_hash(stage)\n        if not cache_key:\n            return\n\n        cache = to_single_stage_lockfile(stage)\n        cache_value = _get_cache_hash(cache)\n\n        existing_cache = self._load_cache(cache_key, cache_value)\n        cache = existing_cache or cache\n\n        for out in self._uncached_outs(stage, cache):\n            out.commit()\n\n        if existing_cache:\n            return\n\n        # sanity check\n        COMPILED_LOCK_FILE_STAGE_SCHEMA(cache)\n\n        path = self._get_cache_path(cache_key, cache_value)\n        dpath = os.path.dirname(path)\n        makedirs(dpath, exist_ok=True)\n        dump_stage_file(path, cache)\n\n    def is_cached(self, stage):\n        return bool(self._load(stage))\n\n    def restore(self, stage):\n        cache = self._load(stage)\n        if not cache:\n            return\n        StageLoader.fill_from_lock(stage, cache)\n\n        for out in self._uncached_outs(stage, cache):\n            out.checkout()\n\n    @staticmethod\n    def _transfer(func, from_remote, to_remote):\n        ret = []\n\n        runs = from_remote.path_info / \"runs\"\n        if not from_remote.exists(runs):\n            return []\n\n        for src in from_remote.walk_files(runs):\n            rel = src.relative_to(from_remote.path_info)\n            dst = to_remote.path_info / rel\n            key = dst.parent\n            # check if any build cache already exists for this key\n            if to_remote.exists(key) and first(to_remote.walk_files(key)):\n                continue\n            func(src, dst)\n            ret.append((src.parent.name, src.name))\n\n        return ret\n\n    def push(self, remote):\n        remote = self.repo.cloud.get_remote(remote)\n        return self._transfer(remote.upload, self.repo.cache.local, remote)\n\n    def pull(self, remote):\n        remote = self.repo.cloud.get_remote(remote)\n        return self._transfer(remote.download, remote, self.repo.cache.local)\n\n    def get_used_cache(self, used_run_cache, *args, **kwargs):\n        from dvc.cache import NamedCache\n\n        cache = NamedCache()\n\n        for key, value in used_run_cache:\n            entry = self._load_cache(key, value)\n            if not entry:\n                continue\n            stage = self._create_stage(entry)\n            cache.update(stage.get_used_cache(*args, **kwargs))\n        return cache\n", "path": "dvc/stage/cache.py"}], "after_files": [{"content": "import logging\nimport os\nfrom contextlib import contextmanager\n\nimport yaml\nfrom funcy import first\nfrom voluptuous import Invalid\n\nfrom dvc.schema import COMPILED_LOCK_FILE_STAGE_SCHEMA\nfrom dvc.serialize import to_single_stage_lockfile\nfrom dvc.stage.loader import StageLoader\nfrom dvc.utils import dict_sha256, relpath\nfrom dvc.utils.fs import makedirs\nfrom dvc.utils.stage import dump_stage_file\n\nlogger = logging.getLogger(__name__)\n\n\ndef _get_cache_hash(cache, key=False):\n    if key:\n        cache[\"outs\"] = [out[\"path\"] for out in cache.get(\"outs\", [])]\n    return dict_sha256(cache)\n\n\ndef _get_stage_hash(stage):\n    if not (stage.cmd and stage.deps and stage.outs):\n        return None\n\n    for dep in stage.deps:\n        if not (dep.scheme == \"local\" and dep.def_path and dep.get_checksum()):\n            return None\n\n    for out in stage.outs:\n        if out.scheme != \"local\" or not out.def_path or out.persist:\n            return None\n\n    return _get_cache_hash(to_single_stage_lockfile(stage), key=True)\n\n\nclass StageCache:\n    def __init__(self, repo):\n        self.repo = repo\n        self.cache_dir = os.path.join(repo.cache.local.cache_dir, \"runs\")\n\n    def _get_cache_dir(self, key):\n        return os.path.join(self.cache_dir, key[:2], key)\n\n    def _get_cache_path(self, key, value):\n        return os.path.join(self._get_cache_dir(key), value)\n\n    def _load_cache(self, key, value):\n        path = self._get_cache_path(key, value)\n\n        try:\n            with open(path) as fobj:\n                return COMPILED_LOCK_FILE_STAGE_SCHEMA(yaml.safe_load(fobj))\n        except FileNotFoundError:\n            return None\n        except (yaml.error.YAMLError, Invalid):\n            logger.warning(\"corrupted cache file '%s'.\", relpath(path))\n            os.unlink(path)\n            return None\n\n    def _load(self, stage):\n        key = _get_stage_hash(stage)\n        if not key:\n            return None\n\n        cache_dir = self._get_cache_dir(key)\n        if not os.path.exists(cache_dir):\n            return None\n\n        for value in os.listdir(cache_dir):\n            cache = self._load_cache(key, value)\n            if cache:\n                return cache\n\n        return None\n\n    def _create_stage(self, cache):\n        from dvc.stage import create_stage, PipelineStage\n\n        params = []\n        for param in cache.get(\"params\", []):\n            if isinstance(param, str):\n                params.append(param)\n                continue\n\n            assert isinstance(param, dict)\n            assert len(param) == 1\n            path = list(param.keys())[0]\n            params_list = param[path]\n            assert isinstance(params_list, list)\n            params.append(f\"{path}:\" + \",\".join(params_list))\n\n        stage = create_stage(\n            PipelineStage,\n            repo=self.repo,\n            path=\"dvc.yaml\",\n            cmd=cache[\"cmd\"],\n            params=params,\n            deps=[dep[\"path\"] for dep in cache.get(\"deps\", [])],\n            outs=[out[\"path\"] for out in cache[\"outs\"]],\n        )\n        StageLoader.fill_from_lock(stage, cache)\n        return stage\n\n    @contextmanager\n    def _cache_type_copy(self):\n        cache_types = self.repo.cache.local.cache_types\n        self.repo.cache.local.cache_types = [\"copy\"]\n        try:\n            yield\n        finally:\n            self.repo.cache.local.cache_types = cache_types\n\n    def _uncached_outs(self, stage, cache):\n        # NOTE: using temporary stage to avoid accidentally modifying original\n        # stage and to workaround `commit/checkout` not working for uncached\n        # outputs.\n        cached_stage = self._create_stage(cache)\n\n        outs_no_cache = [\n            out.def_path for out in stage.outs if not out.use_cache\n        ]\n\n        # NOTE: using copy link to make it look like a git-tracked file\n        with self._cache_type_copy():\n            for out in cached_stage.outs:\n                if out.def_path in outs_no_cache:\n                    yield out\n\n    def save(self, stage):\n        cache_key = _get_stage_hash(stage)\n        if not cache_key:\n            return\n\n        cache = to_single_stage_lockfile(stage)\n        cache_value = _get_cache_hash(cache)\n\n        existing_cache = self._load_cache(cache_key, cache_value)\n        cache = existing_cache or cache\n\n        for out in self._uncached_outs(stage, cache):\n            out.commit()\n\n        if existing_cache:\n            return\n\n        # sanity check\n        COMPILED_LOCK_FILE_STAGE_SCHEMA(cache)\n\n        path = self._get_cache_path(cache_key, cache_value)\n        dpath = os.path.dirname(path)\n        makedirs(dpath, exist_ok=True)\n        dump_stage_file(path, cache)\n\n    def is_cached(self, stage):\n        return bool(self._load(stage))\n\n    def restore(self, stage):\n        cache = self._load(stage)\n        if not cache:\n            return\n        StageLoader.fill_from_lock(stage, cache)\n\n        for out in self._uncached_outs(stage, cache):\n            out.checkout()\n\n    @staticmethod\n    def _transfer(func, from_remote, to_remote):\n        ret = []\n\n        runs = from_remote.path_info / \"runs\"\n        if not from_remote.exists(runs):\n            return []\n\n        for src in from_remote.walk_files(runs):\n            rel = src.relative_to(from_remote.path_info)\n            dst = to_remote.path_info / rel\n            key = dst.parent\n            # check if any build cache already exists for this key\n            if to_remote.exists(key) and first(to_remote.walk_files(key)):\n                continue\n            func(src, dst)\n            ret.append((src.parent.name, src.name))\n\n        return ret\n\n    def push(self, remote):\n        remote = self.repo.cloud.get_remote(remote)\n        return self._transfer(remote.upload, self.repo.cache.local, remote)\n\n    def pull(self, remote):\n        remote = self.repo.cloud.get_remote(remote)\n        return self._transfer(remote.download, remote, self.repo.cache.local)\n\n    def get_used_cache(self, used_run_cache, *args, **kwargs):\n        from dvc.cache import NamedCache\n\n        cache = NamedCache()\n\n        for key, value in used_run_cache:\n            entry = self._load_cache(key, value)\n            if not entry:\n                continue\n            stage = self._create_stage(entry)\n            cache.update(stage.get_used_cache(*args, **kwargs))\n        return cache\n", "path": "dvc/stage/cache.py"}]}