diff --git a/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java b/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java index f4778e45bbb744..3a6c620623a16e 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java +++ b/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java @@ -18,6 +18,7 @@ import com.google.devtools.build.lib.cmdline.BazelModuleContext; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.RepositoryMapping; +import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.Collection; import net.starlark.java.eval.EvalException; @@ -121,9 +122,32 @@ static AllowlistEntry create(String apparentRepoName, PathFragment packagePrefix } final boolean allows(Label label, RepositoryMapping repoMapping) { - return label.getRepository().equals(repoMapping.get(apparentRepoName())) + return reposMatch(apparentRepoName(), label.getRepository(), repoMapping) && label.getPackageFragment().startsWith(packagePrefix()); } + + private static boolean reposMatch( + String allowedName, RepositoryName givenName, RepositoryMapping repoMapping) { + if (givenName.equals(RepositoryName.MAIN)) { + // The main repository may be one of the allowlisted rulesets, in which case we need to fall + // back to interpreting allowedName as the apparent repo name. This is not a performance + // concern since: + // * In Bazel, the main repo is not expected to use private API unless it is one of the + // allowlisted rulesets. For these rulesets, it is acceptable to pay the cost of a failed + // RepositoryMapping lookup, which is expensive because it uses SpellChecker to construct + // error messages. The only other case in which this cost is paid is if the main repo + // attempts to use private APIs and subsequently fails. + // * In Blaze, the repo mapping is always trivial and lookups are cheap. + return allowedName.equals(RepositoryName.MAIN.getName()) + || repoMapping.get(allowedName).isMain(); + } + if (givenName.equals(RepositoryName.BAZEL_TOOLS)) { + return allowedName.equals(RepositoryName.BAZEL_TOOLS.getName()); + } + // allowedName is a module name and givenName is a real canonical repo name, so it belongs to + // any version of that module if and only if it contains + as a prefix. + return givenName.getName().startsWith(allowedName + "+"); + } } /** @@ -186,7 +210,7 @@ public static void failIfLabelOutsideAllowlist( */ public static boolean isNotAllowed( Label label, RepositoryMapping repoMapping, Collection allowlist) { - if (label.getRepository().getName().equals("_builtins")) { + if (label.getRepository().equals(RepositoryName.BUILTINS)) { return false; } return allowlist.stream().noneMatch(e -> e.allows(label, repoMapping));