// 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.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.SourceManifestAction.ManifestType;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.actions.CommandLine;
import com.google.devtools.build.lib.analysis.actions.SymlinkTreeAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.RunUnder;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.syntax.Type;
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 java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * This class manages the creation of the runfiles symlink farms.
 *
 * <p>For executables that might depend on the existence of files at run-time, we create a symlink
 * farm: a directory which contains symlinks to the right locations for those runfiles.
 *
 * <p>The runfiles symlink farm serves two purposes. The first is to allow programs (and
 * programmers) to refer to files using their workspace-relative paths, regardless of whether the
 * files were source files or generated files, and regardless of which part of the package path they
 * came from. The second purpose is to ensure that all run-time dependencies are explicitly declared
 * in the BUILD files; programs may only use files which the build system knows that they depend on.
 *
 * <p>The symlink farm contains a MANIFEST file which describes its contents. The MANIFEST file
 * lists the names and contents of all of the symlinks in the symlink farm. For efficiency, Blaze's
 * dependency analysis ignores the actual symlinks and just looks at the MANIFEST file. It is an
 * invariant that the MANIFEST file should accurately represent the contents of the symlinks
 * whenever the MANIFEST file is present. build_runfile_links.py preserves this invariant (modulo
 * bugs - currently it has a bug where it may fail to preserve that invariant if it gets
 * interrupted). So the Blaze dependency analysis looks only at the MANIFEST file, rather than at
 * the individual symlinks.
 *
 * <p>We create an Artifact for the MANIFEST file and a RunfilesAction Action to create it. This
 * action does not depend on any other Artifacts.
 *
 * <p>When building an executable and running it, there are three things which must be built: the
 * executable itself, the runfiles symlink farm (represented in the action graph by the Artifact for
 * its MANIFEST), and the files pointed to by the symlinks in the symlink farm. To avoid redundancy
 * in the dependency analysis, we create a Middleman Artifact which depends on all of these. Actions
 * which will run an executable should depend on this Middleman Artifact.
 */
@Immutable
public final class RunfilesSupport {
  private static final String RUNFILES_DIR_EXT = ".runfiles";

  private final Runfiles runfiles;

  private final Artifact runfilesInputManifest;
  private final Artifact runfilesManifest;
  private final Artifact runfilesMiddleman;
  private final Artifact sourcesManifest;
  private final Artifact owningExecutable;
  private final boolean createSymlinks;
  private final CommandLine args;

  /**
   * Creates the RunfilesSupport helper with the given executable and runfiles.
   *
   * @param ruleContext the rule context to create the runfiles support for
   * @param executable the executable for whose runfiles this runfiles support is responsible, may
   *     be null
   * @param runfiles the runfiles
   */
  private RunfilesSupport(
      RuleContext ruleContext,
      Artifact executable,
      Runfiles runfiles,
      CommandLine args) {
    owningExecutable = Preconditions.checkNotNull(executable);
    boolean createManifest = ruleContext.getConfiguration().buildRunfilesManifests();
    createSymlinks = createManifest && ruleContext.getConfiguration().buildRunfiles();

    // Adding run_under target to the runfiles manifest so it would become part
    // of runfiles tree and would be executable everywhere.
    RunUnder runUnder = ruleContext.getConfiguration().getRunUnder();
    if (runUnder != null && runUnder.getLabel() != null
        && TargetUtils.isTestRule(ruleContext.getRule())) {
      TransitiveInfoCollection runUnderTarget =
          ruleContext.getPrerequisite(":run_under", Mode.DATA);
      runfiles = new Runfiles.Builder(
          ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles())
          .merge(getRunfiles(runUnderTarget, ruleContext.getWorkspaceName()))
          .merge(runfiles)
          .build();
    }
    this.runfiles = runfiles;

    Preconditions.checkState(!runfiles.isEmpty());

    Map<PathFragment, Artifact> symlinks = getRunfilesSymlinks();
    if (executable != null && !symlinks.containsValue(executable)) {
      throw new IllegalStateException("main program " + executable + " not included in runfiles");
    }

    Artifact artifactsMiddleman = createArtifactsMiddleman(ruleContext, runfiles.getAllArtifacts());
    if (createManifest) {
      runfilesInputManifest = createRunfilesInputManifestArtifact(ruleContext);
      runfilesManifest = createRunfilesAction(ruleContext, runfiles, artifactsMiddleman);
    } else {
      runfilesInputManifest = runfilesManifest =
          createManifestMiddleman(ruleContext, runfiles, artifactsMiddleman);
    }
    runfilesMiddleman = createRunfilesMiddleman(ruleContext, artifactsMiddleman, runfilesManifest);
    sourcesManifest = createSourceManifest(ruleContext, runfiles);

    this.args = args;
  }

