// Copyright 2014 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.analysis.actions;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.devtools.build.lib.actions.ActionAnalysisMetadata.mergeMaps;
import static com.google.devtools.build.lib.packages.ExecGroup.DEFAULT_EXEC_GROUP_NAME;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Interner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.AbstractAction;
import com.google.devtools.build.lib.actions.ActionEnvironment;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionException;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.ActionResult;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
import com.google.devtools.build.lib.actions.BaseSpawn;
import com.google.devtools.build.lib.actions.CommandAction;
import com.google.devtools.build.lib.actions.CommandLine;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.actions.CommandLineItem;
import com.google.devtools.build.lib.actions.CommandLineLimits;
import com.google.devtools.build.lib.actions.CommandLines;
import com.google.devtools.build.lib.actions.CommandLines.CommandLineAndParamFileInfo;
import com.google.devtools.build.lib.actions.CommandLines.ExpandedCommandLines;
import com.google.devtools.build.lib.actions.CompositeRunfilesSupplier;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.PathMapper;
import com.google.devtools.build.lib.actions.ResourceSetOrBuilder;
import com.google.devtools.build.lib.actions.RunfilesSupplier;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.extra.EnvironmentVariable;
import com.google.devtools.build.lib.actions.extra.ExtraActionInfo;
import com.google.devtools.build.lib.actions.extra.SpawnInfo;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.CoreOptions.OutputPathsMode;
import com.google.devtools.build.lib.analysis.starlark.Args;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.exec.SpawnStrategyResolver;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.server.FailureDetails.Spawn.Code;
import com.google.devtools.build.lib.starlarkbuildapi.CommandLineArgsApi;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.OnDemandString;
import com.google.devtools.build.lib.util.ShellEscaper;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
import com.google.errorprone.annotations.CompileTimeConstant;
import com.google.errorprone.annotations.ForOverride;
import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.FormatString;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.StarlarkList;

/** An Action representing an arbitrary subprocess to be forked and exec'd. */
public class SpawnAction extends AbstractAction implements CommandAction {

  private static final String GUID = "ebd6fce3-093e-45ee-adb6-bf513b602f0d";

  private static final Interner<ImmutableSortedMap<String, String>> executionInfoInterner =
      BlazeInterners.newWeakInterner();

  private final NestedSet<Artifact> tools;
  private final RunfilesSupplier runfilesSupplier;
  private final CommandLines commandLines;
  private final ActionEnvironment env;

  private final CharSequence progressMessage;
  private final String mnemonic;

  private final ResourceSetOrBuilder resourceSetOrBuilder;
  private final ImmutableMap<String, String> executionInfo;
  private final OutputPathsMode outputPathsMode;

  /**
   * Constructs a SpawnAction using direct initialization arguments.
   *
   * <p>All collections provided must not be subsequently modified.
   *
   * @param owner the owner of the Action
   * @param tools the set of files comprising the tool that does the work (e.g. compiler). This is a
   *     subset of "inputs" and is only used by the WorkerSpawnStrategy
   * @param inputs the set of all files potentially read by this action; must not be subsequently
   *     modified
   * @param outputs the set of all files written by this action; must not be subsequently modified.
   * @param resourceSetOrBuilder the resources consumed by executing this Action.
   * @param env the action's environment
   * @param executionInfo out-of-band information for scheduling the spawn
   * @param commandLines the command lines to execute. This includes the main argv vector and any
   *     param file-backed command lines.
   * @param progressMessage the message printed during the progression of the build
   * @param runfilesSupplier {@link RunfilesSupplier}s describing the runfiles for the action
   * @param mnemonic the mnemonic that is reported in the master log
   */
  public SpawnAction(
      ActionOwner owner,
      NestedSet<Artifact> tools,
      NestedSet<Artifact> inputs,
      Iterable<? extends Artifact> outputs,
      ResourceSetOrBuilder resourceSetOrBuilder,
      CommandLines commandLines,
      ActionEnvironment env,
      ImmutableMap<String, String> executionInfo,
      CharSequence progressMessage,
      RunfilesSupplier runfilesSupplier,
      String mnemonic,
      OutputPathsMode outputPathsMode) {
    super(owner, inputs, outputs);
    this.tools = tools;
    this.runfilesSupplier = runfilesSupplier;
    this.resourceSetOrBuilder = resourceSetOrBuilder;
    this.executionInfo =
        executionInfo.isEmpty()
            ? ImmutableSortedMap.of()
            : executionInfoInterner.intern(ImmutableSortedMap.copyOf(executionInfo));
    this.commandLines = commandLines;
    this.env = env;
    this.progressMessage = progressMessage;
    this.mnemonic = mnemonic;
    this.outputPathsMode = outputPathsMode;
  }

  @Override
  public final NestedSet<Artifact> getTools() {
    return tools;
  }

  @Override
  public final RunfilesSupplier getRunfilesSupplier() {
    return runfilesSupplier;
  }

  @Override
  public final ActionEnvironment getEnvironment() {
    return env;
  }

  @VisibleForTesting
  public CommandLines getCommandLines() {
    return commandLines;
  }

  @Override
  public List<String> getArguments() throws CommandLineExpansionException, InterruptedException {
    return commandLines.allArguments(PathMappers.create(this, outputPathsMode));
  }

