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

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nullable;

/**
 * Main logic for experimental config-stripped execution paths:
 * https://github.com/bazelbuild/bazel/issues/6526.
 *
 * <p>The actions executors run look like: {@code tool_pkg/mytool src/source.file
 * bazel-out/x86-opt/pkg/gen.file -o bazel-out/x86-opt/pkg/myout}.
 *
 * <p>The "x86-opt" part is a path's "configuration prefix": information describing the build
 * configuration of the action creating the artifact. This example shows artifacts created with
 * {@code --cpu=x86 --compilation_mode=opt}.
 *
 * <p>Executors cache actions based on their a) command line, b) input and output paths, c) input
 * digests. Configuration prefixes harm caching because even if an action behaves exactly the same
 * for different CPU architectures, {@code <cpu>-opt} guarantees the paths will differ.
 *
 * <p>Config-stripping is an experimental feature that strips the configuration prefix from
 * qualifying actions before running them, thus improving caching. "Qualifying" actions are actions
 * known not to depend on the names of their input and output paths. Non-qualifying actions include
 * manifest generators and compilers that store debug symbol source paths.
 *
 * <p>As an experimental feature, most logic is centralized here to provide easy hooks into executor
 * and action code and avoid complicating large swaths of the code base.
 *
 * <p>Enable this feature by setting {@code --experimental_output_paths=strip}. This activates two
 * effects:
 *
 * <ol>
 *   <li>"Qualifying" actions strip config paths from their command lines. An action qualifies if
 *       its implementation logic checks {@code --experimental_output_paths=strip}, creates a {@link
 *       Spawn} with {@link Spawn#stripOutputPaths()} == true, and removes config prefixes from its
 *       command line with the help of {@link PathStripper.CommandAdjuster}. Action logic should
 *       also check {@link PathStripper#isPathStrippable}: see that method's javadoc for why.
 *   <li>A supporting executor strips paths from qualifying actions' inputs and outputs before
 *       staging for execution, with the help of {@link PathStripper.ActionStager}.
 * </ol>
 *
 * <p>So an action is responsible for declaring that it strips paths and adjusting its command line
 * accordingly. The executor is responsible for remapping action inputs and outputs to match.
 *
 * <p>A lot of this work is handled generically in {@link CustomCommandLine} and related classes.
 * Simple actions may be able to opt into this behavior with little more than setting {@link
 * com.google.devtools.build.lib.analysis.actions.SpawnAction.Builder#stripOutputPaths(boolean)}.
 * Starlark actions don't yet have API support: specific mnemonics are enabled by {@link
 * com.google.devtools.build.lib.analysis.actions.StarlarkAction.Builder#stripOutputPaths(String,
 * NestedSet, Artifact, BuildConfigurationValue)}.
 */
public final class PathStripper {
  /**
   * Support for stripping config paths from an action's inputs and outputs.
   *
   * <p>The executor should use this to correctly stage an action for execution.
   */
  public interface ActionStager {
    /**
     * Returns the exec path where the executor should stage an action input or output.
     *
     * <p>If the action should be config-stripped ({@link PathStripper}), removes "k8-fastbuild"
     * from paths like "bazel-out/k8-fastbuild/foo/bar".
     *
     * <p>Else returns the artifact's original exec path.
     */
    String getExecPathString(ActionInput artifact);

    /** Same as {@link #getExecPathString(ActionInput)} but for a {@link PathFragment}. */
    PathFragment strip(PathFragment execPath);

    /**
     * Creates a new action stager for executor implementation logic to use.
     *
     * @param spawn the action to stage. If {@link Spawn#stripOutputPaths()} is true, paths like
     *     "bazel-out/k8-fastbuild/bin/foo" are reduced to "bazel-out/bin/foo". Else they're
     *     unchanged.
     * @param outputRoot the root path where outputs are written (e.g. "bazel-out")
     */
    static ActionStager create(Spawn spawn, PathFragment outputRoot) {
      Preconditions.checkState(outputRoot.isSingleSegment());
      Preconditions.checkState(!outputRoot.getPathString().contains("\\"));
      return spawn.stripOutputPaths() ? actionStripper(outputRoot) : NOOP;
    }

    /** An {@link ActionStager} that doesn't change paths. */
    ActionStager NOOP =
        new ActionStager() {
          @Override
          public String getExecPathString(ActionInput artifact) {
            return artifact.getExecPathString();
          }

          @Override
          public PathFragment strip(PathFragment execPath) {
            return execPath;
          }
        };

