From 3a7236beb8c0692c327aaeb5341801280d0cd870 Mon Sep 17 00:00:00 2001 From: keertk Date: Mon, 20 Mar 2023 07:54:16 -0700 Subject: [PATCH] Allow WORKSPACE and WORKSPACE-loaded .bzl files to see Bzlmod root module's mappings (#17818) Currently, we evaluate WORKSPACE (`WorkspaceFileFunction`) and WORKSPACE-loaded .bzl files (`BzlLoadFunction` with `BzlLoadValue.KeyForWorkspace`) with the repo mapping purely computed from previous WORKSPACE chunks. This is unlike BUILD-loaded .bzl files from WORKSPACE-defined repos (`BzlLoadFunction` with `BzlLoadValue.KeyForBuild`, which is the same as `RepositoryMappingFunction`), which take the mappings of the Bzlmod root module into account. This CL fixes that discrepancy by doing the same "repo mapping composition" everywhere. Fixes https://github.com/bazelbuild/bazel/issues/17655 RELNOTES: Fixed an issue where WORKSPACE and WORKSPACE-loaded .bzl files couldn't see the Bzlmod root module's mappings when Bzlmod is enabled. PiperOrigin-RevId: 515318590 Change-Id: I4babc922f6cdb932d17ce18d9a9d9d427dbed2eb Co-authored-by: Googler --- .../build/lib/cmdline/RepositoryMapping.java | 40 ++++++++--- .../build/lib/skyframe/BzlLoadFunction.java | 55 ++++++++++----- .../skyframe/RepositoryMappingFunction.java | 20 ++---- .../lib/skyframe/WorkspaceFileFunction.java | 23 +++++-- .../lib/cmdline/RepositoryMappingTest.java | 32 ++++++++- .../devtools/build/lib/rules/repository/BUILD | 1 + .../repository/RepositoryDelegatorTest.java | 2 + .../RepositoryMappingFunctionTest.java | 28 ++++---- src/test/py/bazel/bzlmod/bazel_module_test.py | 67 +++++++++++++++++++ 9 files changed, 206 insertions(+), 62 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java b/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java index a1280ed3fb2dea..0246c930171776 100644 --- a/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java +++ b/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryMapping.java @@ -49,16 +49,18 @@ public abstract class RepositoryMapping { abstract RepositoryName ownerRepo(); public static RepositoryMapping create( - Map repositoryMapping, RepositoryName ownerRepo) { - return new AutoValue_RepositoryMapping( - ImmutableMap.copyOf(Preconditions.checkNotNull(repositoryMapping)), - Preconditions.checkNotNull(ownerRepo)); + Map entries, RepositoryName ownerRepo) { + return createInternal( + Preconditions.checkNotNull(entries), Preconditions.checkNotNull(ownerRepo)); } - public static RepositoryMapping createAllowingFallback( - Map repositoryMapping) { - return new AutoValue_RepositoryMapping( - ImmutableMap.copyOf(Preconditions.checkNotNull(repositoryMapping)), null); + public static RepositoryMapping createAllowingFallback(Map entries) { + return createInternal(Preconditions.checkNotNull(entries), null); + } + + private static RepositoryMapping createInternal( + Map entries, RepositoryName ownerRepo) { + return new AutoValue_RepositoryMapping(ImmutableMap.copyOf(entries), ownerRepo); } /** @@ -68,7 +70,7 @@ public static RepositoryMapping createAllowingFallback( public RepositoryMapping withAdditionalMappings(Map additionalMappings) { HashMap allMappings = new HashMap<>(additionalMappings); allMappings.putAll(entries()); - return new AutoValue_RepositoryMapping(ImmutableMap.copyOf(allMappings), ownerRepo()); + return createInternal(allMappings, ownerRepo()); } /** @@ -114,4 +116,24 @@ public Optional getInverse(RepositoryName postMappingName) { .map(Entry::getKey) .findFirst(); } + + /** + * Creates a new {@link RepositoryMapping} instance that is the equivalent of composing this + * {@link RepositoryMapping} with another one. That is, {@code a.composeWith(b).get(name) === + * b.get(a.get(name))} (treating {@code b} as allowing fallback). + * + *

