// 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.config;

import static com.google.common.base.Predicates.not;
import static java.util.stream.Collectors.joining;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSortedMap;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.PlatformOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration.Code;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.PathFragment.InvalidBaseNameException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Logic for figuring out what base directories to place outputs generated from a given
 * configuration.
 *
 * <p>In other words, when your output ends up in <code>blaze-out/x86-fastbuild/...</code>, this
 * class is why.
 */
public class OutputDirectories {
  /**
   * Directories in the output tree.
   *
   * <p>The computation of the output directory should be a non-injective mapping from
   * BuildConfiguration instances to strings. The result should identify the aspects of the
   * configuration that should be reflected in the output file names. Furthermore the returned
   * string must not contain shell metacharacters.
   *
   * <p>For configuration settings which are NOT part of the output directory name, rebuilding with
   * a different value of such a setting will build in the same output directory. This means that
   * any actions whose keys (see Action.getKey()) have changed will be rerun. That may result in a
   * lot of recompilation.
   *
   * <p>For configuration settings which ARE part of the output directory name, rebuilding with a
   * different value of such a setting will rebuild in a different output directory; this will
   * result in higher disk usage and more work the <i>first</i> time you rebuild with a different
   * setting, but will result in less work if you regularly switch back and forth between different
   * settings.
   *
   * <p>With one important exception, it's sound to choose any subset of the config's components for
   * this string, it just alters the dimensionality of the cache. In other words, it's a trade-off
   * on the "injectiveness" scale: at one extreme (output directory name contains all data in the
   * config, and is thus injective) you get extremely precise caching (no competition for the same
   * output-file locations) but you have to rebuild for even the slightest change in configuration.
   * At the other extreme (the output (directory name is a constant) you have very high competition
   * for output-file locations, but if a slight change in configuration doesn't affect a particular
   * build step, you're guaranteed not to have to rebuild it. The important exception has to do with
   * multiple configurations: every configuration in the build must have a different output
   * directory name so that their artifacts do not conflict.
   *
   * <p>The host configuration is special-cased: in order to guarantee that its output directory is
   * always separate from that of the target configuration, we simply pin it to "host". We do this
   * so that the build works even if the two configurations are too close (which is common) and so
   * that the path of artifacts in the host configuration is a bit more readable.
   */
  public enum OutputDirectory {
    BIN("bin"),
    GENFILES("genfiles"),
    MIDDLEMAN(true),
    TESTLOGS("testlogs"),
    COVERAGE("coverage-metadata"),
    INCLUDE(BlazeDirectories.RELATIVE_INCLUDE_DIR),
    OUTPUT(false);

    private final String nameFragment;
    private final boolean middleman;

    /**
     * This constructor is for roots without suffixes, e.g.,
     * [[execroot/repo]/bazel-out/local-fastbuild].
     *
     * @param isMiddleman whether the root should be a middleman root or a "normal" derived root.
     */
    OutputDirectory(boolean isMiddleman) {
      this.nameFragment = isMiddleman ? "internal" : "";
      this.middleman = isMiddleman;
    }

    OutputDirectory(String name) {
      this.nameFragment = name;
      // Must be a legal basename for root: no segments allowed.
      FileSystemUtils.checkBaseName(nameFragment);
      this.middleman = false;
    }

    public ArtifactRoot getRoot(
        String outputDirName, BlazeDirectories directories, RepositoryName mainRepositoryName) {
      // e.g., execroot/repo1
      Path execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
      // e.g., [[execroot/repo1]/bazel-out/config/bin]
      return ArtifactRoot.asDerivedRoot(
          execRoot,
          middleman ? RootType.Middleman : RootType.Output,
          directories.getRelativeOutputPath(),
          outputDirName,
          nameFragment);
    }
  }

  private final BlazeDirectories directories;
  private final String mnemonic;
  private final String outputDirName;

  private final ArtifactRoot outputDirectory;
  private final ArtifactRoot binDirectory;
  private final ArtifactRoot includeDirectory;
  private final ArtifactRoot genfilesDirectory;
  private final ArtifactRoot coverageDirectory;
  private final ArtifactRoot testlogsDirectory;
  private final ArtifactRoot middlemanDirectory;

  private final boolean mergeGenfilesDirectory;

  private final boolean siblingRepositoryLayout;

  private final Path execRoot;

