aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/Package.java123
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java35
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java35
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java63
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingValue.java110
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java2
9 files changed, 367 insertions, 16 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index 7e15bd2b42..f0f79d4d7e 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -25,6 +25,7 @@ import com.google.common.collect.Lists;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.CollectionUtils;
import com.google.devtools.build.lib.collect.ImmutableSortedKeyMap;
import com.google.devtools.build.lib.events.Event;
@@ -180,6 +181,20 @@ public class Package {
private License defaultLicense;
private Set<License.DistributionType> defaultDistributionSet;
+ /**
+ * The map from each repository to that repository's remappings map.
+ * This is only used in the //external package, it is an empty map for all other packages.
+ * For example, an entry of {"@foo" : {"@x", "@y"}} indicates that, within repository foo,
+ * "@x" should be remapped to "@y".
+ */
+ private ImmutableMap<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>>
+ externalPackageRepositoryMappings;
+
+ /**
+ * The map of repository reassignments for BUILD packages. This will be empty for packages
+ * within the main workspace.
+ */
+ private ImmutableMap<RepositoryName, RepositoryName> repositoryMapping;
/**
* The names of the package() attributes that declare default values for rule
@@ -225,6 +240,49 @@ public class Package {
}
/**
+ * Returns the repository mapping for the requested external repository.
+ *
+ * @throws UnsupportedOperationException if called from a package other than
+ * the //external package
+ */
+ public ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping(
+ RepositoryName repository) {
+ if (!isWorkspace()) {
+ throw new UnsupportedOperationException("Can only access the external package repository"
+ + "mappings from the //external package");
+ }
+ return externalPackageRepositoryMappings.getOrDefault(repository, ImmutableMap.of());
+ }
+
+ /**
+ * Returns the workspace mappings for the repository with the given absolute name.
+ *
+ * @throws LabelSyntaxException if repository is not a valid {@link RepositoryName}
+ */
+ public ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping(
+ String repository) throws LabelSyntaxException {
+ RepositoryName repositoryName = RepositoryName.create(repository);
+ return getRepositoryMapping(repositoryName);
+ }
+
+ /**
+ * Gets the global name for a repository within an external repository.
+ *
+ * <p>{@code localName} is a repository name reference found in a BUILD file within a repository
+ * external to the main workspace. This method returns the main workspace's global remapped name
+ * for {@code localName}.
+ */
+ public RepositoryName getGlobalName(RepositoryName localName) {
+ RepositoryName globalname = repositoryMapping.get(localName);
+ return globalname != null ? globalname : localName;
+ }
+
+ /** Returns whether we are in the WORKSPACE file or not. */
+ public boolean isWorkspace() {
+ return getPackageIdentifier().equals(Label.EXTERNAL_PACKAGE_IDENTIFIER);
+ }
+
+ /**
* Package initialization: part 2 of 3: sets this package's default header
* strictness checking.
*
@@ -335,6 +393,20 @@ public class Package {
this.posts = ImmutableList.copyOf(builder.posts);
this.registeredExecutionPlatforms = ImmutableList.copyOf(builder.registeredExecutionPlatforms);
this.registeredToolchains = ImmutableList.copyOf(builder.registeredToolchains);
+ this.repositoryMapping = builder.repositoryMapping;
+ ImmutableMap.Builder<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>>
+ repositoryMappingsBuilder = ImmutableMap.builder();
+ if (!builder.externalPackageRepositoryMappings.isEmpty() && !builder.isWorkspace()) {
+ // 'repo_mapping' should only be used in the //external package, i.e. should only appear
+ // in WORKSPACE files. Currently, if someone tries to use 'repo_mapping' in a BUILD rule, they
+ // will get a "no such attribute" error. This check is to protect against a 'repo_mapping'
+ // attribute being added to a rule in the future.
+ throw new IllegalArgumentException(
+ "'repo_mapping' may only be used in the //external package");
+ }
+ builder.externalPackageRepositoryMappings.forEach((k, v) ->
+ repositoryMappingsBuilder.put(k, ImmutableMap.copyOf(v)));
+ this.externalPackageRepositoryMappings = repositoryMappingsBuilder.build();
}
/**
@@ -729,6 +801,13 @@ public class Package {
*/
protected Package pkg;
+ // The map from each repository to that repository's remappings map.
+ // This is only used in the //external package, it is an empty map for all other packages.
+ private final HashMap<RepositoryName, HashMap<RepositoryName, RepositoryName>>
+ externalPackageRepositoryMappings = new HashMap<>();
+ // The map of repository reassignments for BUILD packages loaded within external repositories.
+ // It will be empty for packages within the main workspace.
+ private ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of();
private Path filename = null;
private Label buildFileLabel = null;
private InputFile buildFile = null;
@@ -802,6 +881,50 @@ public class Package {
}
/**
+ * Updates the externalPackageRepositoryMappings entry for {@code repoWithin}. Adds new
+ * entry from {@code localName} to {@code mappedName} in {@code repoWithin}'s map.
+ *
+ * @param repoWithin the RepositoryName within which the mapping should apply
+ * @param localName the RepositoryName that actually appears in the WORKSPACE and BUILD files
+ * in the {@code repoWithin} repository
+ * @param mappedName the RepositoryName by which localName should be referenced
+ */
+ public Builder addRepositoryMappingEntry(
+ RepositoryName repoWithin, RepositoryName localName, RepositoryName mappedName) {
+ HashMap<RepositoryName, RepositoryName> mapping =
+ externalPackageRepositoryMappings
+ .computeIfAbsent(repoWithin, (RepositoryName k) -> new HashMap<>());
+ mapping.put(localName, mappedName);
+ return this;
+ }
+
+ /** Adds all the mappings from a given {@link Package}. */
+ public Builder addRepositoryMappings(Package aPackage) {
+ ImmutableMap<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>>
+ repositoryMappings = aPackage.externalPackageRepositoryMappings;
+ for (Map.Entry<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>> repositoryName :
+ repositoryMappings.entrySet()) {
+ for (Map.Entry<RepositoryName, RepositoryName> repositoryNameRepositoryNameEntry :
+ repositoryName.getValue().entrySet()) {
+ addRepositoryMappingEntry(
+ repositoryName.getKey(),
+ repositoryNameRepositoryNameEntry.getKey(),
+ repositoryNameRepositoryNameEntry.getValue());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Sets the repository mapping for a regular, BUILD file package (i.e. not the //external
+ * package)
+ */
+ Builder setRepositoryMapping(ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) {
+ this.repositoryMapping = repositoryMapping;
+ return this;
+ }
+
+ /**
* Sets the name of this package's BUILD file.
*/
Builder setFilename(Path filename) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index 71bf904666..d9da36f945 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -26,6 +26,7 @@ import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.LabelValidator;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
@@ -1250,6 +1251,7 @@ public final class PackageFactory {
new AstParseResult(buildFileAST, localReporterForParsing);
return createPackageFromAst(
workspaceName,
+ /*repositoryMapping=*/ ImmutableMap.of(),
packageId,
buildFile,
astParseResult,
@@ -1274,6 +1276,7 @@ public final class PackageFactory {
public Package.Builder createPackageFromAst(
String workspaceName,
+ ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
PackageIdentifier packageId,
Path buildFile,
AstParseResult astParseResult,
@@ -1297,7 +1300,8 @@ public final class PackageFactory {
defaultVisibility,
skylarkSemantics,
imports,
- skylarkFileDependencies);
+ skylarkFileDependencies,
+ repositoryMapping);
} catch (InterruptedException e) {
globber.onInterrupt();
throw e;
@@ -1599,7 +1603,8 @@ public final class PackageFactory {
RuleVisibility defaultVisibility,
SkylarkSemantics skylarkSemantics,
Map<String, Extension> imports,
- ImmutableList<Label> skylarkFileDependencies)
+ ImmutableList<Label> skylarkFileDependencies,
+ ImmutableMap<RepositoryName, RepositoryName> repositoryMapping)
throws InterruptedException {
Package.Builder pkgBuilder = new Package.Builder(packageBuilderHelper.createFreshPackage(
packageId, ruleClassProvider.getRunfilesPrefix()));
@@ -1622,7 +1627,8 @@ public final class PackageFactory {
// set default_visibility once, be reseting the PackageBuilder.defaultVisibilitySet flag.
.setDefaultVisibilitySet(false)
.setSkylarkFileDependencies(skylarkFileDependencies)
- .setWorkspaceName(workspaceName);
+ .setWorkspaceName(workspaceName)
+ .setRepositoryMapping(repositoryMapping);
Event.replayEventsOn(eventHandler, pastEvents);
for (Postable post : pastPosts) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index b9d86ad461..132c511c04 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.LabelValidator;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.events.NullEventHandler;
@@ -55,6 +56,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
@@ -278,6 +280,7 @@ public class WorkspaceFactory {
}
builder.addRegisteredExecutionPlatforms(aPackage.getRegisteredExecutionPlatforms());
builder.addRegisteredToolchains(aPackage.getRegisteredToolchains());
+ builder.addRepositoryMappings(aPackage);
for (Rule rule : aPackage.getTargets(Rule.class)) {
try {
// The old rule references another Package instance and we wan't to keep the invariant that
@@ -466,8 +469,8 @@ public class WorkspaceFactory {
};
/**
- * Returns a function-value implementing the build rule "ruleClass" (e.g. cc_library) in the
- * specified package context.
+ * Returns a function-value implementing the build or workspace rule "ruleClass" (e.g. cc_library)
+ * in the specified package context.
*/
private static BuiltinFunction newRuleFunction(
final RuleFactory ruleFactory, final String ruleClassName, final boolean allowOverride) {
@@ -487,11 +490,29 @@ public class WorkspaceFactory {
+ kwargs.get("name")
+ "')");
}
+ if (kwargs.containsKey("repo_mapping")) {
+ if (!(kwargs.get("repo_mapping") instanceof Map)) {
+ throw new EvalException(
+ ast.getLocation(),
+ "Invalid value for 'repo_mapping': '" + kwargs.get("repo_mapping")
+ + "'. Value must be a map."
+ );
+ }
+ @SuppressWarnings("unchecked")
+ Map<String, String> map = (Map<String, String>) kwargs.get("repo_mapping");
+ String externalRepoName = (String) kwargs.get("name");
+ for (Map.Entry<String, String> e : map.entrySet()) {
+ builder.addRepositoryMappingEntry(
+ RepositoryName.createFromValidStrippedName(externalRepoName),
+ RepositoryName.create((String) e.getKey()),
+ RepositoryName.create((String) e.getValue()));
+ }
+ }
RuleClass ruleClass = ruleFactory.getRuleClass(ruleClassName);
RuleClass bindRuleClass = ruleFactory.getRuleClass("bind");
Rule rule =
WorkspaceFactoryHelper.createAndAddRepositoryRule(
- builder, ruleClass, bindRuleClass, kwargs, ast);
+ builder, ruleClass, bindRuleClass, getFinalKwargs(kwargs), ast);
if (!isLegalWorkspaceName(rule.getName())) {
throw new EvalException(
ast.getLocation(), rule + "'s name field must be a legal workspace name");
@@ -506,6 +527,14 @@ public class WorkspaceFactory {
};
}
+ private static Map<String, Object> getFinalKwargs(Map<String, Object> kwargs) {
+ // 'repo_mapping' is not an explicit attribute of any rule and so it would
+ // result in a rule error if propagated to the rule factory.
+ return kwargs.entrySet().stream()
+ .filter(x -> !x.getKey().equals("repo_mapping"))
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+ }
+
private static ImmutableMap<String, BaseFunction> createWorkspaceFunctions(
boolean allowOverride, RuleFactory ruleFactory) {
Map<String, BaseFunction> map = new HashMap<>();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index d1de91b1c9..6f7a53f96b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -29,6 +29,7 @@ import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
@@ -419,6 +420,16 @@ public class PackageFunction implements SkyFunction {
return null;
}
String workspaceName = workspaceNameValue.getName();
+
+ RepositoryMappingValue repositoryMappingValue =
+ (RepositoryMappingValue)
+ env.getValue(RepositoryMappingValue.key(packageId.getRepository()));
+ if (repositoryMappingValue == null) {
+ return null;
+ }
+ ImmutableMap<RepositoryName, RepositoryName> repositoryMapping =
+ repositoryMappingValue.getRepositoryMapping();
+
RootedPath buildFileRootedPath = packageLookupValue.getRootedPath(packageId);
FileValue buildFileValue = null;
Path buildFilePath = buildFileRootedPath.asPath();
@@ -474,6 +485,7 @@ public class PackageFunction implements SkyFunction {
LoadedPackageCacheEntry packageCacheEntry =
loadPackage(
workspaceName,
+ repositoryMapping,
replacementContents,
packageId,
buildFilePath,
@@ -1150,6 +1162,7 @@ public class PackageFunction implements SkyFunction {
@Nullable
private LoadedPackageCacheEntry loadPackage(
String workspaceName,
+ ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
@Nullable String replacementContents,
PackageIdentifier packageId,
Path buildFilePath,
@@ -1230,16 +1243,18 @@ public class PackageFunction implements SkyFunction {
GlobberWithSkyframeGlobDeps globberWithSkyframeGlobDeps =
makeGlobber(buildFilePath, packageId, packageRoot, env);
long startTimeNanos = BlazeClock.nanoTime();
- Package.Builder pkgBuilder = packageFactory.createPackageFromAst(
- workspaceName,
- packageId,
- buildFilePath,
- astParseResult,
- importResult.importMap,
- importResult.fileDependencies,
- defaultVisibility,
- skylarkSemantics,
- globberWithSkyframeGlobDeps);
+ Package.Builder pkgBuilder =
+ packageFactory.createPackageFromAst(
+ workspaceName,
+ repositoryMapping,
+ packageId,
+ buildFilePath,
+ astParseResult,
+ importResult.importMap,
+ importResult.fileDependencies,
+ defaultVisibility,
+ skylarkSemantics,
+ globberWithSkyframeGlobDeps);
long loadTimeNanos = Math.max(BlazeClock.nanoTime() - startTimeNanos, 0L);
packageCacheEntry = new LoadedPackageCacheEntry(
pkgBuilder,
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
new file mode 100644
index 0000000000..51e697ae84
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java
@@ -0,0 +1,63 @@
+// Copyright 2018 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.skyframe;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
+import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
+import com.google.devtools.build.lib.packages.Package;
+import com.google.devtools.build.skyframe.SkyFunction;
+import com.google.devtools.build.skyframe.SkyFunctionException;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+import javax.annotation.Nullable;
+
+/** {@link SkyFunction} for {@link RepositoryMappingValue}s. */
+public class RepositoryMappingFunction implements SkyFunction {
+
+ @Nullable
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ SkyKey externalPackageKey = PackageValue.key(Label.EXTERNAL_PACKAGE_IDENTIFIER);
+ PackageValue externalPackageValue = (PackageValue) env.getValue(externalPackageKey);
+ if (env.valuesMissing()) {
+ return null;
+ }
+ Package externalPackage = externalPackageValue.getPackage();
+ if (externalPackage.containsErrors()) {
+ throw new RepositoryMappingFunctionException();
+ }
+
+ ImmutableMap<RepositoryName, RepositoryName> mapping =
+ externalPackage.getRepositoryMapping((RepositoryName) skyKey.argument());
+ return RepositoryMappingValue.withMapping(mapping);
+ }
+
+ @Nullable
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+
+ private class RepositoryMappingFunctionException extends SkyFunctionException {
+ RepositoryMappingFunctionException() {
+ super(
+ new BuildFileContainsErrorsException(Label.EXTERNAL_PACKAGE_IDENTIFIER),
+ Transience.PERSISTENT);
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingValue.java
new file mode 100644
index 0000000000..809a86d3a9
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingValue.java
@@ -0,0 +1,110 @@
+// Copyright 2018 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.skyframe;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Interner;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
+import com.google.devtools.build.lib.concurrent.BlazeInterners;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import com.google.devtools.build.skyframe.AbstractSkyKey;
+import com.google.devtools.build.skyframe.SkyFunctionName;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+import java.util.Objects;
+
+/**
+ * A value that represents the 'mappings' of an external Bazel workspace, as defined
+ * in the main WORKSPACE file. The SkyValue contains the mappings themselves, with the key being
+ * the name of the external repository.
+ *
+ * <p>Given the following rule:
+ * <pre>{@code
+ * local_repository(
+ * name = “a”,
+ * path = “../a”,
+ * repo_mapping = {“@x” : “@y”}
+ * )
+ * }</pre>
+ *
+ * <p>The SkyKey would be {@code "@a"} and the SkyValue would be the map {@code {"@x" : "@y"}}
+ *
+ * <p>This is kept as a separate value with trivial change pruning so as to not necessitate a
+ * dependency from every {@link PackageValue} to the //external {@link PackageValue}, so that
+ * changes to things in the WORKSPACE other than the mappings (and name) won't require reloading
+ * all packages. If the mappings are changed then the external packages need to be reloaded.
+ */
+public class RepositoryMappingValue implements SkyValue {
+
+ private final ImmutableMap<RepositoryName, RepositoryName> repositoryMapping;
+
+ private RepositoryMappingValue(ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) {
+ this.repositoryMapping = repositoryMapping;
+ }
+
+ /** Returns the workspace mappings. */
+ public ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping() {
+ return repositoryMapping;
+ }
+
+ /** Returns the {@link Key} for {@link RepositoryMappingValue}s. */
+ public static Key key(RepositoryName repositoryName) {
+ return RepositoryMappingValue.Key.create(repositoryName);
+ }
+
+ /** Returns a {@link RepositoryMappingValue} for a workspace with the given name. */
+ public static RepositoryMappingValue withMapping(
+ ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) {
+ return new RepositoryMappingValue(Preconditions.checkNotNull(repositoryMapping));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RepositoryMappingValue)) {
+ return false;
+ }
+ RepositoryMappingValue other = (RepositoryMappingValue) o;
+ return Objects.equals(repositoryMapping, other.repositoryMapping);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(repositoryMapping);
+ }
+
+ /** {@link SkyKey} for {@link RepositoryMappingValue}. */
+ @AutoCodec.VisibleForSerialization
+ @AutoCodec
+ static class Key extends AbstractSkyKey<RepositoryName> {
+
+ private static final Interner<Key> interner = BlazeInterners.newWeakInterner();
+
+ private Key(RepositoryName arg) {
+ super(arg);
+ }
+
+ @AutoCodec.VisibleForSerialization
+ @AutoCodec.Instantiator
+ static Key create(RepositoryName arg) {
+ return interner.intern(new Key(arg));
+ }
+
+ @Override
+ public SkyFunctionName functionName() {
+ return SkyFunctions.REPOSITORY_MAPPING;
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
index 4d347e8783..7b9ca6d81f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
@@ -114,6 +114,8 @@ public final class SkyFunctions {
SkyFunctionName.create("REGISTERED_TOOLCHAINS");
public static final SkyFunctionName TOOLCHAIN_RESOLUTION =
SkyFunctionName.create("TOOLCHAIN_RESOLUTION");
+ public static final SkyFunctionName REPOSITORY_MAPPING =
+ SkyFunctionName.create("REPOSITORY_MAPPING");
public static Predicate<SkyKey> isSkyFunction(final SkyFunctionName functionName) {
return new Predicate<SkyKey>() {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index c0bb40456d..906924fa9f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -530,6 +530,7 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory {
SkyFunctions.REGISTERED_EXECUTION_PLATFORMS, new RegisteredExecutionPlatformsFunction());
map.put(SkyFunctions.REGISTERED_TOOLCHAINS, new RegisteredToolchainsFunction());
map.put(SkyFunctions.TOOLCHAIN_RESOLUTION, new ToolchainResolutionFunction());
+ map.put(SkyFunctions.REPOSITORY_MAPPING, new RepositoryMappingFunction());
map.putAll(extraSkyFunctions);
return map.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java b/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
index 7ca43d003b..d8f4cb8b83 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
@@ -61,6 +61,7 @@ import com.google.devtools.build.lib.skyframe.PackageValue;
import com.google.devtools.build.lib.skyframe.PerBuildSyscallCache;
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.SkylarkImportLookupFunction;
import com.google.devtools.build.lib.skyframe.WorkspaceASTFunction;
@@ -415,6 +416,7 @@ public abstract class AbstractPackageLoader implements PackageLoader {
SkyFunctions.WORKSPACE_FILE,
new WorkspaceFileFunction(ruleClassProvider, pkgFactory, directories))
.put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction())
+ .put(SkyFunctions.REPOSITORY_MAPPING, new RepositoryMappingFunction())
.put(
SkyFunctions.PACKAGE,
new PackageFunction(