Revert "build in place"

This reverts commit 88e6e6bc5c.
This commit is contained in:
Pradyun Gedam 2020-05-12 05:24:28 +05:30
parent 1b90e1bccf
commit 0bd624275d
No known key found for this signature in database
GPG Key ID: DA17C4B29CB32E4B
3 changed files with 66 additions and 35 deletions

View File

@ -732,18 +732,11 @@ You can install local projects by specifying the project path to pip::
$ pip install path/to/SomeProject $ pip install path/to/SomeProject
pip treats this directory like an unpacked source archive, and directly During regular installation, pip will copy the entire project directory to a
attempts installation. temporary location and install from there. The exception is that pip will
exclude .tox and .nox directories present in the top level of the project from
being copied.
Prior to pip 20.1, pip copied the entire project directory to a temporary
location and attempted installation from that directory. This approach was the
cause of several performance issues, as well as various issues arising when the
project directory depends on its parent directory (such as the presence of a
VCS directory). The main user visible effect of this change is that secondary
build artifacts, if any, would be created in the local directory, whereas
earlier they were created in a temporary copy of the directory and then
deleted. This notably includes the ``build`` and ``.egg-info`` directories in
the case of the setuptools backend.
.. _`editable-installs`: .. _`editable-installs`:

View File

@ -27,7 +27,12 @@ from pip._internal.exceptions import (
from pip._internal.utils.filesystem import copy2_fixed from pip._internal.utils.filesystem import copy2_fixed
from pip._internal.utils.hashes import MissingHashes from pip._internal.utils.hashes import MissingHashes
from pip._internal.utils.logging import indent_log from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import display_path, hide_url, path_to_display from pip._internal.utils.misc import (
display_path,
hide_url,
path_to_display,
rmtree,
)
from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from pip._internal.utils.unpacking import unpack_file from pip._internal.utils.unpacking import unpack_file
@ -234,9 +239,11 @@ def unpack_url(
unpack_vcs_link(link, location) unpack_vcs_link(link, location)
return None return None
# If it's a url to a local directory, we build in-place. # If it's a url to a local directory
# There is nothing to be done here.
if link.is_existing_dir(): if link.is_existing_dir():
if os.path.isdir(location):
rmtree(location)
_copy_source_tree(link.file_path, location)
return None return None
# file urls # file urls
@ -408,25 +415,21 @@ class RequirementPreparer(object):
with indent_log(): with indent_log():
# Since source_dir is only set for editable requirements. # Since source_dir is only set for editable requirements.
assert req.source_dir is None assert req.source_dir is None
if link.is_existing_dir(): req.ensure_has_source_dir(self.build_dir, autodelete_unpacked)
# Build local directories in place. # If a checkout exists, it's unwise to keep going. version
req.source_dir = link.file_path # inconsistencies are logged later, but do not fail the
else: # installation.
req.ensure_has_source_dir(self.build_dir, autodelete_unpacked) # FIXME: this won't upgrade when there's an existing
# If a checkout exists, it's unwise to keep going. version # package unpacked in `req.source_dir`
# inconsistencies are logged later, but do not fail the if os.path.exists(os.path.join(req.source_dir, 'setup.py')):
# installation. raise PreviousBuildDirError(
# FIXME: this won't upgrade when there's an existing "pip can't proceed with requirements '{}' due to a"
# package unpacked in `req.source_dir` " pre-existing build directory ({}). This is "
if os.path.exists(os.path.join(req.source_dir, 'setup.py')): "likely due to a previous installation that failed"
raise PreviousBuildDirError( ". pip is being responsible and not assuming it "
"pip can't proceed with requirements '{}' due to a" "can delete this. Please delete it and try again."
" pre-existing build directory ({}). This is " .format(req, req.source_dir)
"likely due to a previous installation that failed" )
". pip is being responsible and not assuming it "
"can delete this. Please delete it and try again."
.format(req, req.source_dir)
)
# Now that we have the real link, we can tell what kind of # Now that we have the real link, we can tell what kind of
# requirements we have and raise some more informative errors # requirements we have and raise some more informative errors

View File

@ -214,5 +214,40 @@ class Test_unpack_url(object):
unpack_url(dist_url, self.build_dir, unpack_url(dist_url, self.build_dir,
downloader=self.no_downloader, downloader=self.no_downloader,
download_dir=self.download_dir) download_dir=self.download_dir)
# test that nothing was copied to build_dir since we build in place assert os.path.isdir(os.path.join(self.build_dir, 'fspkg'))
assert not os.path.exists(os.path.join(self.build_dir, 'fspkg'))
@pytest.mark.parametrize('exclude_dir', [
'.nox',
'.tox'
])
def test_unpack_url_excludes_expected_dirs(tmpdir, exclude_dir):
src_dir = tmpdir / 'src'
dst_dir = tmpdir / 'dst'
src_included_file = src_dir.joinpath('file.txt')
src_excluded_dir = src_dir.joinpath(exclude_dir)
src_excluded_file = src_dir.joinpath(exclude_dir, 'file.txt')
src_included_dir = src_dir.joinpath('subdir', exclude_dir)
# set up source directory
src_excluded_dir.mkdir(parents=True)
src_included_dir.mkdir(parents=True)
src_included_file.touch()
src_excluded_file.touch()
dst_included_file = dst_dir.joinpath('file.txt')
dst_excluded_dir = dst_dir.joinpath(exclude_dir)
dst_excluded_file = dst_dir.joinpath(exclude_dir, 'file.txt')
dst_included_dir = dst_dir.joinpath('subdir', exclude_dir)
src_link = Link(path_to_url(src_dir))
unpack_url(
src_link,
dst_dir,
Mock(side_effect=AssertionError),
download_dir=None
)
assert not os.path.isdir(dst_excluded_dir)
assert not os.path.isfile(dst_excluded_file)
assert os.path.isfile(dst_included_file)
assert os.path.isdir(dst_included_dir)