Skip to content

Commit 98aa09c

Browse files
committed
Prevent infinite recursion with pip wheel with $TMPDIR in $PWD
During a build of extension module within `pip wheel` the source directory is recursively copied in a temporary directory. See pypa#7555 When the temporary directory is inside the source directory (for example by setting `TMPDIR=$PWD/tmp`) this caused an infinite recursion that ended in: [Errno 36] File name too long We prevent that buy never copying the target to the target in _copy_source_tree. Fixes pypa#7872
1 parent 104b665 commit 98aa09c

File tree

5 files changed

+33
-5
lines changed

5 files changed

+33
-5
lines changed

news/7872.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Prevent an infinite recursion with ``pip wheel`` when ``$TMPDIR`` is within the source directory.

src/pip/_internal/operations/prepare.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,25 @@ def _copy2_ignoring_special_files(src, dest):
156156

157157
def _copy_source_tree(source, target):
158158
# type: (str, str) -> None
159+
target_abspath = os.path.abspath(target)
160+
target_basename = os.path.basename(target_abspath)
161+
target_dirname = os.path.dirname(target_abspath)
162+
159163
def ignore(d, names):
160164
# type: (str, List[str]) -> List[str]
161-
# Pulling in those directories can potentially be very slow,
162-
# exclude the following directories if they appear in the top
163-
# level dir (and only it).
164-
# See discussion at https://github.com/pypa/pip/pull/6770
165-
return ['.tox', '.nox'] if d == source else []
165+
skipped = [] # type: List[str]
166+
if d == source:
167+
# Pulling in those directories can potentially be very slow,
168+
# exclude the following directories if they appear in the top
169+
# level dir (and only it).
170+
# See discussion at https://github.com/pypa/pip/pull/6770
171+
skipped += ['.tox', '.nox']
172+
if os.path.abspath(d) == target_dirname:
173+
# Prevent an infinite recursion if the target is in source.
174+
# This can happen when TMPDIR is set to ${PWD}/...
175+
# and we copy PWD to TMPDIR.
176+
skipped += [target_basename]
177+
return skipped
166178

167179
kwargs = dict(ignore=ignore, symlinks=True) # type: CopytreeKwargs
168180

tests/data/src/extension/extension.c

Whitespace-only changes.

tests/data/src/extension/setup.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from setuptools import Extension, setup
2+
3+
module = Extension('extension', sources=['extension.c'])
4+
setup(name='extension', version='0.0.1', ext_modules = [module])

tests/functional/test_wheel.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,17 @@ def test_pip_wheel_with_user_set_in_config(script, data, common_wheels):
289289
assert "Successfully built withpyproject" in result.stdout, result.stdout
290290

291291

292+
def test_pip_wheel_ext_module_with_tmpdir_inside(script, data, common_wheels):
293+
tmpdir = data.src / 'extension/tmp'
294+
tmpdir.mkdir()
295+
script.environ['TMPDIR'] = str(tmpdir)
296+
result = script.pip(
297+
'wheel', data.src / 'extension',
298+
'--no-index', '-f', common_wheels
299+
)
300+
assert "Successfully built extension" in result.stdout, result.stdout
301+
302+
292303
@pytest.mark.network
293304
def test_pep517_wheels_are_not_confused_with_other_files(script, tmpdir, data):
294305
"""Check correct wheels are copied. (#6196)

0 commit comments

Comments
 (0)