@@ -213,21 +213,28 @@ def _takes_arg(f: typing.Callable, arg_name: str) -> bool:
213213
214214def unpack_source (
215215 ctx : context .WorkContext ,
216+ req : Requirement ,
217+ version : Version ,
216218 source_filename : pathlib .Path ,
217219) -> tuple [pathlib .Path , bool ]:
218- sdist_root_name = _sdist_root_name (source_filename )
219- unpack_dir = ctx .work_dir / sdist_root_name
220+ # sdist names are less standardized and the names of the directories they
221+ # contain are also not very standard. Force the names into a predictable
222+ # form based on the override module name for the requirement.
223+ req_name = overrides .pkgname_to_override_module (req .name )
224+ expected_name = f"{ req_name } -{ version } "
225+
226+ # The unpack_dir is a parent dir where we put temporary outputs during the
227+ # build process, including the unpacked source in a subdirectory.
228+ unpack_dir = ctx .work_dir / expected_name
220229 if unpack_dir .exists ():
221230 if ctx .cleanup :
222231 logger .debug ("cleaning up %s" , unpack_dir )
223232 shutil .rmtree (unpack_dir )
224233 else :
225234 logger .info ("reusing %s" , unpack_dir )
226235 return (unpack_dir / unpack_dir .name , False )
227- # We create a unique directory based on the sdist name, but that
228- # may not be the same name as the root directory of the content in
229- # the sdist (due to case, punctuation, etc.), so after we unpack
230- # it look for what was created.
236+
237+ # sdists might be tarballs or zip files.
231238 logger .debug ("unpacking %s to %s" , source_filename , unpack_dir )
232239 if str (source_filename ).endswith (".tar.gz" ):
233240 with tarfile .open (source_filename , "r" ) as t :
@@ -242,45 +249,51 @@ def unpack_source(
242249 else :
243250 raise ValueError (f"Do not know how to unpack source archive { source_filename } " )
244251
245- # if tarball named foo-2.3.1.tar.gz was downloaded, then ensure that after unpacking, the source directory's path is foo-2.3.1/foo-2.3.1
252+ # We create a unique directory based on the requirement name, but that may
253+ # not be the same name as the root directory of the content in the sdist
254+ # (due to case, punctuation, etc.), so after we unpack it look for what was
255+ # created and ensure the extracted directory matches the override module
256+ # name and version of the requirement.
246257 unpacked_root_dir = next (iter (unpack_dir .glob ("*" )))
247- new_unpacked_root_dir = unpacked_root_dir .parent / sdist_root_name
248- if unpacked_root_dir . name != new_unpacked_root_dir . name :
258+ if unpacked_root_dir .name != expected_name :
259+ desired_name = unpacked_root_dir . parent / expected_name
249260 try :
250- shutil .move (str (unpacked_root_dir ), str (new_unpacked_root_dir ))
261+ shutil .move (
262+ str (unpacked_root_dir ),
263+ str (desired_name ),
264+ )
251265 except Exception as err :
252266 raise Exception (
253- f"Could not rename { unpacked_root_dir .name } to { new_unpacked_root_dir . name } : { err } "
267+ f"Could not rename { unpacked_root_dir .name } to { desired_name } : { err } "
254268 ) from err
269+ unpacked_root_dir = desired_name
255270
256- return (new_unpacked_root_dir , True )
271+ return (unpacked_root_dir , True )
257272
258273
259274def patch_source (
260275 ctx : context .WorkContext ,
261276 source_root_dir : pathlib .Path ,
262277 req : Requirement ,
278+ version : Version ,
263279) -> None :
264- # Flag to check whether patch has been applied
265- has_applied = False
266- # apply any unversioned patch first
267- for p in overrides . patches_for_source_dir (
268- ctx . settings . patches_dir , overrides . pkgname_to_override_module ( req . name )
280+ patch_count = 0
281+ for p in overrides . patches_for_requirement (
282+ patches_dir = ctx . settings . patches_dir ,
283+ req = req ,
284+ version = version ,
269285 ):
270286 _apply_patch (p , source_root_dir )
271- has_applied = True
272-
273- # make sure that we don't apply the generic unversioned patch again
274- if source_root_dir .name != overrides .pkgname_to_override_module (req .name ):
275- for p in overrides .patches_for_source_dir (
276- ctx .settings .patches_dir , source_root_dir .name
277- ):
278- _apply_patch (p , source_root_dir )
279- has_applied = True
287+ patch_count += 1
280288
289+ logger .debug ("%s: applied %d patches" , req .name , patch_count )
281290 # If no patch has been applied, call warn for old patch
282- if not has_applied :
283- _warn_for_old_patch (source_root_dir , ctx .settings .patches_dir )
291+ if not patch_count :
292+ _warn_for_old_patch (
293+ req = req ,
294+ version = version ,
295+ patches_dir = ctx .settings .patches_dir ,
296+ )
284297
285298
286299def _apply_patch (patch : pathlib .Path , source_root_dir : pathlib .Path ):
@@ -290,18 +303,20 @@ def _apply_patch(patch: pathlib.Path, source_root_dir: pathlib.Path):
290303
291304
292305def _warn_for_old_patch (
293- source_root_dir : pathlib .Path ,
306+ req : Requirement ,
307+ version : Version ,
294308 patches_dir : pathlib .Path ,
295309) -> None :
296- # Get the req name as per the source_root_dir naming conventions
297- req_name = source_root_dir .name .rsplit ("-" , 1 )[0 ]
298-
299310 # Filter the patch directories using regex
300- patch_directories = overrides .get_patch_directories (patches_dir , source_root_dir )
311+ patch_directories = overrides .get_versioned_patch_directories (
312+ patches_dir = patches_dir , req = req
313+ )
301314
302315 for dirs in patch_directories :
303316 for p in dirs .iterdir ():
304- logger .warning (f"{ req_name } : patch { p } exists but will not be applied" )
317+ logger .warning (
318+ f"{ req .name } : patch { p } exists but will not be applied for version { version } "
319+ )
305320
306321
307322def write_build_meta (
@@ -366,7 +381,12 @@ def default_prepare_source(
366381 source_filename : pathlib .Path ,
367382 version : Version ,
368383) -> tuple [pathlib .Path , bool ]:
369- source_root_dir , is_new = unpack_source (ctx , source_filename )
384+ source_root_dir , is_new = unpack_source (
385+ ctx = ctx ,
386+ req = req ,
387+ version = version ,
388+ source_filename = source_filename ,
389+ )
370390 if is_new :
371391 prepare_new_source (
372392 ctx = ctx ,
@@ -387,7 +407,7 @@ def prepare_new_source(
387407
388408 `default_prepare_source` runs this function when the sources are new.
389409 """
390- patch_source (ctx , source_root_dir , req )
410+ patch_source (ctx , source_root_dir , req , version )
391411 pyproject .apply_project_override (
392412 ctx = ctx ,
393413 req = req ,
0 commit comments