@@ -549,6 +549,40 @@ 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+
570+ # Check if version matches ("*" matches all, or exact match, or semver prefix)
571+ if version == "*" or version == crate_version or crate_version .startswith (version ):
572+ patches = data .get ("patches" , None )
573+ patch_args = data .get ("patch_args" , None )
574+ patch_tool = data .get ("patch_tool" , None )
575+ if patches or patch_args or patch_tool :
576+ # Compute hash of patch file contents for cache invalidation
577+ patches_hash = None
578+ if patches :
579+ patch_content = ""
580+ for patch in patches :
581+ patch_content += module_ctx .read (module_ctx .path (Label (patch )))
582+ patches_hash = str (hash (patch_content ))
583+ return (patches , patch_args , patch_tool , patches_hash )
584+ return (None , None , None , None )
585+
552586def _generate_hub_and_spokes (
553587 * ,
554588 module_ctx ,
@@ -732,15 +766,20 @@ def _generate_hub_and_spokes(
732766 version = version .replace ("+" , "-" ),
733767 )
734768
769+ # Look up patches from annotations
770+ ann_patches , ann_patch_args , ann_patch_tool , ann_patches_hash = _get_annotation_patches (module_ctx , annotations , name , version )
771+
735772 if "Http" in repo :
736773 # Replicates functionality in repo_http.j2.
737774 build_file_content = module_ctx .read (crates_dir .get_child ("BUILD.%s-%s.bazel" % (name , version )))
738775 repo = repo ["Http" ]
739776 http_archive (
740777 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 ),
778+ # canonical_id forces re-download when patch content changes
779+ canonical_id = ann_patches_hash ,
780+ patch_args = ann_patch_args if ann_patch_args else repo .get ("patch_args" , None ),
781+ patch_tool = ann_patch_tool if ann_patch_tool else repo .get ("patch_tool" , None ),
782+ patches = ann_patches if ann_patches else repo .get ("patches" , None ),
744783 remote_patch_strip = 1 ,
745784 sha256 = repo .get ("sha256" , None ),
746785 type = "tar.gz" ,
@@ -761,9 +800,9 @@ def _generate_hub_and_spokes(
761800 git_repository (
762801 name = crate_repo_name ,
763802 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 ),
803+ patch_args = ann_patch_args if ann_patch_args else repo .get ("patch_args" , None ),
804+ patch_tool = ann_patch_tool if ann_patch_tool else repo .get ("patch_tool" , None ),
805+ patches = ann_patches if ann_patches else repo .get ("patches" , None ),
767806 shallow_since = repo .get ("shallow_since" , None ),
768807 remote = repo ["remote" ],
769808 build_file_content = build_file_content ,
0 commit comments