Move most BlazeRuntime methods related to workspace directories to CommandEnv.

--
MOS_MIGRATED_REVID=118561661
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
index e1566e2..00aba28 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
@@ -30,7 +30,6 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.exec.ExecutionOptions;
 import com.google.devtools.build.lib.packages.Rule;
-import com.google.devtools.build.lib.runtime.BlazeRuntime;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.skyframe.AspectValue;
 import com.google.devtools.build.lib.util.io.OutErr;
@@ -43,11 +42,9 @@
  */
 class BuildResultPrinter {
   private final CommandEnvironment env;
-  private final BlazeRuntime runtime;
 
   BuildResultPrinter(CommandEnvironment env) {
     this.env = env;
-    this.runtime = env.getRuntime();
   }
 
   /**
@@ -138,9 +135,9 @@
           if (temp.getPath().exists()) {
             outErr.printErrLn("  See temp at "
                 + OutputDirectoryLinksUtils.getPrettyPath(temp.getPath(),
-                runtime.getWorkspaceName(),
-                runtime.getWorkspace(),
-                request.getBuildOptions().getSymlinkPrefix()));
+                    env.getWorkspaceName(),
+                    env.getWorkspace(),
+                    request.getBuildOptions().getSymlinkPrefix()));
           }
         }
       }
@@ -156,7 +153,7 @@
 
   private String formatArtifactForShowResults(Artifact artifact, BuildRequest request) {
     return "  " + OutputDirectoryLinksUtils.getPrettyPath(artifact.getPath(),
-        runtime.getWorkspaceName(), runtime.getWorkspace(),
+        env.getWorkspaceName(), env.getWorkspace(),
         request.getBuildOptions().getSymlinkPrefix());
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
index 7c61f72..7da7e28 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
@@ -178,7 +178,7 @@
       }
       configurations = runtime.getSkyframeExecutor().createConfigurations(
             env.getReporter(), runtime.getConfigurationFactory(), buildOptions,
-            runtime.getDirectories(), request.getMultiCpus(), request.getViewOptions().keepGoing);
+            env.getDirectories(), request.getMultiCpus(), request.getViewOptions().keepGoing);
 
       env.getEventBus().post(new ConfigurationsCreatedEvent(configurations));
       env.throwPendingException();
@@ -463,7 +463,7 @@
     getReporter().handle(Event.progress("Loading complete.  Analyzing..."));
     Profiler.instance().markPhase(ProfilePhase.ANALYZE);
 
-    BuildView view = new BuildView(runtime.getDirectories(), runtime.getRuleClassProvider(),
+    BuildView view = new BuildView(env.getDirectories(), runtime.getRuleClassProvider(),
         runtime.getSkyframeExecutor(), runtime.getCoverageReportActionFactory());
     AnalysisResult analysisResult =
         view.update(
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
index 17298c3..0b1e95b 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
@@ -190,7 +190,7 @@
         getActionContextProvidersFromModules(
             runtime,
             new FilesetActionContextImpl.Provider(
-                env.getReporter(), runtime.getWorkspaceName()),
+                env.getReporter(), env.getWorkspaceName()),
             new SimpleActionContextProvider(
                 new SymlinkTreeStrategy(env.getOutputService(), runtime.getBinTools())));
     StrategyConverter strategyConverter = new StrategyConverter(actionContextProviders);
@@ -300,8 +300,8 @@
   private BlazeExecutor createExecutor()
       throws ExecutorInitException {
     return new BlazeExecutor(
-        runtime.getDirectories().getExecRoot(),
-        runtime.getDirectories().getOutputPath(),
+        env.getExecRoot(),
+        env.getOutputPath(),
         getReporter(),
         env.getEventBus(),
         runtime.getClock(),
@@ -360,8 +360,8 @@
         ? targetConfigurations.get(0) : null;
     if (targetConfigurations.size() == 1) {
       OutputDirectoryLinksUtils.createOutputDirectoryLinks(
-          runtime.getWorkspaceName(), getWorkspace(), getExecRoot(),
-          runtime.getOutputPath(), getReporter(), targetConfiguration,
+          env.getWorkspaceName(), env.getWorkspace(), getExecRoot(),
+          env.getOutputPath(), getReporter(), targetConfiguration,
           request.getBuildOptions().getSymlinkPrefix());
     }
 
@@ -531,7 +531,7 @@
   }
 
   private void createActionLogDirectory() throws ExecutorInitException {
-    Path directory = runtime.getDirectories().getActionConsoleOutputDirectory();
+    Path directory = env.getDirectories().getActionConsoleOutputDirectory();
     try {
       if (directory.exists()) {
         FileSystemUtils.deleteTree(directory);
@@ -547,8 +547,8 @@
    */
   private void startLocalOutputBuild() throws ExecutorInitException {
     try (AutoProfiler p = AutoProfiler.profiled("Starting local output build", ProfilerTask.INFO)) {
-      Path outputPath = runtime.getOutputPath();
-      Path localOutputPath = runtime.getDirectories().getLocalOutputPath();
+      Path outputPath = env.getOutputPath();
+      Path localOutputPath = env.getDirectories().getLocalOutputPath();
 
       if (outputPath.isSymbolicLink()) {
         try {
@@ -671,7 +671,7 @@
     boolean verboseExplanations = options.verboseExplanations;
     boolean keepGoing = request.getViewOptions().keepGoing;
 
-    Path actionOutputRoot = runtime.getDirectories().getActionConsoleOutputDirectory();
+    Path actionOutputRoot = env.getDirectories().getActionConsoleOutputDirectory();
     Predicate<Action> executionFilter = CheckUpToDateFilter.fromOptions(
         request.getOptions(ExecutionOptions.class));
 
@@ -735,7 +735,7 @@
 
   private ActionInputFileCache createBuildSingleFileCache(Path execRoot) {
     String cwd = execRoot.getPathString();
-    FileSystem fs = runtime.getDirectories().getFileSystem();
+    FileSystem fs = env.getDirectories().getFileSystem();
 
     ActionInputFileCache cache = null;
     for (BlazeModule module : runtime.getBlazeModules()) {
@@ -757,10 +757,10 @@
   }
 
   private Path getWorkspace() {
-    return runtime.getWorkspace();
+    return env.getWorkspace();
   }
 
   private Path getExecRoot() {
-    return runtime.getExecRoot();
+    return env.getExecRoot();
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java
index d316624..93a8c8c 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java
@@ -20,7 +20,6 @@
 import com.google.devtools.build.lib.actions.Executor.ActionContext;
 import com.google.devtools.build.lib.buildtool.BuildRequest;
 import com.google.devtools.build.lib.exec.ExecutionOptions;
-import com.google.devtools.build.lib.runtime.BlazeRuntime;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 
 /**
@@ -34,13 +33,12 @@
       BuildRequest buildRequest,
       RemoteActionCache actionCache,
       RemoteWorkExecutor workExecutor) {
-    BlazeRuntime runtime = env.getRuntime();
     boolean verboseFailures = buildRequest.getOptions(ExecutionOptions.class).verboseFailures;
     Builder<ActionContext> strategiesBuilder = ImmutableList.builder();
     strategiesBuilder.add(
         new RemoteSpawnStrategy(
             env.getClientEnv(),
-            runtime.getExecRoot(),
+            env.getExecRoot(),
             buildRequest.getOptions(RemoteOptions.class),
             verboseFailures,
             actionCache,
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
index ebc1874..3ed2968 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
@@ -65,7 +65,7 @@
     if (actionCache == null && options.hazelcastNode != null) {
       actionCache =
           new MemcacheActionCache(
-              this.env.getRuntime().getExecRoot(),
+              env.getExecRoot(),
               options,
               HazelcastCacheFactory.create(options));
       // TODO(alpha): Initialize a RemoteWorkExecutor.
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java
index f57f8b9..ad45de4 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java
@@ -122,19 +122,19 @@
    * Only some commands work if cwd != workspaceSuffix in Blaze. In that case, also check if Blaze
    * was called from the output directory and fail if it was.
    */
-  private ExitCode checkCwdInWorkspace(Command commandAnnotation, String commandName,
-      OutErr outErr) {
+  private ExitCode checkCwdInWorkspace(CommandEnvironment env, Command commandAnnotation,
+      String commandName, OutErr outErr) {
     if (!commandAnnotation.mustRunInWorkspace()) {
       return ExitCode.SUCCESS;
     }
 
-    if (!runtime.inWorkspace()) {
-      outErr.printErrLn("The '" + commandName + "' command is only supported from within a "
-          + "workspace.");
+    if (!env.inWorkspace()) {
+      outErr.printErrLn(
+          "The '" + commandName + "' command is only supported from within a workspace.");
       return ExitCode.COMMAND_LINE_ERROR;
     }
 
-    Path workspace = runtime.getWorkspace();
+    Path workspace = env.getWorkspace();
     // TODO(kchodorow): Remove this once spaces are supported.
     if (workspace.getPathString().contains(" ")) {
       outErr.printErrLn(Constants.PRODUCT_NAME + " does not currently work properly from paths "
@@ -256,7 +256,7 @@
     }
 
     try {
-      Path commandLog = getCommandLogPath(runtime.getOutputBase());
+      Path commandLog = getCommandLogPath(env.getOutputBase());
 
       // Unlink old command log from previous build, if present, so scripts
       // reading it don't conflate it with the command log we're about to write.
@@ -269,7 +269,7 @@
           Level.WARNING, "Unable to delete or open command.log", ioException);
     }
 
-    ExitCode result = checkCwdInWorkspace(commandAnnotation, commandName, outErr);
+    ExitCode result = checkCwdInWorkspace(env, commandAnnotation, commandName, outErr);
     if (result != ExitCode.SUCCESS) {
       return result.getNumericExitCode();
     }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
index 7c598c0..638e5f9 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
@@ -212,7 +212,7 @@
     this.directories = directories;
     this.skyframeExecutor = skyframeExecutor;
 
-    if (inWorkspace()) {
+    if (directories.inWorkspace()) {
       writeOutputBaseReadmeFile();
       writeDoNotBuildHereFile();
     }
@@ -396,14 +396,6 @@
     return lastExecutionRange;
   }
 
-  public String getWorkspaceName() {
-    Path workspace = directories.getWorkspace();
-    if (workspace == null) {
-      return "";
-    }
-    return workspace.getBaseName();
-  }
-
   /**
    * Returns the Blaze directories object for this runtime.
    */
@@ -417,48 +409,25 @@
    * <p>This is often the first entry on the {@code --package_path}, but not always.
    * Callers should certainly not make this assumption. The Path returned may be null.
    */
-  public Path getWorkspace() {
+  private Path getWorkspace() {
     return directories.getWorkspace();
   }
 
   /**
-   * Returns if the client passed a valid workspace to be used for the build.
-   */
-  public boolean inWorkspace() {
-    return directories.inWorkspace();
-  }
-
-  /**
    * Returns the output base directory associated with this Blaze server
    * process. This is the base directory for shared Blaze state as well as tool
    * and strategy specific subdirectories.
    */
-  public Path getOutputBase() {
+  private Path getOutputBase() {
     return directories.getOutputBase();
   }
 
   /**
-   * Returns the output path associated with this Blaze server process..
-   */
-  public Path getOutputPath() {
-    return directories.getOutputPath();
-  }
-
-  /**
    * The directory in which blaze stores the server state - that is, the socket
    * file and a log.
    */
-  public Path getServerDirectory() {
-    return getOutputBase().getChild("server");
-  }
-
-  /**
-   * Returns the execution root directory associated with this Blaze server
-   * process. This is where all input and output files visible to the actual
-   * build reside.
-   */
-  public Path getExecRoot() {
-    return directories.getExecRoot();
+  private Path getServerDirectory() {
+    return getDirectories().getOutputBase().getChild("server");
   }
 
   public BinTools getBinTools() {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java
index acbd120..ee80c85 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java
@@ -73,6 +73,7 @@
  */
 public final class CommandEnvironment {
   private final BlazeRuntime runtime;
+  private final BlazeDirectories directories;
 
   private final UUID commandId;  // Unique identifier for the command being run
   private final Reporter reporter;
@@ -107,6 +108,7 @@
 
   public CommandEnvironment(BlazeRuntime runtime, UUID commandId, EventBus eventBus) {
     this.runtime = runtime;
+    this.directories = runtime.getDirectories();
     this.commandId = commandId;
     this.reporter = new Reporter();
     this.eventBus = eventBus;
@@ -120,7 +122,7 @@
 
     // TODO(ulfjack): We don't call beforeCommand() in tests, but rely on workingDirectory being set
     // in setupPackageCache(). This leads to NPE if we don't set it here.
-    this.workingDirectory = runtime.getWorkspace();
+    this.workingDirectory = directories.getWorkspace();
   }
 
   public BlazeRuntime getRuntime() {
@@ -128,7 +130,7 @@
   }
 
   public BlazeDirectories getDirectories() {
-    return runtime.getDirectories();
+    return directories;
   }
 
   /**
@@ -208,11 +210,69 @@
   }
 
   /**
+   * Returns the working directory of the server.
+   *
+   * <p>This is often the first entry on the {@code --package_path}, but not always.
+   * Callers should certainly not make this assumption. The Path returned may be null.
+   */
+  public Path getWorkspace() {
+    return getDirectories().getWorkspace();
+  }
+
+  public String getWorkspaceName() {
+    Path workspace = getDirectories().getWorkspace();
+    if (workspace == null) {
+      return "";
+    }
+    return workspace.getBaseName();
+  }
+
+  /**
+   * Returns if the client passed a valid workspace to be used for the build.
+   */
+  public boolean inWorkspace() {
+    return getDirectories().inWorkspace();
+  }
+
+  /**
+   * Returns the output base directory associated with this Blaze server
+   * process. This is the base directory for shared Blaze state as well as tool
+   * and strategy specific subdirectories.
+   */
+  public Path getOutputBase() {
+    return getDirectories().getOutputBase();
+  }
+
+  /**
+   * Returns the output path associated with this Blaze server process..
+   */
+  public Path getOutputPath() {
+    return getDirectories().getOutputPath();
+  }
+
+  /**
+   * The directory in which blaze stores the server state - that is, the socket
+   * file and a log.
+   */
+  public Path getServerDirectory() {
+    return getOutputBase().getChild("server");
+  }
+
+  /**
+   * Returns the execution root directory associated with this Blaze server
+   * process. This is where all input and output files visible to the actual
+   * build reside.
+   */
+  public Path getExecRoot() {
+    return getDirectories().getExecRoot();
+  }
+
+  /**
    * Returns the working directory of the {@code blaze} client process.
    *
    * <p>This may be equal to {@code BlazeRuntime#getWorkspace()}, or beneath it.
    *
-   * @see BlazeRuntime#getWorkspace()
+   * @see #getWorkspace()
    */
   public Path getWorkingDirectory() {
     return workingDirectory;
@@ -246,7 +306,7 @@
       throw new InvalidConfigurationException("Configuration creation failed");
     }
     return getSkyframeExecutor().createConfigurations(reporter, runtime.getConfigurationFactory(),
-        buildOptions, runtime.getDirectories(), ImmutableSet.<String>of(), keepGoing);
+        buildOptions, getDirectories(), ImmutableSet.<String>of(), keepGoing);
   }
 
   // TODO(ulfjack): Do we even need this method? With Skyframe, the config creation should
@@ -304,7 +364,7 @@
     if (!skyframeExecutor.hasIncrementalState()) {
       skyframeExecutor.resetEvaluator();
     }
-    skyframeExecutor.sync(reporter, packageCacheOptions, runtime.getOutputBase(),
+    skyframeExecutor.sync(reporter, packageCacheOptions, getOutputBase(),
         getWorkingDirectory(), defaultsPackageContents, commandId,
         timestampGranularityMonitor);
   }
@@ -365,12 +425,12 @@
     this.outputFileSystem = determineOutputFileSystem();
 
     // Ensure that the working directory will be under the workspace directory.
-    Path workspace = runtime.getWorkspace();
+    Path workspace = getWorkspace();
     Path workingDirectory;
-    if (runtime.inWorkspace()) {
+    if (inWorkspace()) {
       workingDirectory = workspace.getRelative(options.clientCwd);
     } else {
-      workspace = FileSystemUtils.getWorkingDirectory(runtime.getDirectories().getFileSystem());
+      workspace = FileSystemUtils.getWorkingDirectory(getDirectories().getFileSystem());
       workingDirectory = workspace;
     }
     this.relativeWorkingDirectory = workingDirectory.relativeTo(workspace);
@@ -428,7 +488,7 @@
       return getOutputService().getFilesSystemName();
     }
     try (AutoProfiler p = profiled("Finding output file system", ProfilerTask.INFO)) {
-      return FileSystemUtils.getFileSystem(runtime.getOutputBase());
+      return FileSystemUtils.getFileSystem(getOutputBase());
     }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
index c6e3a2a..1263005 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
@@ -86,7 +86,6 @@
   @Override
   public ExitCode exec(CommandEnvironment env, OptionsProvider options)
       throws ShutdownBlazeServerException {
-    BlazeRuntime runtime = env.getRuntime();
     Options cleanOptions = options.getOptions(Options.class);
     cleanOptions.expunge_async = cleanOptions.cleanStyle.equals("expunge_async");
     cleanOptions.expunge = cleanOptions.cleanStyle.equals("expunge");
@@ -109,7 +108,7 @@
     try {
       String symlinkPrefix =
           options.getOptions(BuildRequest.BuildRequestOptions.class).getSymlinkPrefix();
-      actuallyClean(env, runtime.getOutputBase(), cleanOptions, symlinkPrefix);
+      actuallyClean(env, env.getOutputBase(), cleanOptions, symlinkPrefix);
       return ExitCode.SUCCESS;
     } catch (IOException e) {
       env.getReporter().handle(Event.error(e.getMessage()));
@@ -167,7 +166,7 @@
       // In order to be sure that we delete everything, delete the workspace directory both for
       // --deep_execroot and for --nodeep_execroot.
       for (String directory : new String[] {
-          runtime.getWorkspaceName(), "execroot/" + runtime.getWorkspaceName() }) {
+          env.getWorkspaceName(), "execroot/" + env.getWorkspaceName() }) {
         Path child = outputBase.getRelative(directory);
         if (child.exists()) {
           LOG.finest("Cleaning " + child);
@@ -177,7 +176,7 @@
     }
     // remove convenience links
     OutputDirectoryLinksUtils.removeOutputDirectoryLinks(
-        runtime.getWorkspaceName(), runtime.getWorkspace(), env.getReporter(), symlinkPrefix);
+        env.getWorkspaceName(), env.getWorkspace(), env.getReporter(), symlinkPrefix);
     // shutdown on expunge cleans
     if (cleanOptions.expunge || cleanOptions.expunge_async) {
       throw new ShutdownBlazeServerException(0);
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
index 81e19a0..6acf546 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
@@ -151,7 +151,7 @@
 
       if (dumpOptions.dumpVfs) {
         out.println("Filesystem cache");
-        FileSystemUtils.dump(runtime.getOutputBase().getFileSystem(), out);
+        FileSystemUtils.dump(env.getOutputBase().getFileSystem(), out);
         out.println();
       }
 
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
index 93a947a..65d7255 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
@@ -284,10 +284,10 @@
       Supplier<BuildConfiguration> configurationSupplier, OptionsProvider options) {
     switch (key) {
       // directories
-      case WORKSPACE : return runtime.getWorkspace();
+      case WORKSPACE : return runtime.getDirectories().getWorkspace();
       case INSTALL_BASE : return runtime.getDirectories().getInstallBase();
-      case OUTPUT_BASE : return runtime.getOutputBase();
-      case EXECUTION_ROOT : return runtime.getExecRoot();
+      case OUTPUT_BASE : return runtime.getDirectories().getOutputBase();
+      case EXECUTION_ROOT : return runtime.getDirectories().getExecRoot();
       case OUTPUT_PATH : return runtime.getDirectories().getOutputPath();
       // These are the only (non-hidden) info items that require a configuration, because the
       // corresponding paths contain the short name. Maybe we should recommend using the symlinks
@@ -297,10 +297,11 @@
       case BLAZE_TESTLOGS : return configurationSupplier.get().getTestLogsDirectory().getPath();
 
       // logs
-      case COMMAND_LOG : return BlazeCommandDispatcher.getCommandLogPath(runtime.getOutputBase());
+      case COMMAND_LOG : return BlazeCommandDispatcher.getCommandLogPath(
+          runtime.getDirectories().getOutputBase());
       case MESSAGE_LOG :
         // NB: Duplicated in EventLogModule
-        return runtime.getOutputBase().getRelative("message.log");
+        return runtime.getDirectories().getOutputBase().getRelative("message.log");
 
       // misc
       case RELEASE : return BlazeVersionInfo.instance().getReleaseName();
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java
index 9b2cc21..970cb5c 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java
@@ -30,7 +30,6 @@
 import com.google.devtools.build.lib.profiler.statistics.PhaseStatistics;
 import com.google.devtools.build.lib.profiler.statistics.PhaseSummaryStatistics;
 import com.google.devtools.build.lib.runtime.BlazeCommand;
-import com.google.devtools.build.lib.runtime.BlazeRuntime;
 import com.google.devtools.build.lib.runtime.Command;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.util.ExitCode;
@@ -178,7 +177,6 @@
 
   @Override
   public ExitCode exec(final CommandEnvironment env, OptionsProvider options) {
-    final BlazeRuntime runtime = env.getRuntime();
     ProfileOptions opts =
         options.getOptions(ProfileOptions.class);
 
@@ -194,7 +192,7 @@
         MultiProfileStatistics statistics =
             new MultiProfileStatistics(
                 env.getWorkingDirectory(),
-                runtime.getWorkspaceName(),
+                env.getWorkspaceName(),
                 options.getResidue(),
                 getInfoListener(env),
                 opts.vfsStatsLimit > 0);
@@ -250,7 +248,7 @@
               phaseStatistics.put(
                   phase,
                   new PhaseStatistics(
-                      phase, info, runtime.getWorkspaceName(), opts.vfsStatsLimit > 0));
+                      phase, info, env.getWorkspaceName(), opts.vfsStatsLimit > 0));
             }
 
             CriticalPathStatistics critPathStats = new CriticalPathStatistics(info);
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/ProjectFileSupport.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/ProjectFileSupport.java
index 240a0ec..cfdabe6 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/ProjectFileSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/ProjectFileSupport.java
@@ -65,10 +65,10 @@
       // relative to the cwd instead.
       PathFragment projectFilePath = new PathFragment(targets.get(0).substring(1));
       List<Path> packagePath = PathPackageLocator.create(
-          runtime.getOutputBase(),
+          env.getOutputBase(),
           optionsParser.getOptions(PackageCacheOptions.class).packagePath,
           env.getReporter(),
-          runtime.getWorkspace(),
+          env.getWorkspace(),
           env.getWorkingDirectory()).getPathEntries();
       ProjectFile projectFile = projectFileProvider.getProjectFile(
           env.getWorkingDirectory(), packagePath, projectFilePath);
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
index 34f6819..836c154 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
@@ -242,15 +242,14 @@
     // replaced with a shorter relative path that uses the symlinks in the workspace.
     PathFragment prettyExecutablePath =
         OutputDirectoryLinksUtils.getPrettyPath(executablePath,
-            runtime.getWorkspaceName(), runtime.getWorkspace(),
+            env.getWorkspaceName(), env.getWorkspace(),
             options.getOptions(BuildRequestOptions.class).getSymlinkPrefix());
     List<String> cmdLine = new ArrayList<>();
     if (runOptions.scriptPath == null) {
       PathFragment processWrapperPath = runtime.getBinTools().getExecPath(PROCESS_WRAPPER);
       Preconditions.checkNotNull(
           processWrapperPath, PROCESS_WRAPPER + " not found in embedded tools");
-      cmdLine.add(runtime.getDirectories().getExecRoot()
-          .getRelative(processWrapperPath).getPathString());
+      cmdLine.add(env.getExecRoot().getRelative(processWrapperPath).getPathString());
       cmdLine.add("-1");
       cmdLine.add("15");
       cmdLine.add("-");
@@ -356,7 +355,7 @@
 
     Artifact manifest = runfilesSupport.getRunfilesManifest();
     PathFragment runfilesDir = runfilesSupport.getRunfilesDirectoryExecPath();
-    Path workingDir = env.getRuntime().getExecRoot()
+    Path workingDir = env.getExecRoot()
         .getRelative(runfilesDir)
         .getRelative(runfilesSupport.getRunfiles().getSuffix());
 
@@ -372,7 +371,7 @@
         manifest.getExecPath(),
         runfilesDir,
         false);
-    helper.createSymlinksUsingCommand(env.getRuntime().getExecRoot(), target.getConfiguration(),
+    helper.createSymlinksUsingCommand(env.getExecRoot(), target.getConfiguration(),
         env.getRuntime().getBinTools());
     return workingDir;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java b/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java
index b037dad..8b35723 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java
@@ -21,7 +21,7 @@
 import com.google.devtools.build.lib.actions.ExecException;
 import com.google.devtools.build.lib.actions.UserExecException;
 import com.google.devtools.build.lib.analysis.config.BinTools;
-import com.google.devtools.build.lib.runtime.BlazeRuntime;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.shell.AbnormalTerminationException;
 import com.google.devtools.build.lib.shell.Command;
 import com.google.devtools.build.lib.shell.CommandException;
@@ -79,9 +79,9 @@
     this.sandboxDebug = sandboxDebug;
   }
 
-  static boolean isSupported(BlazeRuntime runtime) {
-    Path execRoot = runtime.getExecRoot();
-    BinTools binTools = runtime.getBinTools();
+  static boolean isSupported(CommandEnvironment commandEnv) {
+    Path execRoot = commandEnv.getExecRoot();
+    BinTools binTools = commandEnv.getRuntime().getBinTools();
 
     PathFragment embeddedTool = binTools.getExecPath(NAMESPACE_SANDBOX);
     if (embeddedTool == null) {
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java
index b04267f..7187937 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java
@@ -22,7 +22,6 @@
 import com.google.devtools.build.lib.concurrent.ExecutorUtil;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.runtime.BlazeModule;
-import com.google.devtools.build.lib.runtime.BlazeRuntime;
 import com.google.devtools.build.lib.runtime.Command;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.util.OS;
@@ -49,9 +48,9 @@
   private CommandEnvironment env;
   private BuildRequest buildRequest;
 
-  private synchronized boolean isSandboxingSupported(BlazeRuntime runtime) {
+  private synchronized boolean isSandboxingSupported(CommandEnvironment env) {
     if (sandboxingSupported == null) {
-      sandboxingSupported = NamespaceSandboxRunner.isSupported(runtime);
+      sandboxingSupported = NamespaceSandboxRunner.isSupported(env);
     }
     return sandboxingSupported.booleanValue();
   }
@@ -60,7 +59,7 @@
   public Iterable<ActionContextProvider> getActionContextProviders() {
     Preconditions.checkNotNull(buildRequest);
     Preconditions.checkNotNull(env);
-    if (isSandboxingSupported(env.getRuntime())) {
+    if (isSandboxingSupported(env)) {
       return ImmutableList.<ActionContextProvider>of(
           new SandboxActionContextProvider(env, buildRequest, backgroundWorkers));
     }
@@ -78,7 +77,7 @@
   @Override
   public Iterable<ActionContextConsumer> getActionContextConsumers() {
     Preconditions.checkNotNull(env);
-    if (isSandboxingSupported(env.getRuntime())) {
+    if (isSandboxingSupported(env)) {
       return ImmutableList.<ActionContextConsumer>of(new SandboxActionContextConsumer());
     }
     return ImmutableList.of();
diff --git a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
index 1083257..9583d31 100644
--- a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
@@ -31,7 +31,6 @@
 import com.google.devtools.build.lib.rules.test.ExclusiveTestStrategy;
 import com.google.devtools.build.lib.rules.test.StandaloneTestStrategy;
 import com.google.devtools.build.lib.rules.test.TestActionContext;
-import com.google.devtools.build.lib.runtime.BlazeRuntime;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 
@@ -69,12 +68,11 @@
 
   public StandaloneActionContextProvider(CommandEnvironment env, BuildRequest buildRequest) {
     this.env = env;
-    BlazeRuntime runtime = env.getRuntime();
     boolean verboseFailures = buildRequest.getOptions(ExecutionOptions.class).verboseFailures;
 
     TestActionContext testStrategy =
         new StandaloneTestStrategy(
-            buildRequest, runtime.getBinTools(), env.getClientEnv(), runtime.getWorkspace());
+            buildRequest, env.getRuntime().getBinTools(), env.getClientEnv(), env.getWorkspace());
 
     Builder<ActionContext> strategiesBuilder = ImmutableList.builder();
 
@@ -82,7 +80,7 @@
     // could potentially be used and a spawnActionContext doesn't specify which one it wants, the
     // last one from strategies list will be used
     strategiesBuilder.add(
-        new StandaloneSpawnStrategy(runtime.getExecRoot(), verboseFailures),
+        new StandaloneSpawnStrategy(env.getExecRoot(), verboseFailures),
         new DummyIncludeScanningContext(),
         new SpawnLinkStrategy(),
         new SpawnGccStrategy(),
diff --git a/src/main/java/com/google/devtools/build/lib/worker/WorkerActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/worker/WorkerActionContextProvider.java
index 17ccb74..e08ff8a 100644
--- a/src/main/java/com/google/devtools/build/lib/worker/WorkerActionContextProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/worker/WorkerActionContextProvider.java
@@ -14,12 +14,11 @@
 package com.google.devtools.build.lib.worker;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.eventbus.EventBus;
 import com.google.devtools.build.lib.actions.ActionContextProvider;
 import com.google.devtools.build.lib.actions.Executor.ActionContext;
 import com.google.devtools.build.lib.buildtool.BuildRequest;
 import com.google.devtools.build.lib.exec.ExecutionOptions;
-import com.google.devtools.build.lib.runtime.BlazeRuntime;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
 
 /**
  * Factory for the Worker-based execution strategy.
@@ -28,14 +27,14 @@
   private final ImmutableList<ActionContext> strategies;
 
   public WorkerActionContextProvider(
-      BlazeRuntime runtime, BuildRequest buildRequest, WorkerPool workers, EventBus eventBus) {
+      CommandEnvironment env, BuildRequest buildRequest, WorkerPool workers) {
     boolean verboseFailures = buildRequest.getOptions(ExecutionOptions.class).verboseFailures;
     int maxRetries = buildRequest.getOptions(WorkerOptions.class).workerMaxRetries;
 
     this.strategies =
         ImmutableList.<ActionContext>of(
             new WorkerSpawnStrategy(
-                runtime.getDirectories(),
+                env.getDirectories(),
                 buildRequest,
                 workers,
                 verboseFailures,
diff --git a/src/main/java/com/google/devtools/build/lib/worker/WorkerModule.java b/src/main/java/com/google/devtools/build/lib/worker/WorkerModule.java
index 91956e1..cde7584 100644
--- a/src/main/java/com/google/devtools/build/lib/worker/WorkerModule.java
+++ b/src/main/java/com/google/devtools/build/lib/worker/WorkerModule.java
@@ -56,7 +56,7 @@
     env.getEventBus().register(this);
 
     if (workers == null) {
-      Path logDir = env.getRuntime().getOutputBase().getRelative("worker-logs");
+      Path logDir = env.getOutputBase().getRelative("worker-logs");
       try {
         logDir.createDirectory();
       } catch (IOException e) {
@@ -112,8 +112,7 @@
     Preconditions.checkNotNull(workers);
 
     return ImmutableList.<ActionContextProvider>of(
-        new WorkerActionContextProvider(
-            env.getRuntime(), buildRequest, workers, env.getEventBus()));
+        new WorkerActionContextProvider(env, buildRequest, workers));
   }
 
   @Override