    /** Instantiates an {@link ActionStager} that strips config prefixes from output paths. */
    private static ActionStager actionStripper(PathFragment outputRoot) {
      return new ActionStager() {
        @Override
        public String getExecPathString(ActionInput artifact) {
          return strip(artifact.getExecPath()).getPathString();
        }

        @Override
        public PathFragment strip(PathFragment execPath) {
          return isOutputPath(execPath, outputRoot) ? PathStripper.strip(execPath) : execPath;
        }
      };
    }
  }

  /**
   * Support for stripping config paths from an action's command line.
   *
   * <p>Action implementation logic should use this to correctly set an action's command line.
   */
  public interface CommandAdjuster {
    /**
     * Returns the exec path to refer to an input or output by.
     *
     * <p>If the action should be config-stripped ({@link PathStripper}), removes "k8-fastbuild"
     * from paths like "bazel-out/k8-fastbuild/foo/bar".
     *
     * <p>Else returns the artifact's original exec path.
     */
    String strip(DerivedArtifact artifact);

    /** Same as {@link #strip(DerivedArtifact)} but for a {@link PathFragment}. */
    PathFragment strip(PathFragment execPath);

    /**
     * We don't yet have a Starlark API for stripping command lines. Simple Starlark calls like
     * {@code args.add(arg_name, file_path} are automatically handled. But calls that involve custom
     * Starlark code require deeper API support that remains a TODO.
     *
     * <p>This method hard-codes support for specific command line entries for specific Starlark
     * actions that we know we want to strip.
     */
    List<String> stripCustomStarlarkArgs(List<String> args);

    /**
     * Creates a new command adjuster for action implementation logic to use.
     *
     * @param stripOutputPaths should this action strip config prefixes?
     * @param starlarkMnemonic this action's mnemonic if it's a Starlark action, else null
     * @param outputRoot the root path where outputs are written (e.g. "bazel-out"). Actions that
     *     don't strip outputs can set this to null.
     */
    static CommandAdjuster create(
        boolean stripOutputPaths,
        @Nullable String starlarkMnemonic,
        @Nullable PathFragment outputRoot) {
      if (stripOutputPaths) {
        Preconditions.checkNotNull(outputRoot);
        Preconditions.checkState(outputRoot.isSingleSegment());
        Preconditions.checkState(!outputRoot.getPathString().contains("\\"));
      }
      return stripOutputPaths ? commandStripper(starlarkMnemonic, outputRoot) : NOOP;
    }

    /** Instantiates a {@link CommandAdjuster} that doesn't change paths. */
    CommandAdjuster NOOP =
        new CommandAdjuster() {
          @Override
          public String strip(DerivedArtifact artifact) {
            return artifact.getExecPathString();
          }

          @Override
          public PathFragment strip(PathFragment execPath) {
            return execPath;
          }

          @Override
          public List<String> stripCustomStarlarkArgs(List<String> args) {
            return args;
          }
        };

    /** Instantiates a {@link CommandAdjuster} that strips config prefixes from output paths. */
    private static CommandAdjuster commandStripper(
        @Nullable String starlarkMnemonic, PathFragment outputRoot) {
      final StringStripper argStripper =
          starlarkMnemonic != null ? new StringStripper(outputRoot.getPathString()) : null;
      return new CommandAdjuster() {
        @Override
        public String strip(DerivedArtifact artifact) {
          return PathStripper.strip(artifact);
        }

        @Override
        public PathFragment strip(PathFragment execPath) {
          return PathStripper.isOutputPath(execPath, outputRoot)
              ? PathStripper.strip(execPath)
              : execPath;
        }

        @Override
        public List<String> stripCustomStarlarkArgs(List<String> args) {
          // Add your favorite Starlark mnemonic that needs custom arg processing here.
          if (!starlarkMnemonic.contains("Android")
              && !starlarkMnemonic.equals("MergeManifests")
              && !starlarkMnemonic.equals("StarlarkRClassGenerator")) {
            return args;
          }
          // Add your favorite arg to custom-process here. When Bazel finds one of these in the
          // argument list (an argument name), it strips output path prefixes from the following
          // argument (the argument value).
          ImmutableList<String> starlarkArgsToStrip =
              ImmutableList.of(
                  "--primaryData",
                  "--directData",
                  "--data",
                  "--resources",
                  "--mergeeManifests",
                  "--library");
          for (int i = 1; i < args.size(); i++) {
            if (starlarkArgsToStrip.contains(args.get(i - 1))) {
              args.set(i, argStripper.strip(args.get(i)));
            }
          }
          return args;
        }
      };
    }
  }

