diff options
author | Damien Martin-Guillerez <dmarting@google.com> | 2016-02-09 18:58:18 +0000 |
---|---|---|
committer | Dmitry Lomov <dslomov@google.com> | 2016-02-10 10:23:44 +0000 |
commit | e891646a17ba8a86b13b163a386f711b5a83547b (patch) | |
tree | b6f057d1bf03d15cb94254c6b1223b00f5761af7 /src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java | |
parent | ea172999bd6f0b6f5b05613040f730a03ea40a1d (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.java | 95 |
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; + } } |