Skip to content

Commit ee0a8fa

Browse files
authored
Merge pull request #3075 from efiop/assert_stage
rwlock: check that .dvc/lock is locked
2 parents 249f6c5 + 1dcce1d commit ee0a8fa

File tree

7 files changed

+23
-8
lines changed

7 files changed

+23
-8
lines changed

dvc/lock.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ def unlock(self):
6868
self._lock.close()
6969
self._lock = None
7070

71+
@property
72+
def is_locked(self):
73+
return bool(self._lock)
74+
7175
def __enter__(self):
7276
self.lock()
7377

dvc/repo/destroy.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
from dvc.utils.fs import remove
2+
from . import locked
23

34

4-
def destroy(self):
5-
for stage in self.stages:
5+
@locked
6+
def _destroy_stages(repo):
7+
for stage in repo.stages:
68
stage.remove(remove_outs=False)
79

8-
remove(self.dvc_dir)
10+
11+
# NOTE: not locking `destroy`, as `remove` will need to delete `.dvc` dir,
12+
# which will cause issues on Windows, as `.dvc/lock` will be busy.
13+
def destroy(repo):
14+
_destroy_stages(repo)
15+
remove(repo.dvc_dir)

dvc/stage.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ def rwlocked(call, read=None, write=None):
143143

144144
stage = call._args[0]
145145

146+
assert stage.repo.lock.is_locked
147+
146148
def _chain(names):
147149
return [
148150
item.path_info

tests/func/test_repro.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ def check_already_cached(self, stage):
841841

842842
patch_run = patch.object(stage, "_run", wraps=stage._run)
843843

844-
with self.dvc.state:
844+
with self.dvc.lock, self.dvc.state:
845845
with patch_download as mock_download:
846846
with patch_checkout as mock_checkout:
847847
with patch_run as mock_run:

tests/func/test_run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,8 @@ def test_run_deterministic_overwrite(deterministic_run):
655655

656656

657657
def test_run_deterministic_callback(deterministic_run):
658-
deterministic_run.stage.remove()
658+
with deterministic_run.stage.repo.lock:
659+
deterministic_run.stage.remove()
659660
deterministic_run.deps = []
660661
deterministic_run.run()
661662
with mock.patch("dvc.prompt.confirm", return_value=True):

tests/func/test_stage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def test_ignored_in_checksum(self):
108108
d = load_stage_file(stage.relpath)
109109
self.assertNotIn(Stage.PARAM_WDIR, d.keys())
110110

111-
with self.dvc.state:
111+
with self.dvc.lock, self.dvc.state:
112112
stage = Stage.load(self.dvc, stage.relpath)
113113
self.assertFalse(stage.changed())
114114

tests/unit/test_stage.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,6 @@ def test_stage_run_ignore_sigint(dvc_repo, mocker):
111111
def test_always_changed(dvc_repo):
112112
stage = Stage(dvc_repo, "path", always_changed=True)
113113
stage.save()
114-
assert stage.changed()
115-
assert stage.status()["path"] == ["always changed"]
114+
with dvc_repo.lock:
115+
assert stage.changed()
116+
assert stage.status()["path"] == ["always changed"]

0 commit comments

Comments
 (0)