  /**
   * Utility class to strip output path configuration prefixes from arbitrary strings.
   *
   * <p>Rules that support path stripping can use this to help their implementation logic.
   */
  public static class StringStripper {
    private final Pattern pattern;
    private final String outputRoot;

    public StringStripper(String outputRoot) {
      this.outputRoot = outputRoot;
      this.pattern = stripPathsPattern(outputRoot);
    }

    public String strip(String str) {
      return pattern.matcher(str).replaceAll(outputRoot + "/");
    }
  }

  /**
   * Returns the regex to strip output paths from a string.
   *
   * <p>Supports strings with multiple output paths in arbitrary places. For example
   * "/path/to/compiler bazel-out/x86-fastbuild/foo src/my.src -Dbazel-out/arm-opt/bar".
   *
   * <p>Doesn't strip paths that would be non-existent without config prefixes. For example, these
   * are unchanged: "bazel-out/x86-fastbuild", "bazel-out;foo", "/path/to/compiler bazel-out".
   *
   * @param outputRoot root segment of output paths (e.g. "bazel-out")
   */
  private static Pattern stripPathsPattern(String outputRoot) {
    // Match "bazel-out" followed by a slash followed by any combination of word characters, "_",
    // and "-", followed by another slash. This would miss substrings like "bazel-out/k8-fastbuild".
    // But those don't represent actual outputs (all outputs would have to have names beneath that
    // path). So we're not trying to replace those.
    return Pattern.compile(outputRoot + "/[\\w_-]+/");
  }

  /**
   * Is this a strippable path?
   *
   * @param artifact artifact whose path to check
   * @param outputRoot - the output tree's execPath-relative root (e.g. "bazel-out")
   */
  private static boolean isOutputPath(ActionInput artifact, PathFragment outputRoot) {
    // We can't simply check for DerivedArtifact. Output paths can also appear, for example, in
    // ParamFileActionInput and ActionInputHelper.BasicActionInput.
    return isOutputPath(artifact.getExecPath(), outputRoot);
  }

  /** Private utility method: Is this a strippable path? */
  private static boolean isOutputPath(PathFragment pathFragment, PathFragment outputRoot) {
    return pathFragment.startsWith(outputRoot);
  }

  /**
   * Is this action safe to strip?
   *
   * <p>This is distinct from whether we <b>should</b> strip it. An action is stripped if a) the
   * action logic declares it's strippable via {@link Spawn#stripOutputPaths()} and b) it's safe to
   * do that (for example, the action doesn't have two inputs in different configurations that would
   * resolve to the same path if prefixes were removed).
   *
   * <p>This method checks b). Action logic is responsible for considering this to set a) correctly.
   */
  public static boolean isPathStrippable(
      NestedSet<? extends ActionInput> actionInputs, PathFragment outputRoot) {
    // For qualifying action types, check that no inputs or outputs would clash if paths were
    // removed, e.g. "bazel-out/k8-fastbuild/foo" and "bazel-out/host/foo".
    //
    // A more clever algorithm could remap these with custom prefixes - "bazel-out/1/foo" and
    // "bazel-out/2/foo" - if experience shows that would help.
    //
    // Another approach could keep host paths intact (since the "host" path prefix doesn't vary
    // with configurations). While this would help more action instances qualify, it also blocks
    // caching the same action in host and target configurations. This could be mitigated by
    // stripping the host prefix *only* when the entire action is in the host configuration.
    HashSet<PathFragment> rootRelativePaths = new HashSet<>();
    for (ActionInput input : actionInputs.toList()) {
      if (!isOutputPath(input, outputRoot)) {
        continue;
      }
      // For "bazel-out/k8-fastbuild/foo/bar", get "foo/bar".
      if (!rootRelativePaths.add(input.getExecPath().subFragment(2))) {
        // TODO(bazel-team): don't fail on duplicate inputs, i.e. when the same exact exec path
        // (including config prefix) is included twice.
        return false;
      }
    }
    return true;
  }

  /*
   * Private utility method: strips the configuration prefix from an output artifact's exec path.
   */
  static PathFragment strip(PathFragment execPath) {
    return execPath.subFragment(0, 1).getRelative(execPath.subFragment(2));
  }

  /**
   * Private utility method: returns an output artifact's exec path with its configuration prefix
   * stripped.
   */
  static String strip(DerivedArtifact artifact) {
    return strip(artifact.getExecPath()).getPathString();
  }

  private PathStripper() {}
}
