aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
diff options
context:
space:
mode:
authorGravatar Damien Martin-Guillerez <dmarting@google.com>2016-02-09 18:58:18 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2016-02-10 10:23:44 +0000
commite891646a17ba8a86b13b163a386f711b5a83547b (patch)
treeb6f057d1bf03d15cb94254c6b1223b00f5761af7 /src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
parentea172999bd6f0b6f5b05613040f730a03ea40a1d (diff)
Split the execution of the WORKSPACE file after each load statement
This is the main step toward supporting load statement of remote repository in the WORKSPACE file (bug #824). Load statement that refers to a remote repository will depend on the previous fragment of the workspace file. Issue #824 Step 3. -- MOS_MIGRATED_REVID=114237027
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java95
1 files changed, 93 insertions, 2 deletions
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 dcf364a3e1..90f4ea87c8 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
@@ -27,6 +27,7 @@ import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.packages.Package.Builder;
import com.google.devtools.build.lib.packages.Package.LegacyBuilder;
+import com.google.devtools.build.lib.packages.Package.NameConflictException;
import com.google.devtools.build.lib.packages.PackageFactory.EnvironmentExtension;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
import com.google.devtools.build.lib.syntax.BaseFunction;
@@ -35,6 +36,7 @@ import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.Environment.Extension;
+import com.google.devtools.build.lib.syntax.Environment.Frame;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.FunctionSignature;
@@ -60,6 +62,16 @@ public class WorkspaceFactory {
public static final String BIND = "bind";
private static final Pattern LEGAL_WORKSPACE_NAME = Pattern.compile("^\\p{Alpha}\\w*$");
+ // List of static function added by #addWorkspaceFunctions. Used to trim them out from the
+ // serialized list of variables bindings.
+ private static final ImmutableList<String> STATIC_WORKSPACE_FUNCTIONS =
+ ImmutableList.of(
+ "workspace",
+ "__embedded_dir__", // serializable so optional
+ "__workspace_dir__", // serializable so optional
+ "DEFAULT_SERVER_JAVABASE", // serializable so optional
+ PackageFactory.PKG_CONTEXT);
+
private final LegacyBuilder builder;
private final Path installDir;
@@ -69,6 +81,18 @@ public class WorkspaceFactory {
private final ImmutableMap<String, BaseFunction> workspaceFunctions;
private final ImmutableList<EnvironmentExtension> environmentExtensions;
+ // Values from the previous workspace file parts.
+ // List of load statements
+ private ImmutableMap<String, Extension> parentImportMap = ImmutableMap.of();
+ // List of top level variable bindings
+ private ImmutableMap<String, Object> parentVariableBindings = ImmutableMap.of();
+
+ // Values accumulated up to the currently parsed workspace file part.
+ // List of load statements
+ private ImmutableMap<String, Extension> importMap = ImmutableMap.of();
+ // List of top level variable bindings
+ private ImmutableMap<String, Object> variableBindings = ImmutableMap.of();
+
/**
* @param builder a builder for the Workspace
* @param ruleClassProvider a provider for known rule classes
@@ -144,7 +168,8 @@ public class WorkspaceFactory {
Preconditions.checkNotNull(importedExtensions);
execute(ast, importedExtensions, new StoredEventHandler());
}
-
+
+
private void execute(BuildFileAST ast, @Nullable Map<String, Extension> importedExtensions,
StoredEventHandler localReporter)
throws InterruptedException {
@@ -152,14 +177,45 @@ public class WorkspaceFactory {
.setGlobals(Environment.BUILD)
.setEventHandler(localReporter);
if (importedExtensions != null) {
- environmentBuilder.setImportedExtensions(importedExtensions);
+ importMap =
+ ImmutableMap.<String, Extension>builder()
+ .putAll(parentImportMap)
+ .putAll(importedExtensions)
+ .build();
+ } else {
+ importMap = parentImportMap;
}
+ environmentBuilder.setImportedExtensions(importMap);
Environment workspaceEnv = environmentBuilder.setLoadingPhase().build();
addWorkspaceFunctions(workspaceEnv, localReporter);
+ for (Map.Entry<String, Object> binding : parentVariableBindings.entrySet()) {
+ try {
+ workspaceEnv.update(binding.getKey(), binding.getValue());
+ } catch (EvalException e) {
+ // This should never happen because everything was already evaluated.
+ throw new IllegalStateException(e);
+ }
+ }
if (!ast.exec(workspaceEnv, localReporter)) {
localReporter.handle(Event.error("Error evaluating WORKSPACE file"));
}
+ // Save the list of variable bindings for the next part of the workspace file. The list of
+ // variable bindings of interest are the global variable bindings that are defined by the user,
+ // so not the workspace functions.
+ // Workspace functions are not serializable and should not be passed over sky values. They
+ // also have a package builder specific to the current part and should be reinitialized for
+ // each workspace file.
+ ImmutableMap.Builder<String, Object> bindingsBuilder = ImmutableMap.builder();
+ Frame globals = workspaceEnv.getGlobals();
+ for (String s : globals.getDirectVariableNames()) {
+ Object o = globals.get(s);
+ if (!isAWorkspaceFunction(s, o)) {
+ bindingsBuilder.put(s, o);
+ }
+ }
+ variableBindings = bindingsBuilder.build();
+
builder.addEvents(localReporter.getEvents());
if (localReporter.hasErrors()) {
builder.setContainsErrors();
@@ -167,11 +223,38 @@ public class WorkspaceFactory {
localReporter.clear();
}
+ private boolean isAWorkspaceFunction(String name, Object o) {
+ return STATIC_WORKSPACE_FUNCTIONS.contains(name) || (workspaceFunctions.get(name) == o);
+ }
+
private static boolean isLegalWorkspaceName(String name) {
Matcher matcher = LEGAL_WORKSPACE_NAME.matcher(name);
return matcher.matches();
}
+ /**
+ * Adds the various values returned by the parsing of the previous workspace file parts.
+ * {@code aPackage} is the package returned by the parent WorkspaceFileFunction, {@code importMap}
+ * is the list of load statements imports computed by the parent WorkspaceFileFunction and
+ * {@code variableBindings} the list of top level variable bindings of that same call.
+ */
+ public void setParent(
+ Package aPackage,
+ ImmutableMap<String, Extension> importMap,
+ ImmutableMap<String, Object> bindings)
+ throws NameConflictException {
+ this.parentVariableBindings = bindings;
+ this.parentImportMap = importMap;
+ // Transmit the content of the parent package to the new package builder.
+ builder.addEvents(aPackage.getEvents());
+ if (aPackage.containsErrors()) {
+ builder.setContainsErrors();
+ }
+ for (Target target : aPackage.getTargets(Rule.class)) {
+ builder.addRule((Rule) target);
+ }
+ }
+
@SkylarkSignature(name = "workspace", objectType = Object.class, returnType = SkylarkList.class,
doc = "Sets the name for this workspace. Workspace names should be a Java-package-style "
+ "description of the project, using underscores as separators, e.g., "
@@ -328,4 +411,12 @@ public class WorkspaceFactory {
static {
SkylarkSignatureProcessor.configureSkylarkFunctions(WorkspaceFactory.class);
}
+
+ public Map<String, Extension> getImportMap() {
+ return importMap;
+ }
+
+ public Map<String, Object> getVariableBindings() {
+ return variableBindings;
+ }
}