Since we're treating the result of {@code a.get(name)} as an apparent repo name instead of a + * canonical repo name, this only really makes sense when {@code a} does not use strict deps (i.e. + * allows fallback). + */ + public RepositoryMapping composeWith(RepositoryMapping other) { + Preconditions.checkArgument( + !usesStrictDeps(), "only an allow-fallback mapping can be composed with other mappings"); + HashMap entries = new HashMap<>(other.entries()); + for (Map.Entry entry : entries().entrySet()) { + RepositoryName mappedName = other.get(entry.getValue().getName()); + entries.put(entry.getKey(), mappedName.isVisible() ? mappedName : entry.getValue()); + } + return createInternal(entries, null); + } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java index a20f630289f460..3b9aff37ab7f5f 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java @@ -165,7 +165,7 @@ public static BzlLoadFunction create( // (b) The memory overhead of the extra Skyframe node and edge per bzl file is pure // waste. new InliningAndCachingGetter(packageFactory, hashFunction, bzlCompileCache), - /*cachedBzlLoadDataManager=*/ null); + /* cachedBzlLoadDataManager= */ null); } public static BzlLoadFunction createForInlining( @@ -188,7 +188,7 @@ public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException { BzlLoadValue.Key key = (BzlLoadValue.Key) skyKey.argument(); try { - return computeInternal(key, env, /*inliningState=*/ null); + return computeInternal(key, env, /* inliningState= */ null); } catch (BzlLoadFailedException e) { throw new BzlLoadFunctionException(e); } @@ -455,12 +455,12 @@ private InliningState( static InliningState create(Environment env) { return new InliningState( new RecordingSkyFunctionEnvironment(env, x -> {}, x -> {}, x -> {}), - /*cachedDataBuilder=*/ null, - /*loadStack=*/ new LinkedHashSet<>(), - /*successfulLoads=*/ new HashMap<>(), - /*unsuccessfulLoads=*/ new HashSet<>(), + /* cachedDataBuilder= */ null, + /* loadStack= */ new LinkedHashSet<>(), + /* successfulLoads= */ new HashMap<>(), + /* unsuccessfulLoads= */ new HashSet<>(), // No parent value to mutate - /*childCachedDataHandler=*/ x -> {}); + /* childCachedDataHandler= */ x -> {}); } /** @@ -598,7 +598,10 @@ private StarlarkBuiltinsValue getBuiltins( env.getValueOrThrow(StarlarkBuiltinsValue.key(), BuiltinsFailedException.class); } else { return StarlarkBuiltinsFunction.computeInline( - StarlarkBuiltinsValue.key(), inliningState, packageFactory, /*bzlLoadFunction=*/ this); + StarlarkBuiltinsValue.key(), + inliningState, + packageFactory, + /* bzlLoadFunction= */ this); } } catch (BuiltinsFailedException e) { throw BzlLoadFailedException.builtinsFailed(key.getLabel(), e); @@ -776,7 +779,7 @@ private BzlLoadValue computeInternalWithCompiledBzl( loadValues, loadKeys, programLoads, - /*demoteErrorsToWarnings=*/ !builtins.starlarkSemantics.getBool( + /* demoteErrorsToWarnings= */ !builtins.starlarkSemantics.getBool( BuildLanguageOptions.CHECK_BZL_VISIBILITY), env.getListener()); @@ -845,7 +848,8 @@ private BzlLoadValue computeInternalWithCompiledBzl( private static RepositoryMapping getRepositoryMapping( BzlLoadValue.Key key, StarlarkSemantics semantics, Environment env) throws InterruptedException { - if (key.isBuiltins() && !semantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD)) { + boolean bzlmod = semantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD); + if (key.isBuiltins() && !bzlmod) { // Without Bzlmod, builtins .bzls never have a repo mapping defined for them, so return // without requesting a RepositoryMappingValue. (NB: In addition to being a slight // optimization, this avoids adding a reverse dependency on the special //external package, @@ -862,9 +866,10 @@ private static RepositoryMapping getRepositoryMapping( if (key instanceof BzlLoadValue.KeyForWorkspace) { // Still during workspace file evaluation BzlLoadValue.KeyForWorkspace keyForWorkspace = (BzlLoadValue.KeyForWorkspace) key; + RepositoryMapping pureWorkspaceMapping; if (keyForWorkspace.getWorkspaceChunk() == 0) { // There is no previous workspace chunk - return RepositoryMapping.ALWAYS_FALLBACK; + pureWorkspaceMapping = RepositoryMapping.ALWAYS_FALLBACK; } else { SkyKey workspaceFileKey = WorkspaceFileValue.key( @@ -872,11 +877,26 @@ private static RepositoryMapping getRepositoryMapping( WorkspaceFileValue workspaceFileValue = (WorkspaceFileValue) env.getValue(workspaceFileKey); // Note: we know for sure that the requested WorkspaceFileValue is fully computed so we do // not need to check if it is null - return RepositoryMapping.createAllowingFallback( - workspaceFileValue.getRepositoryMapping().getOrDefault(repoName, ImmutableMap.of())); - // NOTE(wyv): this means that, in the WORKSPACE file, we can't load from a repo generated by - // bzlmod. If that's a problem, we should "fall back" to the bzlmod case below. + pureWorkspaceMapping = + RepositoryMapping.createAllowingFallback( + workspaceFileValue + .getRepositoryMapping() + .getOrDefault(repoName, ImmutableMap.of())); + } + if (!bzlmod) { + // Without Bzlmod, we just return the mapping purely computed from WORKSPACE stuff. + return pureWorkspaceMapping; + } + // If Bzlmod is in play, we need to make sure that pure WORKSPACE mapping is composed with the + // root module's mapping (just like how all WORKSPACE repos can see what the root module sees + // _after_ WORKSPACE evaluation). + RepositoryMappingValue rootModuleMappingValue = + (RepositoryMappingValue) + env.getValue(RepositoryMappingValue.KEY_FOR_ROOT_MODULE_WITHOUT_WORKSPACE_REPOS); + if (rootModuleMappingValue == null) { + return null; } + return pureWorkspaceMapping.composeWith(rootModuleMappingValue.getRepositoryMapping()); } if (key instanceof BzlLoadValue.KeyForBzlmod) { @@ -903,9 +923,8 @@ private static RepositoryMapping getRepositoryMapping( } } - // This is either a .bzl loaded from BUILD files, or a .bzl loaded for bzlmod (in which case the - // .bzl file *has* to be from a Bazel module anyway). So we can just use the full repo mapping - // from RepositoryMappingFunction. + // This is either a .bzl loaded from BUILD files, or a .bzl loaded for bzlmod, so we can just + // use the full repo mapping from RepositoryMappingFunction. RepositoryMappingValue repositoryMappingValue = (RepositoryMappingValue) env.getValue(RepositoryMappingValue.key(repoName)); if (repositoryMappingValue == null) { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java index 74cf9101263ad1..b75288426fa71f 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java @@ -15,7 +15,6 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import com.google.devtools.build.lib.bazel.bzlmod.BazelModuleResolutionValue; import com.google.devtools.build.lib.bazel.bzlmod.ModuleExtensionId; import com.google.devtools.build.lib.bazel.bzlmod.ModuleKey; @@ -213,26 +212,17 @@ private SkyValue computeFromWorkspace( if (externalPackage.containsErrors()) { throw new RepositoryMappingFunctionException(); } + RepositoryMapping workspaceMapping = + RepositoryMapping.createAllowingFallback( + externalPackage.getRepositoryMapping(repositoryName)); if (rootModuleRepoMapping == null) { // This means Bzlmod is disabled. - return RepositoryMappingValue.withMapping( - RepositoryMapping.createAllowingFallback( - externalPackage.getRepositoryMapping(repositoryName))); + return RepositoryMappingValue.withMapping(workspaceMapping); } // If Bzlmod is in play, we need to make sure that WORKSPACE repos see all repos that root // module can see, taking care to compose the existing WORKSPACE mapping with the main repo // mapping from Bzlmod. - return RepositoryMappingValue.withMapping( - RepositoryMapping.createAllowingFallback( - Maps.transformValues( - externalPackage.getRepositoryMapping(repositoryName), - toRepo -> { - RepositoryName mappedName = rootModuleRepoMapping.get(toRepo.getName()); - // If the Bzlmod-only main repo mapping doesn't contain this repo, don't touch - // it. - return mappedName.isVisible() ? mappedName : toRepo; - })) - .withAdditionalMappings(rootModuleRepoMapping)); + return RepositoryMappingValue.withMapping(workspaceMapping.composeWith(rootModuleRepoMapping)); } private static Optional maybeGetModuleExtensionForRepo( diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java index 3228226ef90dae..768586cb067543 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java @@ -120,14 +120,14 @@ public SkyValue compute(SkyKey skyKey, Environment env) RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE.get(env)); boolean useWorkspaceResolvedFile = resolvedFile.isPresent(); + final boolean bzlmod = starlarkSemantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD); boolean useWorkspaceBzlmodFile = false; RootedPath workspaceBzlmodFile = RootedPath.toRootedPath( workspaceFile.getRoot(), workspaceFile.getRootRelativePath().replaceName("WORKSPACE.bzlmod")); // We only need to check WORKSPACE.bzlmod when the resolved file isn't used. - if (!useWorkspaceResolvedFile - && starlarkSemantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD)) { + if (!useWorkspaceResolvedFile && bzlmod) { FileValue workspaceBzlmodFileValue = (FileValue) env.getValue(FileValue.key(workspaceBzlmodFile)); if (workspaceBzlmodFileValue == null) { @@ -266,6 +266,15 @@ public SkyValue compute(SkyKey skyKey, Environment env) .getRepositoryMapping() .getOrDefault(RepositoryName.MAIN, ImmutableMap.of())); } + if (bzlmod) { + RepositoryMappingValue rootModuleMapping = + (RepositoryMappingValue) + env.getValue(RepositoryMappingValue.KEY_FOR_ROOT_MODULE_WITHOUT_WORKSPACE_REPOS); + if (rootModuleMapping == null) { + return null; + } + repoMapping = repoMapping.composeWith(rootModuleMapping.getRepositoryMapping()); + } Package.Builder builder = packageFactory.newExternalPackageBuilder( @@ -274,12 +283,12 @@ public SkyValue compute(SkyKey skyKey, Environment env) if (chunks.isEmpty()) { return new WorkspaceFileValue( buildAndReportEvents(builder, env), - /* loadedModules = */ ImmutableMap.of(), - /* loadToChunkMap = */ ImmutableMap.of(), - /* bindings = */ ImmutableMap.of(), + /* loadedModules= */ ImmutableMap.of(), + /* loadToChunkMap= */ ImmutableMap.of(), + /* bindings= */ ImmutableMap.of(), workspaceFile, - /* idx = */ 0, // first fragment - /* hasNext = */ false); + /* idx= */ 0, // first fragment + /* hasNext= */ false); } List chunk = chunks.get(key.getIndex()); diff --git a/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java b/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java index 0d9cd3baebeabf..7556c3703e6e09 100644 --- a/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java +++ b/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java @@ -47,7 +47,7 @@ public void neverFallback() throws Exception { } @Test - public void additionalMappings() throws Exception { + public void additionalMappings_basic() throws Exception { RepositoryMapping mapping = RepositoryMapping.create( ImmutableMap.of("A", RepositoryName.create("com_foo_bar_a")), @@ -59,4 +59,34 @@ public void additionalMappings() throws Exception { .isEqualTo( RepositoryName.create("C").toNonVisible(RepositoryName.create("fake_owner_repo"))); } + + @Test + public void additionalMappings_precedence() throws Exception { + RepositoryMapping mapping = + RepositoryMapping.createAllowingFallback(ImmutableMap.of("A", RepositoryName.create("A1"))) + .withAdditionalMappings(ImmutableMap.of("A", RepositoryName.create("A2"))); + assertThat(mapping.get("A")).isEqualTo(RepositoryName.create("A1")); + } + + @Test + public void composeWith() throws Exception { + RepositoryMapping mapping = + RepositoryMapping.createAllowingFallback( + ImmutableMap.of( + "A", RepositoryName.create("A_mapped"), "B", RepositoryName.create("B_mapped"))) + .composeWith( + RepositoryMapping.create( + ImmutableMap.of( + "A", + RepositoryName.create("A_mapped_differently"), + "A_mapped", + RepositoryName.create("A_mapped_twice"), + "C", + RepositoryName.create("C_mapped")), + RepositoryName.create("blah"))); + assertThat(mapping.get("A")).isEqualTo(RepositoryName.create("A_mapped_twice")); + assertThat(mapping.get("B")).isEqualTo(RepositoryName.create("B_mapped")); + assertThat(mapping.get("C")).isEqualTo(RepositoryName.create("C_mapped")); + assertThat(mapping.get("D")).isEqualTo(RepositoryName.create("D")); + } } diff --git a/src/test/java/com/google/devtools/build/lib/rules/repository/BUILD b/src/test/java/com/google/devtools/build/lib/rules/repository/BUILD index f9aa10a96925cd..6788a8aafc853b 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/repository/BUILD +++ b/src/test/java/com/google/devtools/build/lib/rules/repository/BUILD @@ -44,6 +44,7 @@ java_library( "//src/main/java/com/google/devtools/build/lib/skyframe:package_lookup_function", "//src/main/java/com/google/devtools/build/lib/skyframe:precomputed_function", "//src/main/java/com/google/devtools/build/lib/skyframe:precomputed_value", + "//src/main/java/com/google/devtools/build/lib/skyframe:repository_mapping_function", "//src/main/java/com/google/devtools/build/lib/skyframe:sky_functions", "//src/main/java/com/google/devtools/build/lib/skyframe:skyframe_cluster", "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/repository", diff --git a/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java b/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java index 5acc2d4a23ebcd..3da83c1234e485 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java @@ -68,6 +68,7 @@ import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy; import com.google.devtools.build.lib.skyframe.PrecomputedFunction; import com.google.devtools.build.lib.skyframe.PrecomputedValue; +import com.google.devtools.build.lib.skyframe.RepositoryMappingFunction; import com.google.devtools.build.lib.skyframe.SkyFunctions; import com.google.devtools.build.lib.skyframe.WorkspaceFileFunction; import com.google.devtools.build.lib.starlarkbuildapi.repository.RepositoryBootstrap; @@ -220,6 +221,7 @@ public void setupDelegator() throws Exception { new IgnoredPackagePrefixesFunction( /*ignoredPackagePrefixesFile=*/ PathFragment.EMPTY_FRAGMENT)) .put(SkyFunctions.RESOLVED_HASH_VALUES, new ResolvedHashesFunction()) + .put(SkyFunctions.REPOSITORY_MAPPING, new RepositoryMappingFunction()) .put( SkyFunctions.MODULE_FILE, new ModuleFileFunction(registryFactory, rootPath, ImmutableMap.of())) diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java index dbeb9b2128de01..44c9a3955eca31 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java @@ -62,25 +62,29 @@ private EvaluationResult eval(SkyKey key) ModifiedFileSet.builder().modify(PathFragment.create("WORKSPACE")).build(), Root.fromPath(rootDirectory)); return SkyframeExecutorTestUtils.evaluate( - getSkyframeExecutor(), key, /*keepGoing=*/ false, reporter); + getSkyframeExecutor(), key, /* keepGoing= */ false, reporter); } @Before public void setUpForBzlmod() throws Exception { setBuildLanguageOptions("--enable_bzlmod"); scratch.file("MODULE.bazel"); + } + + @Override + protected ImmutableList extraPrecomputedValues() throws Exception { registry = FakeRegistry.DEFAULT_FACTORY.newFakeRegistry(scratch.dir("modules").getPathString()); - ModuleFileFunction.REGISTRIES.set( - getSkyframeExecutor().getDifferencerForTesting(), ImmutableList.of(registry.getUrl())); - ModuleFileFunction.IGNORE_DEV_DEPS.set(getSkyframeExecutor().getDifferencerForTesting(), false); - ModuleFileFunction.MODULE_OVERRIDES.set( - getSkyframeExecutor().getDifferencerForTesting(), ImmutableMap.of()); - BazelModuleResolutionFunction.ALLOWED_YANKED_VERSIONS.set( - getSkyframeExecutor().getDifferencerForTesting(), ImmutableList.of()); - BazelModuleResolutionFunction.CHECK_DIRECT_DEPENDENCIES.set( - getSkyframeExecutor().getDifferencerForTesting(), CheckDirectDepsMode.WARNING); - BazelModuleResolutionFunction.BAZEL_COMPATIBILITY_MODE.set( - getSkyframeExecutor().getDifferencerForTesting(), BazelCompatibilityMode.ERROR); + return ImmutableList.of( + PrecomputedValue.injected( + ModuleFileFunction.REGISTRIES, ImmutableList.of(registry.getUrl())), + PrecomputedValue.injected(ModuleFileFunction.IGNORE_DEV_DEPS, false), + PrecomputedValue.injected(ModuleFileFunction.MODULE_OVERRIDES, ImmutableMap.of()), + PrecomputedValue.injected( + BazelModuleResolutionFunction.ALLOWED_YANKED_VERSIONS, ImmutableList.of()), + PrecomputedValue.injected( + BazelModuleResolutionFunction.CHECK_DIRECT_DEPENDENCIES, CheckDirectDepsMode.WARNING), + PrecomputedValue.injected( + BazelModuleResolutionFunction.BAZEL_COMPATIBILITY_MODE, BazelCompatibilityMode.ERROR)); } @Override diff --git a/src/test/py/bazel/bzlmod/bazel_module_test.py b/src/test/py/bazel/bzlmod/bazel_module_test.py index faa9c519132796..156cb8dddfe62a 100644 --- a/src/test/py/bazel/bzlmod/bazel_module_test.py +++ b/src/test/py/bazel/bzlmod/bazel_module_test.py @@ -930,6 +930,73 @@ def testNativePackageRelativeLabel(self): self.assertIn('5th: @@bleb//bleb:bleb', stderr) self.assertIn('6th: @@//bleb:bleb', stderr) + def testWorkspaceEvaluatedBzlCanSeeRootModuleMappings(self): + self.ScratchFile( + 'MODULE.bazel', + [ + 'bazel_dep(name="aaa",version="1.0")', + 'bazel_dep(name="bbb",version="1.0")', + ], + ) + self.ScratchFile( + 'WORKSPACE.bzlmod', + [ + 'local_repository(name="foo", path="foo", repo_mapping={', + ' "@bar":"@baz",', + ' "@my_aaa":"@aaa",', + '})', + 'load("@foo//:test.bzl", "test")', + 'test()', + ], + ) + self.ScratchFile('foo/WORKSPACE') + self.ScratchFile('foo/BUILD', ['filegroup(name="test")']) + self.ScratchFile( + 'foo/test.bzl', + [ + 'def test():', + ' print("1st: " + str(Label("@bar//:z")))', + ' print("2nd: " + str(Label("@my_aaa//:z")))', + ' print("3rd: " + str(Label("@bbb//:z")))', + ' print("4th: " + str(Label("@blarg//:z")))', + ], + ) + + _, _, stderr = self.RunBazel(['build', '@foo//:test'], allow_failure=False) + stderr = '\n'.join(stderr) + # @bar is mapped to @@baz, which Bzlmod doesn't recognize, so we leave it be + self.assertIn('1st: @@baz//:z', stderr) + # @my_aaa is mapped to @@aaa, which Bzlmod remaps to @@aaa~1.0 + self.assertIn('2nd: @@aaa~1.0//:z', stderr) + # @bbb isn't mapped in WORKSPACE, but Bzlmod maps it to @@bbb~1.0 + self.assertIn('3rd: @@bbb~1.0//:z', stderr) + # @blarg isn't mapped by WORKSPACE or Bzlmod + self.assertIn('4th: @@blarg//:z', stderr) + + def testWorkspaceItselfCanSeeRootModuleMappings(self): + self.ScratchFile( + 'MODULE.bazel', + [ + 'bazel_dep(name="hello")', + 'local_path_override(module_name="hello",path="hello")', + ], + ) + self.ScratchFile( + 'WORKSPACE.bzlmod', + [ + 'load("@hello//:world.bzl", "message")', + 'print(message)', + ], + ) + self.ScratchFile('BUILD', ['filegroup(name="a")']) + self.ScratchFile('hello/WORKSPACE') + self.ScratchFile('hello/BUILD') + self.ScratchFile('hello/MODULE.bazel', ['module(name="hello")']) + self.ScratchFile('hello/world.bzl', ['message="I LUV U!"']) + + _, _, stderr = self.RunBazel(['build', ':a'], allow_failure=False) + self.assertIn('I LUV U!', '\n'.join(stderr)) + if __name__ == '__main__': unittest.main()