@@ -179,7 +179,10 @@ def unpack_url(
179179
180180
181181def _check_download_dir (
182- link : Link , download_dir : str , hashes : Optional [Hashes ]
182+ link : Link ,
183+ download_dir : str ,
184+ hashes : Optional [Hashes ],
185+ warn_on_hash_mismatch : bool = True ,
183186) -> Optional [str ]:
184187 """Check download_dir for previously downloaded file with correct hash
185188 If a correct file is found return its path else None
@@ -195,10 +198,11 @@ def _check_download_dir(
195198 try :
196199 hashes .check_against_path (download_path )
197200 except HashMismatch :
198- logger .warning (
199- "Previously-downloaded file %s has bad hash. Re-downloading." ,
200- download_path ,
201- )
201+ if warn_on_hash_mismatch :
202+ logger .warning (
203+ "Previously-downloaded file %s has bad hash. Re-downloading." ,
204+ download_path ,
205+ )
202206 os .unlink (download_path )
203207 return None
204208 return download_path
@@ -263,7 +267,7 @@ def __init__(
263267
264268 def _log_preparing_link (self , req : InstallRequirement ) -> None :
265269 """Provide context for the requirement being prepared."""
266- if req .link .is_file and not req .original_link_is_in_wheel_cache :
270+ if req .link .is_file and not req .is_wheel_from_cache :
267271 message = "Processing %s"
268272 information = str (display_path (req .link .file_path ))
269273 else :
@@ -284,7 +288,7 @@ def _log_preparing_link(self, req: InstallRequirement) -> None:
284288 self ._previous_requirement_header = (message , information )
285289 logger .info (message , information )
286290
287- if req .original_link_is_in_wheel_cache :
291+ if req .is_wheel_from_cache :
288292 with indent_log ():
289293 logger .info ("Using cached %s" , req .link .filename )
290294
@@ -485,7 +489,18 @@ def prepare_linked_requirement(
485489 file_path = None
486490 if self .download_dir is not None and req .link .is_wheel :
487491 hashes = self ._get_linked_req_hashes (req )
488- file_path = _check_download_dir (req .link , self .download_dir , hashes )
492+ file_path = _check_download_dir (
493+ req .link ,
494+ self .download_dir ,
495+ hashes ,
496+ # When a locally built wheel has been found in cache, we don't warn
497+ # about re-downloading when the already downloaded wheel hash does
498+ # not match. This is because the hash must be checked against the
499+ # original link, not the cached link. It that case the already
500+ # downloaded file will be removed and re-fetched from cache (which
501+ # implies a hash check against the cache entry's origin.json).
502+ warn_on_hash_mismatch = not req .is_wheel_from_cache ,
503+ )
489504
490505 if file_path is not None :
491506 # The file is already available, so mark it as downloaded
@@ -536,9 +551,35 @@ def _prepare_linked_requirement(
536551 assert req .link
537552 link = req .link
538553
539- self ._ensure_link_req_src_dir (req , parallel_builds )
540554 hashes = self ._get_linked_req_hashes (req )
541555
556+ if hashes and req .is_wheel_from_cache :
557+ assert req .download_info is not None
558+ assert link .is_wheel
559+ assert link .is_file
560+ # We need to verify hashes, and we have found the requirement in the cache
561+ # of locally built wheels.
562+ if (
563+ isinstance (req .download_info .info , ArchiveInfo )
564+ and req .download_info .info .hashes
565+ and hashes .has_one_of (req .download_info .info .hashes )
566+ ):
567+ # At this point we know the requirement was built from a hashable source
568+ # artifact, and we verified that the cache entry's hash of the original
569+ # artifact matches one of the hashes we expect. We don't verify hashes
570+ # against the cached wheel, because the wheel is not the original.
571+ hashes = None
572+ else :
573+ logger .warning (
574+ "The hashes of the source archive found in cache entry "
575+ "don't match, ignoring cached built wheel "
576+ "and re-downloading source."
577+ )
578+ req .link = req .cached_wheel_source_link
579+ link = req .link
580+
581+ self ._ensure_link_req_src_dir (req , parallel_builds )
582+
542583 if link .is_existing_dir ():
543584 local_file = None
544585 elif link .url not in self ._downloaded :
0 commit comments