|
24 | 24 | PreviousBuildDirError,
|
25 | 25 | VcsHashUnsupported,
|
26 | 26 | )
|
27 |
| -from pip._internal.utils.filesystem import copy2_fixed |
28 | 27 | from pip._internal.utils.hashes import MissingHashes
|
29 | 28 | from pip._internal.utils.logging import indent_log
|
30 |
| -from pip._internal.utils.misc import ( |
31 |
| - display_path, |
32 |
| - hide_url, |
33 |
| - path_to_display, |
34 |
| - rmtree, |
35 |
| -) |
| 29 | +from pip._internal.utils.misc import display_path, hide_url |
36 | 30 | from pip._internal.utils.temp_dir import TempDirectory
|
37 | 31 | from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
38 | 32 | from pip._internal.utils.unpacking import unpack_file
|
@@ -133,59 +127,6 @@ def get_http_url(
|
133 | 127 | return File(from_path, content_type)
|
134 | 128 |
|
135 | 129 |
|
136 |
| -def _copy2_ignoring_special_files(src, dest): |
137 |
| - # type: (str, str) -> None |
138 |
| - """Copying special files is not supported, but as a convenience to users |
139 |
| - we skip errors copying them. This supports tools that may create e.g. |
140 |
| - socket files in the project source directory. |
141 |
| - """ |
142 |
| - try: |
143 |
| - copy2_fixed(src, dest) |
144 |
| - except shutil.SpecialFileError as e: |
145 |
| - # SpecialFileError may be raised due to either the source or |
146 |
| - # destination. If the destination was the cause then we would actually |
147 |
| - # care, but since the destination directory is deleted prior to |
148 |
| - # copy we ignore all of them assuming it is caused by the source. |
149 |
| - logger.warning( |
150 |
| - "Ignoring special file error '%s' encountered copying %s to %s.", |
151 |
| - str(e), |
152 |
| - path_to_display(src), |
153 |
| - path_to_display(dest), |
154 |
| - ) |
155 |
| - |
156 |
| - |
157 |
| -def _copy_source_tree(source, target): |
158 |
| - # 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 |
| - |
163 |
| - def ignore(d, names): |
164 |
| - # type: (str, List[str]) -> List[str] |
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 |
178 |
| - |
179 |
| - kwargs = dict(ignore=ignore, symlinks=True) # type: CopytreeKwargs |
180 |
| - |
181 |
| - if not PY2: |
182 |
| - # Python 2 does not support copy_function, so we only ignore |
183 |
| - # errors on special file copy in Python 3. |
184 |
| - kwargs['copy_function'] = _copy2_ignoring_special_files |
185 |
| - |
186 |
| - shutil.copytree(source, target, **kwargs) |
187 |
| - |
188 |
| - |
189 | 130 | def get_file_url(
|
190 | 131 | link, # type: Link
|
191 | 132 | download_dir=None, # type: Optional[str]
|
@@ -239,11 +180,9 @@ def unpack_url(
|
239 | 180 | unpack_vcs_link(link, location)
|
240 | 181 | return None
|
241 | 182 |
|
242 |
| - # If it's a url to a local directory |
| 183 | + # If it's a url to a local directory, we build in-place. |
| 184 | + # There is nothing to be done here. |
243 | 185 | if link.is_existing_dir():
|
244 |
| - if os.path.isdir(location): |
245 |
| - rmtree(location) |
246 |
| - _copy_source_tree(link.file_path, location) |
247 | 186 | return None
|
248 | 187 |
|
249 | 188 | # file urls
|
@@ -415,21 +354,25 @@ def prepare_linked_requirement(
|
415 | 354 | with indent_log():
|
416 | 355 | # Since source_dir is only set for editable requirements.
|
417 | 356 | assert req.source_dir is None
|
418 |
| - req.ensure_has_source_dir(self.build_dir, autodelete_unpacked) |
419 |
| - # If a checkout exists, it's unwise to keep going. version |
420 |
| - # inconsistencies are logged later, but do not fail the |
421 |
| - # installation. |
422 |
| - # FIXME: this won't upgrade when there's an existing |
423 |
| - # package unpacked in `req.source_dir` |
424 |
| - if os.path.exists(os.path.join(req.source_dir, 'setup.py')): |
425 |
| - raise PreviousBuildDirError( |
426 |
| - "pip can't proceed with requirements '{}' due to a" |
427 |
| - " pre-existing build directory ({}). This is " |
428 |
| - "likely due to a previous installation that failed" |
429 |
| - ". pip is being responsible and not assuming it " |
430 |
| - "can delete this. Please delete it and try again." |
431 |
| - .format(req, req.source_dir) |
432 |
| - ) |
| 357 | + if link.is_existing_dir(): |
| 358 | + # Build local directories in place. |
| 359 | + req.source_dir = link.file_path |
| 360 | + else: |
| 361 | + req.ensure_has_source_dir(self.build_dir, autodelete_unpacked) |
| 362 | + # If a checkout exists, it's unwise to keep going. version |
| 363 | + # inconsistencies are logged later, but do not fail the |
| 364 | + # installation. |
| 365 | + # FIXME: this won't upgrade when there's an existing |
| 366 | + # package unpacked in `req.source_dir` |
| 367 | + if os.path.exists(os.path.join(req.source_dir, 'setup.py')): |
| 368 | + raise PreviousBuildDirError( |
| 369 | + "pip can't proceed with requirements '{}' due to a" |
| 370 | + " pre-existing build directory ({}). This is " |
| 371 | + "likely due to a previous installation that failed" |
| 372 | + ". pip is being responsible and not assuming it " |
| 373 | + "can delete this. Please delete it and try again." |
| 374 | + .format(req, req.source_dir) |
| 375 | + ) |
433 | 376 |
|
434 | 377 | # Now that we have the real link, we can tell what kind of
|
435 | 378 | # requirements we have and raise some more informative errors
|
|
0 commit comments