  /**
   * Returns the executable owning this RunfilesSupport. Only use from Skylark.
   */
  public Artifact getExecutable() {
    return owningExecutable;
  }

  /**
   * Returns the exec path of the directory where the runfiles contained in this
   * RunfilesSupport are generated. When the owning rule has no executable,
   * returns null.
   */
  public PathFragment getRunfilesDirectoryExecPath() {
    PathFragment executablePath = owningExecutable.getExecPath();
    return executablePath.getParentDirectory().getChild(
        executablePath.getBaseName() + RUNFILES_DIR_EXT);
  }

  /** @return whether or not runfiles symlinks should be created */
  public boolean getCreateSymlinks() {
    return createSymlinks;
  }

  public Runfiles getRunfiles() {
    return runfiles;
  }

  /**
   * For executable programs, the .runfiles_manifest file outside of the
   * runfiles symlink farm; otherwise, returns null.
   *
   * <p>The MANIFEST file represents the contents of all of the symlinks in the
   * symlink farm. For efficiency, Blaze's dependency analysis ignores the
   * actual symlinks and just looks at the MANIFEST file. It is an invariant
   * that the MANIFEST file should accurately represent the contents of the
   * symlinks whenever the MANIFEST file is present.
   */
  public Artifact getRunfilesInputManifest() {
    return runfilesInputManifest;
  }

  private Artifact createRunfilesInputManifestArtifact(RuleContext context) {
    // The executable may be null for emptyRunfiles
    PathFragment relativePath = (owningExecutable != null)
        ? owningExecutable.getRootRelativePath()
        : context.getPackageDirectory().getRelative(context.getLabel().getName());
    String basename = relativePath.getBaseName();
    PathFragment inputManifestPath = relativePath.replaceName(basename + ".runfiles_manifest");
    return context.getDerivedArtifact(inputManifestPath,
        context.getConfiguration().getBinDirectory(context.getRule().getRepository()));
  }

  /**
   * For executable programs, returns the MANIFEST file in the runfiles
   * symlink farm, if blaze is run with --build_runfile_links; returns
   * the .runfiles_manifest file outside of the symlink farm, if blaze
   * is run with --nobuild_runfile_links.
   * <p>
   * Beware: In most cases {@link #getRunfilesInputManifest} is the more
   * appropriate function.
   */
  public Artifact getRunfilesManifest() {
    return runfilesManifest;
  }

  /**
   * For executable programs, the root directory of the runfiles symlink farm;
   * otherwise, returns null.
   */
  public Path getRunfilesDirectory() {
    return FileSystemUtils.replaceExtension(getRunfilesInputManifest().getPath(), RUNFILES_DIR_EXT);
  }

  /**
   * Returns the files pointed to by the symlinks in the runfiles symlink farm. This method is slow.
   */
  @VisibleForTesting
  public Collection<Artifact> getRunfilesSymlinkTargets() {
    return getRunfilesSymlinks().values();
  }

  /**
   * Returns the names of the symlinks in the runfiles symlink farm as a Set of PathFragments. This
   * method is slow.
   */
  // We should make this VisibleForTesting, but it is still used by TestHelper
  public Set<PathFragment> getRunfilesSymlinkNames() {
    return getRunfilesSymlinks().keySet();
  }

  /**
   * Returns the names of the symlinks in the runfiles symlink farm as a Set of PathFragments. This
   * method is slow.
   */
  @VisibleForTesting
  public Map<PathFragment, Artifact> getRunfilesSymlinks() {
    return runfiles.asMapWithoutRootSymlinks();
  }

