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

import com.google.common.annotations.VisibleForTesting;
import com.google.common.hash.HashCode;
import com.google.devtools.build.lib.actions.Root;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.util.StringCanonicalizer;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;

/**
 * Encapsulates the directories related to a workspace.
 *
 * <p>The <code>workspace</code> is the top-level directory in the user's client (possibly
 * read-only). The <code>execRoot</code> is the working directory for all spawned tools, which is
 * generally below the <code>outputBase</code>.
 *
 * <p>Care must be taken to avoid multiple Bazel instances trying to write to the same output
 * directory. At this time, this is enforced by requiring a 1:1 correspondence between a running
 * Bazel instance and an output base directory, though this requirement may be softened in the
 * future.
 *
 * <p>If the user does not qualify an output base directory, the startup code will derive it
 * deterministically from the workspace. Note also that while the Bazel server process runs with the
 * workspace directory as its working directory, the client process may have a different working
 * directory, typically a subdirectory.
 *
 * <p>Do not put shortcuts to specific files here!
 */
@Immutable
public final class BlazeDirectories {

  // Include directory name, relative to execRoot/blaze-out/configuration.
  public static final String RELATIVE_INCLUDE_DIR = StringCanonicalizer.intern("include");
  @VisibleForTesting
  static final String DEFAULT_EXEC_ROOT = "default-exec-root";

  private final ServerDirectories serverDirectories;
  /** Workspace root and server CWD. */
  private final Path workspace;
  /** The root of all build actions. */
  private final Path execRoot;

  // These two are kept to avoid creating new objects every time they are accessed. This showed up
  // in a profiler.
  private final Path outputPath;
  private final Path localOutputPath;
  private final String productName;

  public BlazeDirectories(
      ServerDirectories serverDirectories,
      Path workspace,
      boolean deepExecRoot,
      String productName) {
    this.serverDirectories = serverDirectories;
    this.workspace = workspace;
    this.productName = productName;
    Path outputBase = serverDirectories.getOutputBase();
    Path execRootBase = deepExecRoot ? outputBase.getChild("execroot") : outputBase;
    boolean useDefaultExecRootName = this.workspace == null || this.workspace.isRootDirectory();
    if (useDefaultExecRootName) {
      // TODO(bazel-team): if workspace is null execRoot should be null, but at the moment there is
      // a lot of code that depends on it being non-null.
      this.execRoot = execRootBase.getChild(DEFAULT_EXEC_ROOT);
    } else {
      this.execRoot = execRootBase.getChild(workspace.getBaseName());
    }
    String relativeOutputPath = getRelativeOutputPath(productName);
    this.outputPath = execRoot.getRelative(getRelativeOutputPath());
    this.localOutputPath = outputBase.getRelative(relativeOutputPath);
  }

  @VisibleForTesting
  public BlazeDirectories(ServerDirectories serverDirectories, Path workspace, String productName) {
    this(serverDirectories, workspace, false, productName);
  }

  @VisibleForTesting
  public BlazeDirectories(Path installBase, Path outputBase, Path workspace, String productName) {
    this(new ServerDirectories(installBase, outputBase), workspace, false, productName);
  }

  /**
   * Returns the Filesystem that all of our directories belong to. Handy for
   * resolving absolute paths.
   */
  public FileSystem getFileSystem() {
    return serverDirectories.getFileSystem();
  }

  public ServerDirectories getServerDirectories() {
    return serverDirectories;
  }

  /**
   * Returns the base of the output tree, which hosts all build and scratch
   * output for a user and workspace.
   */
  public Path getInstallBase() {
    return serverDirectories.getInstallBase();
  }

  /**
   * Returns the workspace directory, which is also the working dir of the server.
   */
  public Path getWorkspace() {
    return workspace;
  }

  /**
   * Returns if the workspace directory is a valid workspace.
   */
  public boolean inWorkspace() {
    return this.workspace != null;
  }

  /**
   * Returns the base of the output tree, which hosts all build and scratch
   * output for a user and workspace.
   */
  public Path getOutputBase() {
    return serverDirectories.getOutputBase();
  }

  /**
   * Returns the execution root for the main package. This is created before the workspace file
   * has been read, so it has an incorrect path.  Use {@link #getExecRoot(String)} instead.
   */
  @Deprecated
  public Path getExecRoot() {
    return execRoot;
  }

  /**
   * Returns the execution root for a particular repository. This is the directory underneath which
   * Blaze builds the source symlink forest, to represent the merged view of different workspaces
   * specified with --package_path.
   */
  public Path getExecRoot(String workspaceName) {
    return execRoot.getParentDirectory().getRelative(workspaceName);
  }

  /**
   * Returns the output path for the main repository using the workspace's directory name. Use
   * {@link #getOutputPath(String)}, instead.
   */
  @Deprecated
  public Path getOutputPath() {
    return outputPath;
  }

  /**
   * Returns the output path used by this Blaze instance.
   */
  public Path getOutputPath(String workspaceName) {
    return getExecRoot(workspaceName).getRelative(getRelativeOutputPath());
  }

  /**
   * Returns the local output path used by this Blaze instance.
   */
  public Path getLocalOutputPath() {
    return localOutputPath;
  }

  /**
   * Returns the directory where the stdout/stderr for actions can be stored
   * temporarily for a build. If the directory already exists, the directory
   * is cleaned.
   */
  public Path getActionConsoleOutputDirectory() {
    return getOutputBase().getRelative("action_outs");
  }

  /**
   * Returns the installed embedded binaries directory, under the shared
   * installBase location.
   */
  public Path getEmbeddedBinariesRoot() {
    return serverDirectories.getEmbeddedBinariesRoot();
  }

  /**
   * Returns the configuration-independent root where the build-data should be placed, given the
   * {@link BlazeDirectories} of this server instance. Nothing else should be placed here.
   */
  public Root getBuildDataDirectory(String workspaceName) {
    return Root
        .asDerivedRoot(getExecRoot(workspaceName), getOutputPath(workspaceName), true);
  }

 /**
  * Returns the MD5 content hash of the blaze binary (includes deploy JAR, embedded binaries, and
  * anything else that ends up in the install_base).
  */
  public HashCode getInstallMD5() {
    return serverDirectories.getInstallMD5();
  }

  public String getRelativeOutputPath() {
    return BlazeDirectories.getRelativeOutputPath(productName);
  }

  /**
   * Returns the output directory name, relative to the execRoot.
   * TODO(bazel-team): (2011) make this private?
   */
  public static String getRelativeOutputPath(String productName) {
    return StringCanonicalizer.intern(productName + "-out");
  }
}
