@@ -549,6 +549,39 @@ def _collect_splicing_config(module, repository):
549549
550550 return config
551551
552+ def _get_annotation_patches (module_ctx , annotations , crate_name , crate_version ):
553+ """Look up patch-related fields from annotations for a specific crate.
554+
555+ Args:
556+ module_ctx: The module context for reading files.
557+ annotations: Dict of crate name to list of annotation JSON strings.
558+ crate_name: The name of the crate to look up.
559+ crate_version: The version of the crate to look up.
560+
561+ Returns:
562+ A tuple of (patches, patch_args, patch_tool, patches_hash).
563+ patches_hash is a hash of patch file contents for cache invalidation.
564+ """
565+
566+ crate_annotations = annotations .get (crate_name , [])
567+ for annotation_json in crate_annotations :
568+ version , data = json .decode (annotation_json )
569+ # Check if version matches ("*" matches all, or exact match, or semver prefix)
570+ if version == "*" or version == crate_version or crate_version .startswith (version ):
571+ patches = data .get ("patches" , None )
572+ patch_args = data .get ("patch_args" , None )
573+ patch_tool = data .get ("patch_tool" , None )
574+ if patches or patch_args or patch_tool :
575+ # Compute hash of patch file contents for cache invalidation
576+ patches_hash = None
577+ if patches :
578+ patch_content = ""
579+ for patch in patches :
580+ patch_content += module_ctx .read (module_ctx .path (Label (patch )))
581+ patches_hash = str (hash (patch_content ))
582+ return (patches , patch_args , patch_tool , patches_hash )
583+ return (None , None , None , None )
584+
552585def _generate_hub_and_spokes (
553586 * ,
554587 module_ctx ,
@@ -732,15 +765,20 @@ def _generate_hub_and_spokes(
732765 version = version .replace ("+" , "-" ),
733766 )
734767
768+ # Look up patches from annotations
769+ ann_patches , ann_patch_args , ann_patch_tool , ann_patches_hash = _get_annotation_patches (module_ctx , annotations , name , version )
770+
735771 if "Http" in repo :
736772 # Replicates functionality in repo_http.j2.
737773 build_file_content = module_ctx .read (crates_dir .get_child ("BUILD.%s-%s.bazel" % (name , version )))
738774 repo = repo ["Http" ]
739775 http_archive (
740776 name = crate_repo_name ,
741- patch_args = repo .get ("patch_args" , None ),
742- patch_tool = repo .get ("patch_tool" , None ),
743- patches = repo .get ("patches" , None ),
777+ # canonical_id forces re-download when patch content changes
778+ canonical_id = ann_patches_hash ,
779+ patch_args = ann_patch_args if ann_patch_args else repo .get ("patch_args" , None ),
780+ patch_tool = ann_patch_tool if ann_patch_tool else repo .get ("patch_tool" , None ),
781+ patches = ann_patches if ann_patches else repo .get ("patches" , None ),
744782 remote_patch_strip = 1 ,
745783 sha256 = repo .get ("sha256" , None ),
746784 type = "tar.gz" ,
@@ -761,9 +799,9 @@ def _generate_hub_and_spokes(
761799 git_repository (
762800 name = crate_repo_name ,
763801 init_submodules = True ,
764- patch_args = repo .get ("patch_args" , None ),
765- patch_tool = repo .get ("patch_tool" , None ),
766- patches = repo .get ("patches" , None ),
802+ patch_args = ann_patch_args if ann_patch_args else repo .get ("patch_args" , None ),
803+ patch_tool = ann_patch_tool if ann_patch_tool else repo .get ("patch_tool" , None ),
804+ patches = ann_patches if ann_patches else repo .get ("patches" , None ),
767805 shallow_since = repo .get ("shallow_since" , None ),
768806 remote = repo ["remote" ],
769807 build_file_content = build_file_content ,
0 commit comments