  @Override
  public Sequence<CommandLineArgsApi> getStarlarkArgs() {
    ImmutableList.Builder<CommandLineArgsApi> result = ImmutableList.builder();
    ImmutableSet<Artifact> directoryInputs =
        getInputs().toList().stream().filter(Artifact::isDirectory).collect(toImmutableSet());

    for (CommandLineAndParamFileInfo commandLine : commandLines.unpack()) {
      result.add(Args.forRegisteredAction(commandLine, directoryInputs));
    }
    return StarlarkList.immutableCopyOf(result.build());
  }

  @Override
  public Sequence<String> getStarlarkArgv() throws EvalException, InterruptedException {
    try {
      return StarlarkList.immutableCopyOf(getArguments());
    } catch (CommandLineExpansionException ex) {
      throw new EvalException(ex);
    }
  }

  @Override
  @VisibleForTesting
  public NestedSet<Artifact> getPossibleInputsForTesting() {
    return getInputs();
  }

  /** Returns command argument, argv[0]. */
  @VisibleForTesting
  public String getCommandFilename() throws CommandLineExpansionException, InterruptedException {
    return Iterables.getFirst(getArguments(), null);
  }

  /** Returns the (immutable) list of arguments, excluding the command name, argv[0]. */
  @VisibleForTesting
  public List<String> getRemainingArguments()
      throws CommandLineExpansionException, InterruptedException {
    return ImmutableList.copyOf(Iterables.skip(getArguments(), 1));
  }

  @Override
  public final boolean isVolatile() {
    return executeUnconditionally();
  }

  /** Hook for subclasses to perform work before the spawn is executed. */
  protected void beforeExecute(ActionExecutionContext actionExecutionContext)
      throws ExecException {}

  /**
   * Hook for subclasses to perform work after the spawn is executed. This method is only executed
   * if the subprocess execution returns normally, not in case of errors (non-zero exit,
   * setup/network failures, etc.).
   */
  @ForOverride
  protected void afterExecute(
      ActionExecutionContext actionExecutionContext,
      List<SpawnResult> spawnResults,
      PathMapper pathMapper)
      throws ExecException, InterruptedException {}

  @Override
  public final ActionResult execute(ActionExecutionContext actionExecutionContext)
      throws ActionExecutionException, InterruptedException {
    try {
      beforeExecute(actionExecutionContext);
      Spawn spawn = getSpawn(actionExecutionContext);
      ImmutableList<SpawnResult> result =
          actionExecutionContext
              .getContext(SpawnStrategyResolver.class)
              .exec(spawn, actionExecutionContext);
      afterExecute(actionExecutionContext, result, spawn.getPathMapper());
      return ActionResult.create(result);
    } catch (CommandLineExpansionException e) {
      throw createCommandLineException(e);
    } catch (ExecException e) {
      throw ActionExecutionException.fromExecException(e, this);
    }
  }

  private ActionExecutionException createCommandLineException(CommandLineExpansionException e) {
    DetailedExitCode detailedExitCode =
        DetailedExitCode.of(
            FailureDetail.newBuilder()
                .setMessage(Strings.nullToEmpty(e.getMessage()))
                .setSpawn(
                    FailureDetails.Spawn.newBuilder().setCode(Code.COMMAND_LINE_EXPANSION_FAILURE))
                .build());
    return new ActionExecutionException(e, this, /*catastrophe=*/ false, detailedExitCode);
  }

  @VisibleForTesting
  public ResourceSetOrBuilder getResourceSetOrBuilder() {
    return resourceSetOrBuilder;
  }

  /**
   * Returns a Spawn that is representative of the command that this Action will execute. This
   * function must not modify any state.
   *
   * <p>This method is final, as it is merely a shorthand use of the generic way to obtain a spawn,
   * which also depends on the client environment. Subclasses that wish to override the way to get a
   * spawn should override the other getSpawn() methods instead.
   */
  @VisibleForTesting
  public final Spawn getSpawn() throws CommandLineExpansionException, InterruptedException {
    return getSpawn(getInputs());
  }

  final Spawn getSpawn(NestedSet<Artifact> inputs)
      throws CommandLineExpansionException, InterruptedException {
    return new ActionSpawn(
        commandLines.allArguments(),
        this,
        /* env= */ ImmutableMap.of(),
        /* envResolved= */ false,
        inputs,
        /* additionalInputs= */ ImmutableList.of(),
        /* filesetMappings= */ ImmutableMap.of(),
        /* reportOutputs= */ true,
        PathMapper.NOOP);
  }

  /**
   * Returns a spawn that is representative of the command that this Action will execute in the
   * given client environment.
   */
  public Spawn getSpawn(ActionExecutionContext actionExecutionContext)
      throws CommandLineExpansionException, InterruptedException {
    return getSpawn(
        actionExecutionContext.getArtifactExpander(),
        actionExecutionContext.getClientEnv(),
        /*envResolved=*/ false,
        actionExecutionContext.getTopLevelFilesets(),
        /*reportOutputs=*/ true);
  }

  /**
   * Return a spawn that is representative of the command that this Action will execute in the given
   * environment.
   *
   * @param envResolved If set to true, the passed environment variables will be used as the Spawn
   *     effective environment. Otherwise they will be used as client environment to resolve the
   *     action env.
   */
  protected Spawn getSpawn(
      ArtifactExpander artifactExpander,
      Map<String, String> env,
      boolean envResolved,
      Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings,
      boolean reportOutputs)
      throws CommandLineExpansionException, InterruptedException {
    PathMapper pathMapper = PathMappers.create(this, outputPathsMode);
    ExpandedCommandLines expandedCommandLines =
        commandLines.expand(
            artifactExpander, getPrimaryOutput().getExecPath(), pathMapper, getCommandLineLimits());
    return new ActionSpawn(
        ImmutableList.copyOf(expandedCommandLines.arguments()),
        this,
        env,
        envResolved,
        getInputs(),
        expandedCommandLines.getParamFiles(),
        filesetMappings,
        reportOutputs,
        pathMapper);
  }

