From 1239e48500c1ee4b3675cbb97399c33bea80c892 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Sat, 24 Jan 2026 18:26:41 +0000 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20enhance=20circ?= =?UTF-8?q?ular=20dependency=20detection=20in=20Bazel=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add cycle detection logic to process_mcfunction rule to prevent implicit circular dependencies during build. The DataPackInfo provider now includes transitive_pack_ids field for tracking dependency closure. Backward compatible with existing providers. Related to issue about circular dependency detection. --- rule/process_mcfunction.bzl | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/rule/process_mcfunction.bzl b/rule/process_mcfunction.bzl index 1d26a17..e9dbbf0 100644 --- a/rule/process_mcfunction.bzl +++ b/rule/process_mcfunction.bzl @@ -21,6 +21,7 @@ DataPackInfo = provider( "pack_id", # The ID of the pack (namespace) "data_root", # Path to the data directory root (relative to workspace) "pack_root", # Path to the pack root directory (relative to workspace) + "transitive_pack_ids", # Set of all pack IDs in the transitive dependency closure ], ) @@ -95,12 +96,39 @@ def _process_mcfunction_impl(ctx): }, ) - # Create DataPackInfo for this pack + # Collect transitive pack IDs from dependencies and detect cycles + transitive_pack_ids = {} + for dep in ctx.attr.deps: + if DataPackInfo in dep: + dep_info = dep[DataPackInfo] + # Handle backward compatibility: old providers may not have transitive_pack_ids field + dep_transitive_pack_ids = [] + if hasattr(dep_info, "transitive_pack_ids"): + dep_transitive_pack_ids = dep_info.transitive_pack_ids + # Check if this pack_id already appears in dep's transitive closure (direct cycle) + if ctx.attr.pack_id in dep_transitive_pack_ids: + fail("Circular dependency detected: pack '%s' depends on pack '%s' which already depends on '%s' through transitive dependencies" % ( + ctx.attr.pack_id, dep_info.pack_id, ctx.attr.pack_id + )) + # Add dep's pack_id and its transitive pack_ids + transitive_pack_ids[dep_info.pack_id] = True + for pid in dep_transitive_pack_ids: + transitive_pack_ids[pid] = True + + # Check for direct self-dependency (should be caught by Bazel but just in case) + if ctx.attr.pack_id in transitive_pack_ids: + fail("Circular dependency detected: pack '%s' depends on itself through transitive dependencies" % ctx.attr.pack_id) + + # Include own pack_id in transitive closure (reflexive) + transitive_pack_ids[ctx.attr.pack_id] = True + + # Create DataPackInfo for this pack with transitive closure # This allows dependent packs to get information about this pack pack_info = DataPackInfo( pack_id = ctx.attr.pack_id, data_root = "data", pack_root = ctx.label.package, + transitive_pack_ids = list(transitive_pack_ids.keys()), ) return [