  /**
   * Returns both runfiles artifacts and "conditional" artifacts that may be part of a Runfiles
   * PruningManifest. This means the returned set may be an overapproximation of the actual set of
   * runfiles (see {@link Runfiles.PruningManifest}).
   */
  public Iterable<Artifact> getRunfilesArtifacts() {
    return runfiles.getArtifacts();
  }

  /**
   * Returns the name of the workspace that the build is occurring in.
   */
  public PathFragment getWorkspaceName() {
    return runfiles.getSuffix();
  }

  /**
   * Returns the middleman artifact that depends on getExecutable(),
   * getRunfilesManifest(), and getRunfilesSymlinkTargets(). Anything which
   * needs to actually run the executable should depend on this.
   */
  public Artifact getRunfilesMiddleman() {
    return runfilesMiddleman;
  }

  /**
   * Returns the Sources manifest.
   */
  public Artifact getSourceManifest() {
    return sourcesManifest;
  }

  private Artifact createArtifactsMiddleman(ActionConstructionContext context,
      Iterable<Artifact> allRunfilesArtifacts) {
    return context.getAnalysisEnvironment().getMiddlemanFactory().createRunfilesMiddleman(
        context.getActionOwner(), owningExecutable, allRunfilesArtifacts,
        context.getMiddlemanDirectory(),
        "runfiles_artifacts");
  }

  private Artifact createRunfilesMiddleman(ActionConstructionContext context,
      Artifact artifactsMiddleman, Artifact outputManifest) {
    return context.getAnalysisEnvironment().getMiddlemanFactory().createRunfilesMiddleman(
        context.getActionOwner(), owningExecutable,
        ImmutableList.of(artifactsMiddleman, outputManifest),
        context.getMiddlemanDirectory(),
        "runfiles");
  }

  /**
   * Creates a runfiles action for all of the specified files, and returns the
   * output artifact (the artifact for the MANIFEST file).
   *
   * <p>The "runfiles" action creates a symlink farm that links all the runfiles
   * (which may come from different places, e.g. different package paths,
   * generated files, etc.) into a single tree, so that programs can access them
   * using the workspace-relative name.
   */
  private Artifact createRunfilesAction(ActionConstructionContext context, Runfiles runfiles,
      Artifact artifactsMiddleman) {
    // Compute the names of the runfiles directory and its MANIFEST file.
    Artifact inputManifest = getRunfilesInputManifest();
    context.getAnalysisEnvironment().registerAction(
        SourceManifestAction.forRunfiles(
            ManifestType.SOURCE_SYMLINKS, context.getActionOwner(), inputManifest, runfiles));

    if (!createSymlinks) {
      // Just return the manifest if that's all the build calls for.
      return inputManifest;
    }

    PathFragment runfilesDir = FileSystemUtils.replaceExtension(inputManifest.getRootRelativePath(),
        RUNFILES_DIR_EXT);
    PathFragment outputManifestPath = runfilesDir.getRelative("MANIFEST");

    BuildConfiguration config = context.getConfiguration();
    Artifact outputManifest = context.getDerivedArtifact(
        outputManifestPath, context.getBinDirectory());
    context
        .getAnalysisEnvironment()
        .registerAction(
            new SymlinkTreeAction(
                context.getActionOwner(),
                inputManifest,
                artifactsMiddleman,
                outputManifest,
                /*filesetTree=*/ false,
                config.getLocalShellEnvironment(),
                config.runfilesEnabled()));
    return outputManifest;
  }

  /**
   * Creates a middleman artifact which substitutes for the input and
   * output manifests when manifest files are disabled.
   */
  private Artifact createManifestMiddleman(ActionConstructionContext context, Runfiles runfiles,
      Artifact artifactsMiddleman) {
    // Deps which are otherwise omitted when we don't build the manifest.
    // These may include "pruning manifests" which are needed at execution time.
    Collection<Artifact> manifestDeps = SourceManifestAction.getDependencies(runfiles);
    if (manifestDeps.isEmpty()) {
      // Can't create a runfiles middleman from zero artifacts.
      return artifactsMiddleman;
    }
    return context.getAnalysisEnvironment().getMiddlemanFactory().createRunfilesMiddleman(
        context.getActionOwner(), owningExecutable, SourceManifestAction.getDependencies(runfiles),
        context.getMiddlemanDirectory(),
        "runfiles_manifest");
  }