  @ForOverride
  protected CommandLineLimits getCommandLineLimits() {
    return getOwner().getBuildConfigurationInfo().getCommandLineLimits();
  }

  Spawn getSpawnForExtraAction() throws CommandLineExpansionException, InterruptedException {
    return getSpawn(getInputs());
  }

  @Override
  protected void computeKey(
      ActionKeyContext actionKeyContext,
      @Nullable ArtifactExpander artifactExpander,
      Fingerprint fp)
      throws CommandLineExpansionException, InterruptedException {
    fp.addString(GUID);
    commandLines.addToFingerprint(actionKeyContext, artifactExpander, fp);
    fp.addString(mnemonic);
    // We don't need the toolManifests here, because they are a subset of the inputManifests by
    // definition and the output of an action shouldn't change whether something is considered a
    // tool or not.
    fp.addPaths(runfilesSupplier.getRunfilesDirs());
    env.addTo(fp);
    fp.addStringMap(getExecutionInfo());
    PathMappers.addToFingerprint(getMnemonic(), getExecutionInfo(), outputPathsMode, fp);
  }

  @Override
  public String describeKey() {
    StringBuilder message = new StringBuilder();
    message.append(getProgressMessage());
    message.append('\n');
    for (Map.Entry<String, String> entry : env.getFixedEnv().entrySet()) {
      message.append("  Environment variable: ");
      message.append(ShellEscaper.escapeString(entry.getKey()));
      message.append('=');
      message.append(ShellEscaper.escapeString(entry.getValue()));
      message.append('\n');
    }
    for (String var : getClientEnvironmentVariables()) {
      message.append("  Environment variables taken from the client environment: ");
      message.append(ShellEscaper.escapeString(var));
      message.append('\n');
    }
    try {
      for (String argument : ShellEscaper.escapeAll(getArguments())) {
        message.append("  Argument: ");
        message.append(argument);
        message.append('\n');
      }
    } catch (InterruptedException ex) {
      Thread.currentThread().interrupt();
      message.append("Interrupted while expanding command line\n");
    } catch (CommandLineExpansionException e) {
      message.append("Could not expand command line: ");
      message.append(e);
      message.append('\n');
    }
    message.append("  Output paths mode: ");
    message.append(outputPathsMode);
    message.append('\n');
    return message.toString();
  }

  @Override
  public final String getMnemonic() {
    return mnemonic;
  }

  @Override
  protected String getRawProgressMessage() {
    if (progressMessage != null) {
      return progressMessage.toString();
    }
    return super.getRawProgressMessage();
  }

  @Override
  public ExtraActionInfo.Builder getExtraActionInfo(ActionKeyContext actionKeyContext)
      throws CommandLineExpansionException, InterruptedException {
    return super.getExtraActionInfo(actionKeyContext)
        .setExtension(SpawnInfo.spawnInfo, getExtraActionSpawnInfo());
  }

  /**
   * Returns information about this spawn action for use by the extra action mechanism.
   *
   * <p>Subclasses of SpawnAction may override this in order to provide action-specific behaviour.
   * This can be necessary, for example, when the action discovers inputs.
   */
  private SpawnInfo getExtraActionSpawnInfo()
      throws CommandLineExpansionException, InterruptedException {
    SpawnInfo.Builder info = SpawnInfo.newBuilder();
    Spawn spawn = getSpawnForExtraAction();
    info.addAllArgument(spawn.getArguments());
    for (Map.Entry<String, String> variable : spawn.getEnvironment().entrySet()) {
      info.addVariable(
          EnvironmentVariable.newBuilder()
              .setName(variable.getKey())
              .setValue(variable.getValue())
              .build());
    }
    for (ActionInput input : spawn.getInputFiles().toList()) {
      // Explicitly ignore middleman artifacts here.
      if (!(input instanceof Artifact) || !((Artifact) input).isMiddlemanArtifact()) {
        info.addInputFile(input.getExecPathString());
      }
    }
    info.addAllOutputFile(ActionInputHelper.toExecPaths(spawn.getOutputFiles()));
    return info.build();
  }

  @Override
  @VisibleForTesting
  public final ImmutableMap<String, String> getIncompleteEnvironmentForTesting() {
    // TODO(ulfjack): AbstractAction should declare getEnvironment with a return value of type
    // ActionEnvironment to avoid developers misunderstanding the purpose of this method. That
    // requires first updating all subclasses and callers to actually handle environments correctly,
    // so it's not a small change.
    return getEnvironment().getFixedEnv();
  }

  /** Returns the out-of-band execution data for this action. */
  @Override
  public ImmutableMap<String, String> getExecutionInfo() {
    return mergeMaps(super.getExecutionInfo(), executionInfo);
  }

  /** A spawn instance that is tied to a specific SpawnAction. */
  private static final class ActionSpawn extends BaseSpawn {
    private final NestedSet<ActionInput> inputs;
    private final Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings;
    private final ImmutableMap<String, String> effectiveEnvironment;
    private final boolean reportOutputs;
    private final PathMapper pathMapper;