  OutputDirectories(
      BlazeDirectories directories,
      CoreOptions options,
      @Nullable PlatformOptions platformOptions,
      ImmutableSortedMap<Class<? extends Fragment>, Fragment> fragments,
      RepositoryName mainRepositoryName,
      boolean siblingRepositoryLayout,
      String transitionDirectoryNameFragment)
      throws InvalidMnemonicException {
    this.directories = directories;
    this.mnemonic =
        buildMnemonic(options, platformOptions, fragments, transitionDirectoryNameFragment);
    this.outputDirName = options.isHost ? "host" : mnemonic;

    this.outputDirectory =
        OutputDirectory.OUTPUT.getRoot(outputDirName, directories, mainRepositoryName);
    this.binDirectory = OutputDirectory.BIN.getRoot(outputDirName, directories, mainRepositoryName);
    this.includeDirectory =
        OutputDirectory.INCLUDE.getRoot(outputDirName, directories, mainRepositoryName);
    this.genfilesDirectory =
        OutputDirectory.GENFILES.getRoot(outputDirName, directories, mainRepositoryName);
    this.coverageDirectory =
        OutputDirectory.COVERAGE.getRoot(outputDirName, directories, mainRepositoryName);
    this.testlogsDirectory =
        OutputDirectory.TESTLOGS.getRoot(outputDirName, directories, mainRepositoryName);
    this.middlemanDirectory =
        OutputDirectory.MIDDLEMAN.getRoot(outputDirName, directories, mainRepositoryName);

    this.mergeGenfilesDirectory = options.mergeGenfilesDirectory;
    this.siblingRepositoryLayout = siblingRepositoryLayout;
    this.execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
  }

  private static void addMnemonicPart(
      List<String> nameParts, String part, String errorTemplate, Object... spec)
      throws InvalidMnemonicException {
    if (Strings.isNullOrEmpty(part)) {
      return;
    }

    validateMnemonicPart(part, errorTemplate, spec);

    nameParts.add(part);
  }

  /**
   * Validate that part is valid for use in the mnemonic, emitting an error message based on the
   * template if not.
   *
   * <p>The error template is expanded with the part itself as the first argument, and any remaining
   * elements of errorArgs following.
   */
  private static void validateMnemonicPart(String part, String errorTemplate, Object... errorArgs)
      throws InvalidMnemonicException {
    try {
      PathFragment.checkSeparators(part);
    } catch (InvalidBaseNameException e) {
      Object[] args = new Object[errorArgs.length + 1];
      args[0] = part;
      System.arraycopy(errorArgs, 0, args, 1, errorArgs.length);
      String message = String.format(errorTemplate, args);
      throw new InvalidMnemonicException(message, e);
    }
  }

  private static String buildMnemonic(
      CoreOptions options,
      @Nullable PlatformOptions platformOptions,
      ImmutableSortedMap<Class<? extends Fragment>, Fragment> fragments,
      String transitionDirectoryNameFragment)
      throws InvalidMnemonicException {
    // See explanation at declaration for outputRoots.
    List<String> nameParts = new ArrayList<>();

    // Add the fragment-specific sections.
    for (Map.Entry<Class<? extends Fragment>, Fragment> entry : fragments.entrySet()) {
      String outputDirectoryName = entry.getValue().getOutputDirectoryName();
      addMnemonicPart(
          nameParts,
          outputDirectoryName,
          "Output directory name '%s' specified by %s",
          entry.getKey().getSimpleName());
    }

    // Add the compilation mode.
    addMnemonicPart(nameParts, options.compilationMode.toString(), "Compilation mode '%s'");

    // Add the platform suffix, if any.
    addMnemonicPart(nameParts, options.platformSuffix, "Platform suffix '%s'");

    // Add the transition suffix.
    addMnemonicPart(
        nameParts, transitionDirectoryNameFragment, "Transition directory name fragment '%s'");

    // Join all the parts.
    String mnemonic = nameParts.stream().filter(not(Strings::isNullOrEmpty)).collect(joining("-"));

    // Replace the CPU idenfitier.
    String cpuIdentifier = buildCpuIdentifier(options, platformOptions);
    validateMnemonicPart(cpuIdentifier, "CPU name '%s'");
    mnemonic = mnemonic.replace("{CPU}", cpuIdentifier);

    return mnemonic;
  }

