diff --git a/dvc/stage/cache.py b/dvc/stage/cache.py index d76e7befc..a7acefadd 100644 --- a/dvc/stage/cache.py +++ b/dvc/stage/cache.py @@ -180,7 +180,7 @@ class StageCache: dump_yaml(tmp, cache) self.repo.odb.local.move(tmp, path) - def restore(self, stage, run_cache=True, pull=False): + def restore(self, stage, run_cache=True, pull=False, dry=False): from .serialize import to_single_stage_lockfile if not _can_hash(stage): @@ -195,14 +195,15 @@ class StageCache: else: if not run_cache: # backward compatibility raise RunCacheNotFoundError(stage) - stage.save_deps() + if not dry: + stage.save_deps() cache = self._load(stage) if not cache: raise RunCacheNotFoundError(stage) cached_stage = self._create_stage(cache, wdir=stage.wdir) - if pull: + if pull and not dry: for objs in cached_stage.get_used_objs().values(): self.repo.cloud.pull(objs) @@ -213,7 +214,8 @@ class StageCache: "Stage '%s' is cached - skipping run, checking out outputs", stage.addressing, ) - cached_stage.checkout() + if not dry: + cached_stage.checkout() def transfer(self, from_odb, to_odb): from dvc.fs import HTTPFileSystem, LocalFileSystem diff --git a/dvc/stage/run.py b/dvc/stage/run.py index 7287fe76a..ca76dcb2f 100644 --- a/dvc/stage/run.py +++ b/dvc/stage/run.py @@ -139,14 +139,16 @@ def cmd_run(stage, dry=False, checkpoint_func=None, run_env=None): def run_stage( stage, dry=False, force=False, checkpoint_func=None, run_env=None, **kwargs ): - if not (dry or force or checkpoint_func): + if not (force or checkpoint_func): from .cache import RunCacheNotFoundError try: - stage.repo.stage_cache.restore(stage, **kwargs) - return + stage.repo.stage_cache.restore(stage, dry=dry, **kwargs) + if not dry: + return except RunCacheNotFoundError: - stage.save_deps() + if not dry: + stage.save_deps() run = cmd_run if dry else unlocked_repo(cmd_run) run(stage, dry=dry, checkpoint_func=checkpoint_func, run_env=run_env) diff --git a/tests/func/test_run_cache.py b/tests/func/test_run_cache.py index 5061268ed..e39733424 100644 --- a/tests/func/test_run_cache.py +++ b/tests/func/test_run_cache.py @@ -33,7 +33,7 @@ def test_restore(tmp_dir, dvc, run_copy, mocker): (stage,) = dvc.reproduce("copy-foo-bar") - mock_restore.assert_called_once_with(stage) + mock_restore.assert_called_once_with(stage, dry=False) mock_run.assert_not_called() assert (tmp_dir / "bar").exists() and not (tmp_dir / "foo").unlink() assert (tmp_dir / PIPELINE_LOCK).exists() @@ -100,7 +100,7 @@ def test_memory_for_multiple_runs_of_same_stage( assert (tmp_dir / PIPELINE_LOCK).exists() assert (tmp_dir / "bar").read_text() == "foobar" mock_run.assert_not_called() - mock_restore.assert_called_once_with(stage) + mock_restore.assert_called_once_with(stage, dry=False) mock_restore.reset_mock() (tmp_dir / PIPELINE_LOCK).unlink() @@ -109,7 +109,7 @@ def test_memory_for_multiple_runs_of_same_stage( assert (tmp_dir / "bar").read_text() == "foo" mock_run.assert_not_called() - mock_restore.assert_called_once_with(stage) + mock_restore.assert_called_once_with(stage, dry=False) assert (tmp_dir / "bar").exists() and not (tmp_dir / "foo").unlink() assert (tmp_dir / PIPELINE_LOCK).exists() @@ -138,7 +138,7 @@ def test_memory_runs_of_multiple_stages(tmp_dir, dvc, run_copy, mocker): assert (tmp_dir / "foo.bak").read_text() == "foo" assert (tmp_dir / PIPELINE_LOCK).exists() mock_run.assert_not_called() - mock_restore.assert_called_once_with(stage) + mock_restore.assert_called_once_with(stage, dry=False) mock_restore.reset_mock() (stage,) = dvc.reproduce("backup-bar") @@ -146,7 +146,7 @@ def test_memory_runs_of_multiple_stages(tmp_dir, dvc, run_copy, mocker): assert (tmp_dir / "bar.bak").read_text() == "bar" assert (tmp_dir / PIPELINE_LOCK).exists() mock_run.assert_not_called() - mock_restore.assert_called_once_with(stage) + mock_restore.assert_called_once_with(stage, dry=False) def test_restore_pull(tmp_dir, dvc, run_copy, mocker, local_remote): @@ -168,7 +168,7 @@ def test_restore_pull(tmp_dir, dvc, run_copy, mocker, local_remote): (stage,) = dvc.reproduce("copy-foo-bar", pull=True) - mock_restore.assert_called_once_with(stage, pull=True) + mock_restore.assert_called_once_with(stage, pull=True, dry=False) mock_run.assert_not_called() assert mock_checkout.call_count == 2 assert (tmp_dir / "bar").exists() and not (tmp_dir / "foo").unlink() diff --git a/tests/unit/stage/test_run.py b/tests/unit/stage/test_run.py index c464b8adc..263300fcc 100644 --- a/tests/unit/stage/test_run.py +++ b/tests/unit/stage/test_run.py @@ -13,9 +13,9 @@ from dvc.stage.run import run_stage (["mycmd1 arg1", "mycmd2 arg2"], ["> mycmd1 arg1", "> mycmd2 arg2"]), ], ) -def test_run_stage_dry(caplog, cmd, expected): +def test_run_stage_dry(caplog, dvc, cmd, expected): with caplog.at_level(level=logging.INFO, logger="dvc"): - stage = Stage(None, "stage.dvc", cmd=cmd) + stage = Stage(dvc, "stage.dvc", cmd=cmd) run_stage(stage, dry=True) expected.insert(0, "Running stage 'stage.dvc':")