    /**
     * Creates an ActionSpawn with the given environment variables.
     *
     * <p>Subclasses of ActionSpawn may subclass in order to provide action-specific values for
     * environment variables or action inputs.
     */
    private ActionSpawn(
        ImmutableList<String> arguments,
        SpawnAction parent,
        Map<String, String> env,
        boolean envResolved,
        NestedSet<Artifact> inputs,
        Iterable<? extends ActionInput> additionalInputs,
        Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings,
        boolean reportOutputs,
        PathMapper pathMapper)
        throws CommandLineExpansionException {
      super(
          arguments,
          ImmutableMap.of(),
          parent.getExecutionInfo(),
          parent.getRunfilesSupplier(),
          parent,
          parent.resourceSetOrBuilder);
      this.inputs = getNonFilesetInputs(inputs).addAll(additionalInputs).build();
      this.filesetMappings = filesetMappings;
      this.pathMapper = pathMapper;

      // If the action environment is already resolved using the client environment, the given
      // environment variables are used as they are. Otherwise, they are used as clientEnv to
      // resolve the action environment variables.
      if (envResolved) {
        effectiveEnvironment = ImmutableMap.copyOf(env);
      } else {
        effectiveEnvironment = parent.getEffectiveEnvironment(env);
      }
      this.reportOutputs = reportOutputs;
    }

    /** Returns a {@link NestedSetBuilder} containing only the non-fileset inputs. */
    private static NestedSetBuilder<ActionInput> getNonFilesetInputs(NestedSet<Artifact> inputs) {
      NestedSetBuilder<ActionInput> builder = NestedSetBuilder.stableOrder();
      // TODO(tjgq): Investigate whether we can avoid flattening when filesetMappings is empty.
      // This requires auditing getSpawnForExtraAction(), which doesn't appear to propagate the
      // filesetMappings from the shadowed action.
      boolean hasFilesets = false;
      for (Artifact input : inputs.toList()) {
        if (!input.isFileset()) {
          builder.add(input);
        } else {
          hasFilesets = true;
        }
      }
      // If possible, keep the original nested set. This aids callers that exploit the nested set
      // structure to perform optimizations (see SpawnInputExpander#walkInputs and its callers).
      return hasFilesets
          ? builder
          : NestedSetBuilder.<ActionInput>stableOrder().addTransitive(inputs);
    }

    @Override
    public PathMapper getPathMapper() {
      return pathMapper;
    }

    @Override
    public ImmutableMap<String, String> getEnvironment() {
      return effectiveEnvironment;
    }

    @Override
    public ImmutableMap<Artifact, ImmutableList<FilesetOutputSymlink>> getFilesetMappings() {
      return ImmutableMap.copyOf(filesetMappings);
    }

    @Override
    public NestedSet<? extends ActionInput> getInputFiles() {
      return inputs;
    }

    @Override
    public Collection<Artifact> getOutputFiles() {
      return reportOutputs ? super.getOutputFiles() : ImmutableSet.of();
    }
  }

  /**
   * Builder class to construct {@link SpawnAction} instances.
   */
  public static class Builder {

    private final NestedSetBuilder<Artifact> toolsBuilder = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<Artifact> inputsBuilder = NestedSetBuilder.stableOrder();
    private final List<Artifact> outputs = new ArrayList<>();
    private final List<RunfilesSupplier> inputRunfilesSuppliers = new ArrayList<>();
    private ResourceSetOrBuilder resourceSetOrBuilder = AbstractAction.DEFAULT_RESOURCE_SET;
    private ImmutableMap<String, String> environment = ImmutableMap.of();
    private ImmutableMap<String, String> executionInfo = ImmutableMap.of();
    private boolean useDefaultShellEnvironment = false;
    protected boolean executeUnconditionally;
    private Object executableArg;
    @Nullable private CustomCommandLine.Builder executableArgs;
    private List<CommandLineAndParamFileInfo> commandLines = new ArrayList<>();

    private CharSequence progressMessage;
    private String mnemonic = "Unknown";
    private String execGroup = DEFAULT_EXEC_GROUP_NAME;

    /** Creates a SpawnAction builder. */
    public Builder() {}

    /** Creates a builder that is a copy of another builder. */
    public Builder(Builder other) {
      this.toolsBuilder.addTransitive(other.toolsBuilder.build());
      this.inputsBuilder.addTransitive(other.inputsBuilder.build());
      this.outputs.addAll(other.outputs);
      this.inputRunfilesSuppliers.addAll(other.inputRunfilesSuppliers);
      this.resourceSetOrBuilder = other.resourceSetOrBuilder;
      this.environment = other.environment;
      this.executionInfo = other.executionInfo;
      this.useDefaultShellEnvironment = other.useDefaultShellEnvironment;
      this.executableArg = other.executableArg;
      this.executableArgs = other.executableArgs;
      this.commandLines = new ArrayList<>(other.commandLines);
      this.progressMessage = other.progressMessage;
      this.mnemonic = other.mnemonic;
    }

