blob: fb1e9adcea3645838e1aab90a23f62f5b84852ae [file] [log] [blame]
// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package com.google.devtools.build.lib.bazel.bzlmod;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import javax.annotation.Nullable;
/**
* A SkyFunction that computes the {@link RepositoryMapping#entries()} for the repos generated by a
* module extension. While the repos differ in {@link RepositoryMapping#ownerRepo()}, the entries
* are identical and sharing the instance ensures that memory and CPU usage are only linear in the
* number of repos.
*/
public class ModuleExtensionRepoMappingEntriesFunction implements SkyFunction {
@Override
@Nullable
public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
BazelDepGraphValue bazelDepGraphValue =
(BazelDepGraphValue) env.getValue(BazelDepGraphValue.KEY);
if (bazelDepGraphValue == null) {
return null;
}
var moduleExtensionId = ((ModuleExtensionRepoMappingEntriesValue.Key) skyKey).argument();
var extensionEvalValue =
(SingleExtensionEvalValue) env.getValue(SingleExtensionEvalValue.key(moduleExtensionId));
if (extensionEvalValue == null) {
return null;
}
return computeRepoMappingEntries(moduleExtensionId, extensionEvalValue, bazelDepGraphValue);
}
/**
* Calculates repo mappings for a repo generated from a module extension. Such a repo can see all
* repos generated by the same module extension, as well as all repos that the Bazel module
* hosting the extension can see (see above).
*/
private ModuleExtensionRepoMappingEntriesValue computeRepoMappingEntries(
ModuleExtensionId extensionId,
SingleExtensionEvalValue extensionEvalValue,
BazelDepGraphValue bazelDepGraphValue) {
// Find the key of the module containing this extension. This will be used to compute additional
// mappings -- any repo generated by an extension contained in the module "foo" can additionally
// see all repos that "foo" can see.
ModuleKey moduleKey =
bazelDepGraphValue
.getCanonicalRepoNameLookup()
.get(extensionId.getBzlFileLabel().getRepository());
// NOTE(wyv): This means that if "foo" has a bazel_dep with the repo name "bar", and the
// extension generates an internal repo name "bar", then within a repo generated by the
// extension, "bar" will refer to the latter. We should explore a way to differentiate between
// the two to avoid any surprises.
ImmutableMap.Builder<String, RepositoryName> entries = ImmutableMap.builder();
entries.putAll(bazelDepGraphValue.getFullRepoMapping(moduleKey).entries());
entries.putAll(extensionEvalValue.getCanonicalRepoNameToInternalNames().inverse());
return ModuleExtensionRepoMappingEntriesValue.create(entries.buildKeepingLast(), moduleKey);
}
}