Move the outputService field to the CommandEnvironment.

--
MOS_MIGRATED_REVID=105841398
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 bf018f1..3a95cbd 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
@@ -187,7 +187,7 @@
             new FilesetActionContextImpl.Provider(
                 env.getReporter(), runtime.getWorkspaceName()),
             new SimpleActionContextProvider(
-                new SymlinkTreeStrategy(runtime.getOutputService(), runtime.getBinTools())));
+                new SymlinkTreeStrategy(env.getOutputService(), runtime.getBinTools())));
     StrategyConverter strategyConverter = new StrategyConverter(actionContextProviders);
 
     ImmutableList<ActionContextConsumer> actionContextConsumers =
@@ -356,7 +356,7 @@
       }
     }
 
-    OutputService outputService = runtime.getOutputService();
+    OutputService outputService = env.getOutputService();
     if (outputService != null) {
       outputService.startBuild(buildId);
     } else {
@@ -484,10 +484,10 @@
       }
       // Finalize output service last, so that if we do throw an exception, we know all the other
       // code has already run.
-      if (runtime.getOutputService() != null) {
+      if (env.getOutputService() != null) {
         boolean isBuildSuccessful =
             buildResult.getSuccessfulTargets().size() == configuredTargets.size();
-        runtime.getOutputService().finalizeBuild(isBuildSuccessful);
+        env.getOutputService().finalizeBuild(isBuildSuccessful);
       }
     }
   }
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 ebfd4bf..0640fb6 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
@@ -14,7 +14,6 @@
 
 package com.google.devtools.build.lib.runtime;
 
-import static com.google.devtools.build.lib.profiler.AutoProfiler.profiled;
 import static com.google.devtools.build.lib.profiler.AutoProfiler.profiledAndLogged;
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
 
@@ -172,8 +171,6 @@
   private final TimestampGranularityMonitor timestampGranularityMonitor;
   private final Clock clock;
 
-  private OutputService outputService;
-
   private final Iterable<BlazeModule> blazeModules;
 
   private final AtomicInteger storedExitCode = new AtomicInteger();
@@ -265,19 +262,6 @@
     }
   }
 
-  /**
-   * Figures out what file system we are writing output to. Here we use
-   * outputBase instead of outputPath because we need a file system to create the latter.
-   */
-  private String determineOutputFileSystem() {
-    if (getOutputService() != null) {
-      return getOutputService().getFilesSystemName();
-    }
-    try (AutoProfiler p = profiled("Finding output file system", ProfilerTask.INFO)) {
-      return FileSystemUtils.getFileSystem(getOutputBase());
-    }
-  }
-
   public CommandEnvironment initCommand() {
     EventBus eventBus = new EventBus(eventBusExceptionHandler);
     skyframeExecutor.setEventBus(eventBus);
@@ -596,30 +580,7 @@
   void beforeCommand(Command command, CommandEnvironment env, OptionsParser optionsParser,
       CommonCommandOptions options, long execStartTimeNanos)
       throws AbruptExitException {
-    env.getEventBus().post(new GotOptionsEvent(startupOptionsProvider,
-        optionsParser));
-    env.throwPendingException();
-
-    outputService = null;
-    BlazeModule outputModule = null;
-    for (BlazeModule module : blazeModules) {
-      OutputService moduleService = module.getOutputService();
-      if (moduleService != null) {
-        if (outputService != null) {
-          throw new IllegalStateException(String.format(
-              "More than one module (%s and %s) returns an output service",
-              module.getClass(), outputModule.getClass()));
-        }
-        outputService = moduleService;
-        outputModule = module;
-      }
-    }
-
-    skyframeExecutor.setBatchStatter(outputService == null
-        ? null
-        : outputService.getBatchStatter());
-
-    env.setOutputFileSystem(determineOutputFileSystem());
+    env.setOutputFileSystem(env.determineOutputFileSystem());
 
     // Ensure that the working directory will be under the workspace directory.
     Path workspace = getWorkspace();
@@ -786,13 +747,6 @@
     };
   }
 