    /**
     * Builds the SpawnAction using the passed-in action configuration.
     *
     * <p>This method makes a copy of all the collections, so it is safe to reuse the builder after
     * this method returns.
     *
     * <p>This is annotated with @CheckReturnValue, which causes a compiler error when you call this
     * method and ignore its return value. This is because some time ago, calling .build() had the
     * side-effect of registering it with the RuleContext that was passed in to the constructor.
     * This logic was removed, but if people don't notice and still rely on the side-effect, things
     * may break.
     *
     * @return the SpawnAction.
     */
    @CheckReturnValue
    public SpawnAction build(ActionConstructionContext context) {
      return build(context.getActionOwner(execGroup), context.getConfiguration());
    }

    @VisibleForTesting
    @CheckReturnValue
    public SpawnAction build(ActionOwner owner, BuildConfigurationValue configuration) {
      CommandLines.Builder result = CommandLines.builder();
      if (executableArg != null) {
        result.addSingleArgument(executableArg);
      } else if (executableArgs != null) {
        result.addCommandLine(executableArgs.build());
      }
      for (CommandLineAndParamFileInfo pair : this.commandLines) {
        result.addCommandLine(pair);
      }
      CommandLines commandLines = result.build();
      ActionEnvironment env;
      if (useDefaultShellEnvironment && environment != null) {
        // Inherited variables override fixed variables in ActionEnvironment. Since we want the
        // fixed part of the action-provided environment to override the inherited part of the
        // user-provided environment, we have to explicitly filter the inherited part.
        var userFilteredInheritedEnv =
            ImmutableSet.copyOf(
                Sets.difference(
                    configuration.getActionEnvironment().getInheritedEnv(), environment.keySet()));
        // Do not create a new ActionEnvironment in the common case where no vars have been filtered
        // out.
        if (userFilteredInheritedEnv.equals(
            configuration.getActionEnvironment().getInheritedEnv())) {
          env = configuration.getActionEnvironment();
        } else {
          env =
              ActionEnvironment.create(
                  configuration.getActionEnvironment().getFixedEnv(), userFilteredInheritedEnv);
        }
        env = env.withAdditionalFixedVariables(environment);
      } else if (useDefaultShellEnvironment) {
        env = configuration.getActionEnvironment();
      } else {
        env = ActionEnvironment.create(environment);
      }
      return buildSpawnAction(owner, commandLines, configuration, env);
    }

    @CheckReturnValue
    public SpawnAction buildForActionTemplate(ActionOwner owner) {
      CommandLines.Builder result = CommandLines.builder();
      if (executableArg != null) {
        result.addSingleArgument(executableArg);
      } else {
        result.addCommandLine(executableArgs.build());
      }
      for (CommandLineAndParamFileInfo pair : commandLines) {
        result.addCommandLine(pair.commandLine);
      }
      return buildSpawnAction(owner, result.build(), null, ActionEnvironment.create(environment));
    }

    /**
     * Builds the SpawnAction using the passed-in action configuration.
     *
     * <p>This method makes a copy of all the collections, so it is safe to reuse the builder after
     * this method returns.
     */
    private SpawnAction buildSpawnAction(
        ActionOwner owner,
        CommandLines commandLines,
        @Nullable BuildConfigurationValue configuration,
        ActionEnvironment env) {
      NestedSet<Artifact> tools = toolsBuilder.build();

      // Don't call getInputsAndTools - it wouldn't reuse the built set of tools.
      NestedSet<Artifact> inputsAndTools =
          NestedSetBuilder.<Artifact>stableOrder()
              .addTransitive(inputsBuilder.build())
              .addTransitive(tools)
              .build();

      return createSpawnAction(
          owner,
          tools,
          inputsAndTools,
          ImmutableSet.copyOf(outputs),
          resourceSetOrBuilder,
          commandLines,
          env,
          configuration,
          configuration == null
              ? executionInfo
              : configuration.modifiedExecutionInfo(executionInfo, mnemonic),
          progressMessage,
          CompositeRunfilesSupplier.fromSuppliers(this.inputRunfilesSuppliers),
          mnemonic);
    }

    /** Creates a SpawnAction. */
    protected SpawnAction createSpawnAction(
        ActionOwner owner,
        NestedSet<Artifact> tools,
        NestedSet<Artifact> inputsAndTools,
        ImmutableSet<Artifact> outputs,
        ResourceSetOrBuilder resourceSetOrBuilder,
        CommandLines commandLines,
        ActionEnvironment env,
        @Nullable BuildConfigurationValue configuration,
        ImmutableMap<String, String> executionInfo,
        CharSequence progressMessage,
        RunfilesSupplier runfilesSupplier,
        String mnemonic) {
      return new SpawnAction(
          owner,
          tools,
          inputsAndTools,
          outputs,
          resourceSetOrBuilder,
          commandLines,
          env,
          executionInfo,
          progressMessage,
          runfilesSupplier,
          mnemonic,
          PathMappers.getOutputPathsMode(configuration));
    }

    /**
     * Adds an artifact that is necessary for executing the spawn itself (e.g. a compiler), in
     * contrast to an artifact that is necessary for the spawn to do its work (e.g. source code).
     *
     * <p>The artifact is implicitly added to the inputs of the action as well.
     */
    @CanIgnoreReturnValue
    public Builder addTool(Artifact tool) {
      toolsBuilder.add(tool);
      return this;
    }

    /**
     * Adds an executable and its runfiles, which is necessary for executing the spawn itself (e.g.
     * a compiler), in contrast to artifacts that are necessary for the spawn to do its work (e.g.
     * source code).
     */
    @CanIgnoreReturnValue
    public Builder addTool(FilesToRunProvider tool) {
      addTransitiveTools(tool.getFilesToRun());
      addRunfilesSupplier(tool.getRunfilesSupplier());
      return this;
    }

