diff --git a/dvc/commands/data_sync.py b/dvc/commands/data_sync.py index ce84d05a8..a04b8f602 100644 --- a/dvc/commands/data_sync.py +++ b/dvc/commands/data_sync.py @@ -40,6 +40,7 @@ class CmdDataPull(CmdDataBase): recursive=self.args.recursive, run_cache=self.args.run_cache, glob=self.args.glob, + allow_missing=self.args.allow_missing, ) self.log_summary(stats) except (CheckoutError, DvcException) as exc: @@ -197,6 +198,12 @@ def add_parser(subparsers, _parent_parser): default=False, help=argparse.SUPPRESS, ) + pull_parser.add_argument( + "--allow-missing", + action="store_true", + default=False, + help="Ignore errors if some of the files or directories are missing.", + ) pull_parser.set_defaults(func=CmdDataPull) # Push diff --git a/dvc/repo/pull.py b/dvc/repo/pull.py index 93ae72f6c..300847581 100644 --- a/dvc/repo/pull.py +++ b/dvc/repo/pull.py @@ -25,6 +25,7 @@ def pull( # noqa: PLR0913 run_cache=False, glob=False, odb: Optional["ObjectDB"] = None, + allow_missing=False, ): if isinstance(targets, str): targets = [targets] @@ -48,6 +49,7 @@ def pull( # noqa: PLR0913 with_deps=with_deps, force=force, recursive=recursive, + allow_missing=allow_missing, ) stats["fetched"] = processed_files_count diff --git a/tests/func/test_data_cloud.py b/tests/func/test_data_cloud.py index 1f5e59ae5..286e01ce1 100644 --- a/tests/func/test_data_cloud.py +++ b/tests/func/test_data_cloud.py @@ -7,6 +7,7 @@ from flaky.flaky_decorator import flaky import dvc_data from dvc.cli import main +from dvc.exceptions import CheckoutError from dvc.external_repo import clean_repos from dvc.stage.exceptions import StageNotFound from dvc.testing.remote_tests import TestRemote # noqa, pylint: disable=unused-import @@ -561,3 +562,17 @@ def test_target_remote(tmp_dir, dvc, make_remote): "6b18131dc289fd37006705affe961ef8.dir", "b8a9f715dbb64fd5c56e7783c6820a61", } + + +def test_pull_allow_missing(tmp_dir, dvc, local_remote): + dvc.stage.add(name="bar", outs=["bar"], cmd="echo bar > bar") + + with pytest.raises(CheckoutError): + dvc.pull() + + tmp_dir.dvc_gen("foo", "foo") + dvc.push() + clean(["foo"], dvc) + + stats = dvc.pull(allow_missing=True) + assert stats["fetched"] == 1 diff --git a/tests/unit/command/test_data_sync.py b/tests/unit/command/test_data_sync.py index 776b56955..a8eca7ad2 100644 --- a/tests/unit/command/test_data_sync.py +++ b/tests/unit/command/test_data_sync.py @@ -58,6 +58,7 @@ def test_pull(mocker): "--recursive", "--run-cache", "--glob", + "--allow-missing", ] ) assert cli_args.func == CmdDataPull @@ -79,6 +80,7 @@ def test_pull(mocker): recursive=True, run_cache=True, glob=True, + allow_missing=True, )