-  /**
-   * @return the OutputService in use, or null if none.
-   */
-  public OutputService getOutputService() {
-    return outputService;
-  }
-
   private String getFileSizeString(Path path, String type) {
     try {
       return String.format("%d bytes (%s)", path.getFileSize(), type);
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 9eda313..806fd01 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
@@ -14,6 +14,8 @@
 
 package com.google.devtools.build.lib.runtime;
 
+import static com.google.devtools.build.lib.profiler.AutoProfiler.profiled;
+
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
@@ -31,15 +33,19 @@
 import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.exec.OutputService;
 import com.google.devtools.build.lib.packages.NoSuchThingException;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.pkgcache.LoadingPhaseRunner;
 import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
 import com.google.devtools.build.lib.pkgcache.PackageManager;
 import com.google.devtools.build.lib.pkgcache.TargetPatternEvaluator;
+import com.google.devtools.build.lib.profiler.AutoProfiler;
+import com.google.devtools.build.lib.profiler.ProfilerTask;
 import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
 import com.google.devtools.build.lib.util.AbruptExitException;
 import com.google.devtools.build.lib.util.ExitCode;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.common.options.OptionsParser;
 import com.google.devtools.common.options.OptionsProvider;
@@ -72,6 +78,7 @@
   private final BuildView view;
 
   private long commandStartTime;
+  private OutputService outputService;
   private String outputFileSystem;
   private Path workingDirectory;
 
@@ -82,8 +89,8 @@
     public Path getFileFromWorkspace(Label label)
         throws NoSuchThingException, InterruptedException, IOException {
       Target target = getPackageManager().getTarget(reporter, label);
-      return (runtime.getOutputService() != null)
-          ? runtime.getOutputService().stageTool(target)
+      return (outputService != null)
+          ? outputService.stageTool(target)
           : target.getPackage().getPackageDirectory().getRelative(target.getName());
     }
 
@@ -201,6 +208,13 @@
     return workingDirectory;
   }
 
+  /**
+   * @return the OutputService in use, or null if none.
+   */
+  public OutputService getOutputService() {
+    return outputService;
+  }
+
   public ActionCache getPersistentActionCache() throws IOException {
     return runtime.getPersistentActionCache(reporter);
   }
@@ -306,6 +320,41 @@
       throws AbruptExitException {
     commandStartTime -= options.startupTime;
 
+    eventBus.post(new GotOptionsEvent(runtime.getStartupOptionsProvider(), optionsParser));
+    throwPendingException();
+
+    outputService = null;
+    BlazeModule outputModule = null;
+    for (BlazeModule module : runtime.getBlazeModules()) {
+      OutputService moduleService = module.getOutputService();
+      if (moduleService != null) {
+        if (outputService != null) {
+          throw new IllegalStateException(String.format(
+              "More than one module (%s and %s) returns an output service",
+              module.getClass(), outputModule.getClass()));
+        }
+        outputService = moduleService;
+        outputModule = module;
+      }
+    }
+
+    getSkyframeExecutor().setBatchStatter(outputService == null
+        ? null
+        : outputService.getBatchStatter());
+
     runtime.beforeCommand(command, this, optionsParser, options, execStartTimeNanos);
   }
+
+  /**
+   * Figures out what file system we are writing output to. Here we use
+   * outputBase instead of outputPath because we need a file system to create the latter.
+   */
+  String determineOutputFileSystem() {
+    if (getOutputService() != null) {
+      return getOutputService().getFilesSystemName();
+    }
+    try (AutoProfiler p = profiled("Finding output file system", ProfilerTask.INFO)) {
+      return FileSystemUtils.getFileSystem(runtime.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 4b7b4e3..63b7174 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
@@ -125,8 +125,8 @@
       Path outputBase, Options cleanOptions, String symlinkPrefix) throws IOException,
       ShutdownBlazeServerException, CommandException, ExecException, InterruptedException {
     BlazeRuntime runtime = env.getRuntime();
-    if (runtime.getOutputService() != null) {
-      runtime.getOutputService().clean();
+    if (env.getOutputService() != null) {
+      env.getOutputService().clean();
     }
     if (cleanOptions.expunge) {
       LOG.info("Expunging...");