    /** Adds an input to this action. */
    @CanIgnoreReturnValue
    public Builder addInput(Artifact artifact) {
      inputsBuilder.add(artifact);
      return this;
    }

    /** Adds tools to this action. */
    @CanIgnoreReturnValue
    Builder addTools(Iterable<Artifact> artifacts) {
      toolsBuilder.addAll(artifacts);
      return this;
    }

    /** Adds tools to this action. */
    @CanIgnoreReturnValue
    public Builder addTransitiveTools(NestedSet<Artifact> artifacts) {
      toolsBuilder.addTransitive(artifacts);
      return this;
    }

    /** Adds inputs to this action. */
    @CanIgnoreReturnValue
    public Builder addInputs(Iterable<Artifact> artifacts) {
      inputsBuilder.addAll(artifacts);
      return this;
    }

    /**
     * Returns the inputs that the spawn action will depend on. Tools are by definition a subset of
     * the inputs, so they are also present.
     *
     * <p>Warning: this calls {@link NestedSetBuilder#build} on both inputs and tools.
     */
    // TODO(antunesi): Refactor so this method isn't needed. Building new NestedSets on every call
    // is a memory vulnerability, see b/291063247.
    public NestedSet<Artifact> getInputsAndTools() {
      return NestedSetBuilder.<Artifact>stableOrder()
          .addTransitive(inputsBuilder.build())
          .addTransitive(toolsBuilder.build())
          .build();
    }

