Skip to content

Commit e378131

Browse files
authored
Provision lock (#2516)
1 parent d41bd62 commit e378131

File tree

5 files changed

+47
-2
lines changed

5 files changed

+47
-2
lines changed

Diff for: CONTRIBUTORS

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Marc Schlaich
8080
Marius Gedminas
8181
Mariusz Rusiniak
8282
Mark Hirota
83+
Masen Furer
8384
Matt Good
8485
Matt Jeffery
8586
Matthew Kenigsberg

Diff for: docs/changelog/2515.bugfix.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Multiple tox instances no longer clobber the ``.tox`` directory when
2+
``provision_tox_env`` is used. - by :user:`masenf`

Diff for: docs/config.rst

+5
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ Global settings are defined under the ``tox`` section as:
7676
When tox is invoked with the ``--no-provision`` flag,
7777
the provision won't be attempted, tox will fail instead.
7878

79+
.. versionchanged:: 3.27.0
80+
81+
When provisioning, tox will take a lock to ensure exclusive access to the
82+
`provision_tox_env` and avoid clobbering by other tox instances.
83+
7984
.. warning::
8085

8186
The new virtual environment will only contain dependencies specified by the :conf:`requires` keyword.

Diff for: src/tox/session/commands/provision.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import os
55

66
from tox.exception import InvocationError
7+
from tox.reporter import verbosity0
8+
from tox.util.lock import hold_lock
79

810

911
def provision_tox(provision_venv, args):
@@ -21,5 +23,9 @@ def provision_tox(provision_venv, args):
2123

2224

2325
def ensure_meta_env_up_to_date(provision_venv):
24-
if provision_venv.setupenv():
25-
provision_venv.finishvenv()
26+
config = provision_venv.envconfig.config
27+
lock_file = config.toxworkdir.join("{}.lock".format(config.provision_tox_env))
28+
29+
with hold_lock(lock_file, verbosity0):
30+
if provision_venv.setupenv():
31+
provision_venv.finishvenv()

Diff for: tests/integration/test_provision_int.py

+31
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,34 @@ def test_provision_interrupt_child(initproj, monkeypatch, capfd, signal_type):
134134
out,
135135
"\n".join(repr(i) for i in all_process),
136136
)
137+
138+
139+
@pytest.mark.skipif("sys.platform == 'win32'", reason="pyenv does not exists on Windows")
140+
def test_provision_race(initproj, cmd, monkeypatch):
141+
initproj(
142+
"pkg123-0.7",
143+
filedefs={
144+
"tox.ini": """\
145+
[tox]
146+
skipsdist=True
147+
minversion = 3.7.0
148+
requires =
149+
setuptools == 40.6.3
150+
[testenv]
151+
commands=python -c "import sys; print(sys.executable); raise SystemExit(1)"
152+
[testenv:x2]
153+
""",
154+
},
155+
)
156+
157+
procs = [
158+
subprocess.Popen(
159+
[sys.executable, "-m", "tox", "-e", "py", "-vv"],
160+
stdout=subprocess.PIPE,
161+
)
162+
for _ in range(2)
163+
]
164+
for proc in procs:
165+
stdout, stderr = proc.communicate()
166+
assert proc.returncode != 0
167+
assert b".tox/.tox/bin/python -m virtualenv" in stdout

0 commit comments

Comments
 (0)