  /**
   * Creates an {@link Artifact} which writes the "sources only" manifest file.
   *
   * @param context the owner for the manifest action
   * @param runfiles the runfiles
   * @return the Artifact representing the file write action.
   */
  private Artifact createSourceManifest(ActionConstructionContext context, Runfiles runfiles) {
    // Put the sources only manifest next to the MANIFEST file but call it SOURCES.
    PathFragment executablePath = owningExecutable.getRootRelativePath();
    PathFragment sourcesManifestPath = executablePath.getParentDirectory().getChild(
        executablePath.getBaseName() + ".runfiles.SOURCES");
    Artifact sourceOnlyManifest = context.getDerivedArtifact(
        sourcesManifestPath,
        context.getBinDirectory());
    context.getAnalysisEnvironment().registerAction(SourceManifestAction.forRunfiles(
        ManifestType.SOURCES_ONLY, context.getActionOwner(), sourceOnlyManifest, runfiles));
    return sourceOnlyManifest;
  }

  /**
   * Helper method that returns a collection of artifacts that are necessary for the runfiles of the
   * given target. Note that the runfile symlink tree is never built, so this may include artifacts
   * that end up not being used (see {@link Runfiles}).
   *
   * @return the Runfiles object
   */
  private static Runfiles getRunfiles(TransitiveInfoCollection target, String workspaceName) {
    RunfilesProvider runfilesProvider = target.getProvider(RunfilesProvider.class);
    if (runfilesProvider != null) {
      return runfilesProvider.getDefaultRunfiles();
    } else {
      return new Runfiles.Builder(workspaceName)
          .addTransitiveArtifacts(target.getProvider(FilesToRunProvider.class).getFilesToRun())
          .build();
    }
  }

  /** Returns the unmodifiable list of expanded and tokenized 'args' attribute values. */
  public CommandLine getArgs() {
    return args;
  }

  /**
   * Creates and returns a {@link RunfilesSupport} object for the given rule and executable. Note
   * that this method calls back into the passed in rule to obtain the runfiles.
   */
  public static RunfilesSupport withExecutable(
      RuleContext ruleContext, Runfiles runfiles, Artifact executable) {
    return new RunfilesSupport(
        ruleContext,
        executable,
        runfiles,
        computeArgs(ruleContext, CommandLine.EMPTY));
  }

  /**
   * Creates and returns a {@link RunfilesSupport} object for the given rule and executable. Note
   * that this method calls back into the passed in rule to obtain the runfiles.
   */
  public static RunfilesSupport withExecutable(
      RuleContext ruleContext, Runfiles runfiles, Artifact executable, List<String> appendingArgs) {
    return new RunfilesSupport(
        ruleContext,
        executable,
        runfiles,
        computeArgs(ruleContext, CommandLine.of(appendingArgs)));
  }

  /**
   * Creates and returns a {@link RunfilesSupport} object for the given rule, executable, runfiles
   * and args.
   */
  public static RunfilesSupport withExecutable(
      RuleContext ruleContext, Runfiles runfiles, Artifact executable, CommandLine appendingArgs) {
    return new RunfilesSupport(
        ruleContext,
        executable,
        runfiles,
        computeArgs(ruleContext, appendingArgs));
  }

  private static CommandLine computeArgs(
      RuleContext ruleContext,
      CommandLine additionalArgs) {
    if (!ruleContext.getRule().isAttrDefined("args", Type.STRING_LIST)) {
      // Some non-_binary rules create RunfilesSupport instances; it is fine to not have an args
      // attribute here.
      return additionalArgs;
    }
    return CommandLine.concat(
        ruleContext.getExpander().withDataLocations().tokenized("args"),
        additionalArgs);
  }
}
