Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 52 additions & 6 deletions crate_universe/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,40 @@ def _collect_splicing_config(module, repository):

return config

def _get_annotation_patches(module_ctx, annotations, crate_name, crate_version):
"""Look up patch-related fields from annotations for a specific crate.

Args:
module_ctx: The module context for reading files.
annotations: Dict of crate name to list of annotation JSON strings.
crate_name: The name of the crate to look up.
crate_version: The version of the crate to look up.

Returns:
A tuple of (patches, patch_args, patch_tool, patches_hash).
patches_hash is a hash of patch file contents for cache invalidation.
"""

crate_annotations = annotations.get(crate_name, [])
for annotation_json in crate_annotations:
version, data = json.decode(annotation_json)

# Check if version matches ("*" matches all, or exact match, or semver prefix)
if version == "*" or version == crate_version or crate_version.startswith(version):
patches = data.get("patches", None)
patch_args = data.get("patch_args", None)
patch_tool = data.get("patch_tool", None)
if patches or patch_args or patch_tool:
# Compute hash of patch file contents for cache invalidation
patches_hash = None
if patches:
patch_content = ""
for patch in patches:
patch_content += module_ctx.read(module_ctx.path(Label(patch)))
patches_hash = str(hash(patch_content))
return (patches, patch_args, patch_tool, patches_hash)
return (None, None, None, None)

def _generate_hub_and_spokes(
*,
module_ctx,
Expand Down Expand Up @@ -732,15 +766,20 @@ def _generate_hub_and_spokes(
version = version.replace("+", "-"),
)

# Look up patches from annotations
ann_patches, ann_patch_args, ann_patch_tool, ann_patches_hash = _get_annotation_patches(module_ctx, annotations, name, version)

if "Http" in repo:
# Replicates functionality in repo_http.j2.
build_file_content = module_ctx.read(crates_dir.get_child("BUILD.%s-%s.bazel" % (name, version)))
repo = repo["Http"]
http_archive(
name = crate_repo_name,
patch_args = repo.get("patch_args", None),
patch_tool = repo.get("patch_tool", None),
patches = repo.get("patches", None),
# canonical_id forces re-download when patch content changes
canonical_id = ann_patches_hash,
patch_args = ann_patch_args if ann_patch_args else repo.get("patch_args", None),
patch_tool = ann_patch_tool if ann_patch_tool else repo.get("patch_tool", None),
patches = ann_patches if ann_patches else repo.get("patches", None),
remote_patch_strip = 1,
sha256 = repo.get("sha256", None),
type = "tar.gz",
Expand All @@ -761,9 +800,9 @@ def _generate_hub_and_spokes(
git_repository(
name = crate_repo_name,
init_submodules = True,
patch_args = repo.get("patch_args", None),
patch_tool = repo.get("patch_tool", None),
patches = repo.get("patches", None),
patch_args = ann_patch_args if ann_patch_args else repo.get("patch_args", None),
patch_tool = ann_patch_tool if ann_patch_tool else repo.get("patch_tool", None),
patches = ann_patches if ann_patches else repo.get("patches", None),
shallow_since = repo.get("shallow_since", None),
remote = repo["remote"],
build_file_content = build_file_content,
Expand Down Expand Up @@ -992,6 +1031,13 @@ def _crate_impl(module_ctx):
repo_specific_annotations = {}
for annotation_tag in mod.tags.annotation:
annotation_dict = structs.to_dict(annotation_tag)

# Watch patch files so changes trigger repository re-generation.
# This must be done before patches are stringified downstream.
for patch_label in annotation_dict.get("patches", []):
if patch_label:
module_ctx.watch(module_ctx.path(patch_label))

if "build_script_data_select" in annotation_dict:
annotation_dict["build_script_data"] = struct(
common = annotation_dict["build_script_data"],
Expand Down
8 changes: 8 additions & 0 deletions crate_universe/private/generate_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,14 @@ def compile_config(
if unexpected:
fail("The following annotations use `additive_build_file` which is not supported for {}: {}".format(repository_name, unexpected))

# Watch patch files so changes trigger repository re-generation.
if repository_ctx:
for _name, data in annotations.items():
patches = data.get("patches", None)
if patches:
for patch in patches:
repository_ctx.watch(repository_ctx.path(Label(patch)))

# Deprecated: Apply `generate_target_compatible_with` to `render_config`.
if not generate_target_compatible_with:
# buildifier: disable=print
Expand Down
Loading