fix(perf): only load a stage/.dvc file if the target is an address to that stage (#10838)

This commit is contained in:
skshetry
2025-08-13 15:54:04 +05:45
committed by GitHub
parent 748c45655e
commit 4b1adfd646
7 changed files with 182 additions and 33 deletions
+18 -1
View File
@@ -8,7 +8,7 @@ import pytest
from dulwich.porcelain import remove as git_rm
from dvc.cli import main
from dvc.dvcfile import PROJECT_FILE, load_file
from dvc.dvcfile import PROJECT_FILE, FileMixin, SingleStageFile, load_file
from dvc.exceptions import CheckoutError, CheckoutErrorSuggestGit, NoOutputOrStageError
from dvc.fs import system
from dvc.stage.exceptions import StageFileDoesNotExistError
@@ -754,3 +754,20 @@ def test_checkout_cleanup_properly_on_untracked_nested_directories(tmp_dir, scm,
dvc.checkout(force=True)
assert (tmp_dir / "datasets").read_text() == {"dir1": {"file1": "file1"}}
def test_checkout_loads_specific_file(tmp_dir, dvc, mocker):
tmp_dir.dvc_gen("foo", "foo")
tmp_dir.dvc_gen("bar", "bar")
(tmp_dir / "bar").unlink()
(tmp_dir / "foo").unlink()
f = SingleStageFile(dvc, "foo.dvc")
spy = mocker.spy(FileMixin, "_load")
assert dvc.checkout("foo.dvc") == {"added": ["foo"], "deleted": [], "modified": []}
spy.assert_called_with(f)
assert (tmp_dir / "foo").exists()
assert not (tmp_dir / "bar").exists()
+36
View File
@@ -7,6 +7,7 @@ import pytest
import dvc_data
from dvc.cli import main
from dvc.dvcfile import FileMixin, SingleStageFile
from dvc.exceptions import CheckoutError
from dvc.repo.open_repo import clean_repos
from dvc.scm import CloneError
@@ -678,3 +679,38 @@ def test_pull_granular_excluding_import_that_cannot_be_pulled(
dvc.pull()
with pytest.raises(CloneError, match="SCM error"):
dvc.pull(imp_stage.addressing)
def test_loads_single_file(tmp_dir, dvc, local_remote, mocker):
tmp_dir.dvc_gen("foo", "foo")
tmp_dir.dvc_gen("bar", "bar")
foo_dvcfile = SingleStageFile(dvc, "foo.dvc")
bar_dvcfile = SingleStageFile(dvc, "bar.dvc")
spy = mocker.spy(FileMixin, "_load")
assert dvc.push("foo.dvc") == 1
spy.assert_called_with(foo_dvcfile)
spy.reset_mock()
assert dvc.push("bar.dvc") == 1
spy.assert_called_with(bar_dvcfile)
spy.reset_mock()
dvc.cache.local.clear()
(tmp_dir / "bar").unlink()
(tmp_dir / "foo").unlink()
assert dvc.pull("foo.dvc") == {
"added": ["foo"],
"deleted": [],
"fetched": 1,
"modified": [],
}
spy.assert_called_with(foo_dvcfile)
assert (tmp_dir / "foo").exists()
assert not (tmp_dir / "bar").exists()
spy.reset_mock()
assert dvc.fetch("bar.dvc") == 1
spy.assert_called_with(bar_dvcfile)
+30 -1
View File
@@ -4,7 +4,8 @@ from itertools import chain
import pytest
from pygtrie import Trie
from dvc.repo.index import Index
from dvc.exceptions import NoOutputOrStageError
from dvc.repo.index import Index, index_from_targets
from dvc.stage import Stage
@@ -402,3 +403,31 @@ def test_data_index(tmp_dir, dvc, local_cloud, erepo_dir):
assert data.storage_map[("ifoo_partial",)].remote.read_only
assert data.storage_map[("idir_partial",)].remote.read_only
def test_index_from_targets(tmp_dir, dvc):
stage1 = dvc.stage.add(name="stage1", cmd="echo hello")
stage2 = dvc.stage.add(name="stage2", cmd="echo hello world")
(foo_stage,) = tmp_dir.dvc_gen("foo", "foo")
index = index_from_targets(dvc, ["stage1"])
assert index.stages == [stage1]
index = index_from_targets(dvc, ["stage2"])
assert index.stages == [stage2]
index = index_from_targets(dvc, ["dvc.yaml"])
assert set(index.stages) == {stage1, stage2}
index = index_from_targets(dvc, ["dvc.yaml:stage2"])
assert index.stages == [stage2]
index = index_from_targets(dvc, ["foo.dvc"])
assert index.stages == [foo_stage]
index = index_from_targets(dvc, ["stage1", "foo.dvc"])
assert set(index.stages) == {foo_stage, stage1}
with pytest.raises(NoOutputOrStageError):
index = index_from_targets(dvc, ["not-existing-stage"])