  private static String buildCpuIdentifier(
      CoreOptions options, @Nullable PlatformOptions platformOptions) {
    if (options.platformInOutputDir && platformOptions != null) {
      Label targetPlatform = platformOptions.computeTargetPlatform();
      // Only use non-default platforms.
      if (!PlatformOptions.platformIsDefault(targetPlatform)) {
        return targetPlatform.getName();
      }
    }

    // Fall back to using the CPU.
    return options.cpu;
  }

  private ArtifactRoot buildDerivedRoot(
      String nameFragment, RepositoryName repository, boolean isMiddleman) {
    // e.g., execroot/mainRepoName/bazel-out/[repoName/]config/bin
    // TODO(jungjw): Ideally, we would like to do execroot_base/repoName/bazel-out/config/bin
    // instead. However, it requires individually symlinking the top-level elements of external
    // repositories, which is blocked by a Windows symlink issue #8704.
    RootType rootType;
    if (repository.isMain() || repository.isDefault()) {
      rootType = isMiddleman ? RootType.SiblingMainMiddleman : RootType.SiblingMainOutput;
    } else {
      rootType = isMiddleman ? RootType.SiblingExternalMiddleman : RootType.SiblingExternalOutput;
    }
    return ArtifactRoot.asDerivedRoot(
        execRoot,
        rootType,
        directories.getRelativeOutputPath(),
        repository.strippedName(),
        outputDirName,
        nameFragment);
  }

  /** Returns the output directory for this build configuration. */
  ArtifactRoot getOutputDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout ? buildDerivedRoot("", repositoryName, false) : outputDirectory;
  }

  /** Returns the bin directory for this build configuration. */
  ArtifactRoot getBinDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout ? buildDerivedRoot("bin", repositoryName, false) : binDirectory;
  }

  /** Returns the include directory for this build configuration. */
  ArtifactRoot getIncludeDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot(BlazeDirectories.RELATIVE_INCLUDE_DIR, repositoryName, false)
        : includeDirectory;
  }

  /** Returns the genfiles directory for this build configuration. */
  ArtifactRoot getGenfilesDirectory(RepositoryName repositoryName) {
    return mergeGenfilesDirectory
        ? getBinDirectory(repositoryName)
        : siblingRepositoryLayout
            ? buildDerivedRoot("genfiles", repositoryName, false)
            : genfilesDirectory;
  }

  /**
   * Returns the directory where coverage-related artifacts and metadata files should be stored.
   * This includes for example uninstrumented class files needed for Jacoco's coverage reporting
   * tools.
   */
  ArtifactRoot getCoverageMetadataDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot("coverage-metadata", repositoryName, false)
        : coverageDirectory;
  }

  /** Returns the testlogs directory for this build configuration. */
  ArtifactRoot getTestLogsDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot("testlogs", repositoryName, false)
        : testlogsDirectory;
  }

  /** Returns a relative path to the genfiles directory at execution time. */
  PathFragment getGenfilesFragment(RepositoryName repositoryName) {
    return getGenfilesDirectory(repositoryName).getExecPath();
  }

  /**
   * Returns the path separator for the host platform. This is basically the same as {@link
   * java.io.File#pathSeparator}, except that that returns the value for this JVM, which may or may
   * not match the host platform. You should only use this when invoking tools that are known to use
   * the native path separator, i.e., the path separator for the machine that they run on.
   */
  String getHostPathSeparator() {
    // TODO(bazel-team): Maybe do this in the constructor instead? This isn't serialization-safe.
    return OS.getCurrent() == OS.WINDOWS ? ";" : ":";
  }

  /** Returns the internal directory (used for middlemen) for this build configuration. */
  ArtifactRoot getMiddlemanDirectory(RepositoryName repositoryName) {
    return siblingRepositoryLayout
        ? buildDerivedRoot("internal", repositoryName, true)
        : middlemanDirectory;
  }

  String getMnemonic() {
    return mnemonic;
  }

  boolean mergeGenfilesDirectory() {
    return mergeGenfilesDirectory;
  }

  BlazeDirectories getDirectories() {
    return directories;
  }

  /** Indicates a failure to construct the mnemonic for an output directory. */
  public static class InvalidMnemonicException extends InvalidConfigurationException {
    InvalidMnemonicException(String message, InvalidBaseNameException e) {
      super(
          message + " is invalid as part of a path: " + e.getMessage(),
          Code.INVALID_OUTPUT_DIRECTORY_MNEMONIC);
    }
  }
}