    /** Adds transitive inputs to this action. */
    @CanIgnoreReturnValue
    public Builder addTransitiveInputs(NestedSet<Artifact> artifacts) {
      inputsBuilder.addTransitive(artifacts);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addRunfilesSupplier(RunfilesSupplier supplier) {
      inputRunfilesSuppliers.add(supplier);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addOutput(Artifact artifact) {
      outputs.add(artifact);
      return this;
    }

    @CanIgnoreReturnValue
    public Builder addOutputs(Iterable<Artifact> artifacts) {
      Iterables.addAll(outputs, artifacts);
      return this;
    }

    /**
     * Sets RecourceSet for builder. If ResourceSetBuilder set, then ResourceSetBuilder will
     * override setResources.
     */
    @CanIgnoreReturnValue
    public Builder setResources(ResourceSetOrBuilder resourceSetOrBuilder) {
      this.resourceSetOrBuilder = resourceSetOrBuilder;
      return this;
    }

    /**
     * Sets the map of environment variables. Do not use! This makes the builder ignore the 'default
     * shell environment', which is computed from the --action_env command line option.
     */
    @CanIgnoreReturnValue
    public Builder setEnvironment(Map<String, String> environment) {
      this.environment = ImmutableMap.copyOf(environment);
      this.useDefaultShellEnvironment = false;
      return this;
    }

    /** Sets the map of execution info. */
    @CanIgnoreReturnValue
    public Builder setExecutionInfo(Map<String, String> info) {
      this.executionInfo = ImmutableMap.copyOf(info);
      return this;
    }

    /**
     * Sets the environment to the configuration's default shell environment.
     *
     * <p><b>All actions should set this if possible and avoid using {@link #setEnvironment}.</b>
     *
     * <p>When this property is set, the action will use a minimal, standardized environment map.
     *
     * <p>The list of envvars available to the action (the keys in this map) comes from two places:
     * from the rule class provider and from the command line or rc-files via {@code --action_env}
     * flags.
     *
     * <p>The values for these variables may come from one of three places: from the configuration
     * fragment, or from the {@code --action_env} flag (when the flag specifies a name-value pair,
     * e.g. {@code --action_env=FOO=bar}), or from the client environment (when the flag only
     * specifies a name, e.g. {@code --action_env=HOME}).
     *
     * <p>The client environment is specified by the {@code --client_env} flags. The Bazel client
     * passes these flags to the Bazel server upon each build (e.g. {@code
     * --client_env=HOME=/home/johndoe}), so the server can keep track of environmental changes
     * between builds, and always use the up-to-date environment (as opposed to calling {@code
     * System.getenv}, which it should never do, though as of 2017-08-02 it still does in a few
     * places).
     *
     * <p>The {@code --action_env} has priority over configuration-fragment-dictated envvar values,
     * i.e. if the configuration fragment tries to add FOO=bar to the environment, and there's also
     * {@code --action_env=FOO=baz} or {@code --action_env=FOO}, then FOO will be available to the
     * action and its value will be "baz", or whatever the corresponding {@code --client_env} flag
     * specified, respectively.
     *
     * @see BuildConfigurationValue#getLocalShellEnvironment
     */
    @CanIgnoreReturnValue
    public Builder useDefaultShellEnvironment() {
      this.environment = null;
      this.useDefaultShellEnvironment = true;
      return this;
    }

    /**
     * Same as {@link #useDefaultShellEnvironment()}, but additionally sets the provided fixed
     * environment variables, which take precedence over the variables contained in the default
     * shell environment.
     */
    @CanIgnoreReturnValue
    public Builder useDefaultShellEnvironmentWithOverrides(Map<String, String> environment) {
      this.environment = ImmutableMap.copyOf(environment);
      this.useDefaultShellEnvironment = true;
      return this;
    }

    /**
     * Sets the executable path; the path is interpreted relative to the execution root, unless it's
     * a bare file name.
     *
     * <p><b>Caution</b>: if the executable is a bare file name ("foo"), it will be interpreted
     * relative to PATH. See https://github.com/bazelbuild/bazel/issues/13189 for details. To avoid
     * that, use {@link #setExecutable(Artifact)} instead.
     *
     * <p>Calling this method overrides any previous values set via calls to {@link #setExecutable}
     * or {@link #setShellCommand}.
     */
    @CanIgnoreReturnValue
    public Builder setExecutable(PathFragment executable) {
      this.executableArg = executable;
      this.executableArgs = null;
      return this;
    }

    /**
     * Sets the executable as an artifact.
     *
     * <p>Calling this method overrides any previous values set via calls to {@link #setExecutable}
     * or {@link #setShellCommand}.
     */
    @CanIgnoreReturnValue
    public Builder setExecutable(Artifact executable) {
      addTool(executable);
      this.executableArg = ensureCallable(executable);
      this.executableArgs = null;
      return this;
    }

    /**
     * Sets the executable as a configured target. Automatically adds the files to run to the tools
     * and inputs and uses the executable of the target as the executable.
     *
     * <p>Calling this method overrides any previous values set via calls to {@link #setExecutable}
     * or {@link #setShellCommand}.
     */
    @CanIgnoreReturnValue
    public Builder setExecutable(TransitiveInfoCollection executable) {
      FilesToRunProvider provider = checkNotNull(executable.getProvider(FilesToRunProvider.class));
      return setExecutable(provider);
    }

    /**
     * Sets the executable as a configured target. Automatically adds the files to run to the tools
     * and inputs and uses the executable of the target as the executable.
     *
     * <p>Calling this method overrides any previous values set via calls to {@link #setExecutable}
     * or {@link #setShellCommand}.
     */
    @CanIgnoreReturnValue
    public Builder setExecutable(FilesToRunProvider executableProvider) {
      Artifact executable =
          checkNotNull(
              executableProvider.getExecutable(), "The target does not have an executable");
      this.executableArg = ensureCallable(executable);
      this.executableArgs = null;
      return addTool(executableProvider);
    }

    /**
     * Sets the executable as a String.
     *
     * <p><b>Caution</b>: this is an optimisation intended to be used only by {@link
     * com.google.devtools.build.lib.analysis.starlark.StarlarkActionFactory}. It prevents reference
     * duplication when passing {@link PathFragment} to Starlark as a String and then executing with
     * it.
     *
     * <p>Calling this method overrides any previous values set via calls to {@link #setExecutable}
     * or {@link #setShellCommand}.
     */
    @CanIgnoreReturnValue
    public Builder setExecutableAsString(String executable) {
      this.executableArg = executable;
      this.executableArgs = null;
      return this;
    }

    /**
     * Sets the executable to be a jar executed from the given deploy jar. The deploy jar is
     * automatically added to the action inputs.
     *
     * <p>Assumes that the Jar artifact declares a main class.
     *
     * <p>Calling this method overrides any previous values set via calls to {@link #setExecutable}
     * or {@link #setShellCommand}.
     */
    @CanIgnoreReturnValue
    public Builder setJarExecutable(
        PathFragment javaExecutable, Artifact deployJar, NestedSet<String> jvmArgs) {
      this.executableArgs =
          CustomCommandLine.builder()
              .addPath(javaExecutable)
              .addAll(jvmArgs)
              .add("-jar")
              .addExecPath(deployJar);
      this.executableArg = null;
      toolsBuilder.add(deployJar);
      return this;
    }

    /**
     * Sets the executable to be the shell and adds the given command as the command to be executed.
     *
     * <p>Note that this will not clear the arguments, so any arguments will be passed in addition
     * to the command given here.
     *
     * <p>Calling this method overrides any previous values set via calls to {@link #setExecutable}
     * or {@link #setShellCommand}.
     */
    @CanIgnoreReturnValue
    public Builder setShellCommand(PathFragment shExecutable, String command, boolean pad) {
      this.executableArg = new ShellCommand(shExecutable, command, pad);
      this.executableArgs = null;
      return this;
    }

    /**
     * Sets the executable to be the shell and adds the given interned commands as the commands to
     * be executed.
     */
    @CanIgnoreReturnValue
    public Builder setShellCommand(Iterable<String> command, boolean pad) {
      this.executableArgs = CustomCommandLine.builder().addAll(ImmutableList.copyOf(command));
      if (pad) {
        executableArgs.add("");
      }
      this.executableArg = null;
      return this;
    }

    /** Appends the arguments to the list of executable arguments. */
    @CanIgnoreReturnValue
    public Builder addExecutableArguments(String... arguments) {
      if (executableArg != null) {
        executableArgs = CustomCommandLine.builder().addObject(executableArg);
        executableArg = null;
      }
      executableArgs.addAll(ImmutableList.copyOf(arguments));
      return this;
    }

    /**
     * Adds a delegate to compute the command line at a later time.
     *
     * <p>The arguments are added after the executable arguments. If you add multiple command lines,
     * they are expanded in the corresponding order.
     *
     * <p>The main intention of this method is to save memory by allowing client-controlled sharing
     * between actions and configured targets. Objects passed to this method MUST be immutable.
     *
     * <p>See also {@link CustomCommandLine}.
     */
    @CanIgnoreReturnValue
    public Builder addCommandLine(CommandLine commandLine) {
      this.commandLines.add(new CommandLineAndParamFileInfo(commandLine, null));
      return this;
    }

    /**
     * Adds a delegate to compute the command line at a later time, optionally spilled to a params
     * file.
     *
     * <p>The arguments are added after the executable arguments. If you add multiple command lines,
     * they are expanded in the corresponding order. If the command line is spilled to a params
     * file, it is replaced with an argument pointing to the param file.
     *
     * <p>The main intention of this method is to save memory by allowing client-controlled sharing
     * between actions and configured targets. Objects passed to this method MUST be immutable.
     *
     * <p>See also {@link CustomCommandLine}.
     */
    @CanIgnoreReturnValue
    public Builder addCommandLine(CommandLine commandLine, @Nullable ParamFileInfo paramFileInfo) {
      this.commandLines.add(new CommandLineAndParamFileInfo(commandLine, paramFileInfo));
      return this;
    }

    /**
     * Sets the progress message.
     *
     * <p>The message may contain <code>%{label}</code>, <code>%{input}</code> or <code>%{output}
     * </code> patterns, which are substituted with label string, first input or output's path,
     * respectively.
     */
    @CanIgnoreReturnValue
    public Builder setProgressMessage(@CompileTimeConstant String progressMessage) {
      this.progressMessage = progressMessage;
      return this;
    }

    /**
     * Sets the progress message. The string is lazily evaluated.
     *
     * @param progressMessage The message to display
     * @param subject Passed to {@link String#format}
     * @deprecated Use {@link #setProgressMessage(String)} with provided patterns.
     */
    @FormatMethod
    @Deprecated
    @CanIgnoreReturnValue
    public Builder setProgressMessage(@FormatString String progressMessage, Object subject) {
      return setProgressMessage(
          new OnDemandString() {
            @Override
            public String toString() {
              return String.format(progressMessage, subject);
            }
          });
    }

    /**
     * Sets the progress message. The string is lazily evaluated.
     *
     * @param progressMessage The message to display
     * @param subject0 Passed to {@link String#format}
     * @param subject1 Passed to {@link String#format}
     * @deprecated Use {@link #setProgressMessage(String)} with provided patterns.
     */
    @FormatMethod
    @Deprecated
    @CanIgnoreReturnValue
    public Builder setProgressMessage(
        @FormatString String progressMessage, Object subject0, Object subject1) {
      return setProgressMessage(
          new OnDemandString() {
            @Override
            public String toString() {
              return String.format(progressMessage, subject0, subject1);
            }
          });
    }

    /**
     * Sets the progress message. The string is lazily evaluated.
     *
     * @param progressMessage The message to display
     * @param subject0 Passed to {@link String#format}
     * @param subject1 Passed to {@link String#format}
     * @param subject2 Passed to {@link String#format}
     * @deprecated Use {@link #setProgressMessage(String)} with provided patterns.
     */
    @FormatMethod
    @Deprecated
    @CanIgnoreReturnValue
    public Builder setProgressMessage(
        @FormatString String progressMessage, Object subject0, Object subject1, Object subject2) {
      return setProgressMessage(
          new OnDemandString() {
            @Override
            public String toString() {
              return String.format(progressMessage, subject0, subject1, subject2);
            }
          });
    }

    /**
     * Sets a lazily computed progress message.
     *
     * <p>When possible, prefer use of one of the overloads that use {@link String#format}. If you
     * do use this overload, take care not to capture anything expensive.
     */
    @CanIgnoreReturnValue
    private Builder setProgressMessage(OnDemandString progressMessage) {
      this.progressMessage = progressMessage;
      return this;
    }

    /**
     * Sets the progress message.
     *
     * <p>Same as {@link #setProgressMessage(String)}, except that it may be used with non compile
     * time constants (needed for Starlark literals).
     */
    @CanIgnoreReturnValue
    public Builder setProgressMessageFromStarlark(String progressMessage) {
      this.progressMessage = progressMessage;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setMnemonic(String mnemonic) {
      checkArgument(
          !mnemonic.isEmpty() && CharMatcher.javaLetterOrDigit().matchesAllOf(mnemonic),
          "mnemonic must only contain letters and/or digits, and have non-zero length, was: \"%s\"",
          mnemonic);
      this.mnemonic = mnemonic;
      return this;
    }

    /**
     * Sets the exec group for this action by name. This does not check that {@code execGroup} is
     * being set to a valid exec group (i.e. one that actually exists). This method expects callers
     * to do that work.
     */
    @CanIgnoreReturnValue
    public Builder setExecGroup(String execGroup) {
      this.execGroup = execGroup;
      return this;
    }
  }

  /**
   * Returns a {@link CommandLineItem} for the given executable.
   *
   * <p>In the common case that the executable's exec path is already {@linkplain
   * PathFragment#getCallablePathString callable} (contains {@link PathFragment#SEPARATOR_CHAR}),
   * returns the executable as-is to avoid creating a new object.
   *
   * <p>The only time this method can't return {@code executable} as-is is for source artifacts in
   * the root package, since their exec path contains no path separator. Note that derived artifacts
   * are necessarily callable since they are always under an output directory.
   */
  private static CommandLineItem ensureCallable(Artifact executable) {
    PathFragment execPath = executable.getExecPath();
    return execPath.getCallablePathString().equals(executable.expandToCommandLine())
        ? executable
        : execPath::getCallablePathString;
  }
}
