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

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.actions.SimpleSpawn;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.UserExecException;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.shell.CommandException;
import com.google.devtools.build.lib.util.CommandBuilder;
import com.google.devtools.build.lib.util.OsUtils;
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.io.IOException;
import java.util.List;

/**
 * Helper class responsible for the symlink tree creation. Used to generate runfiles and fileset
 * symlink farms.
 */
public final class SymlinkTreeHelper {
  @VisibleForTesting
  public static final String BUILD_RUNFILES = "build-runfiles" + OsUtils.executableExtension();

  /**
   * These actions run faster overall when serialized, because most of their cost is in the ext2
   * block allocator, and there's less seeking required if their directory creations get
   * non-interleaved allocations. So we give them a huge resource cost.
   */
  public static final ResourceSet RESOURCE_SET = ResourceSet.createWithRamCpuIo(1000, 0.5, 0.75);

  private final Path inputManifest;
  private final Path symlinkTreeRoot;
  private final boolean filesetTree;

  /**
   * Creates SymlinkTreeHelper instance. Can be used independently of SymlinkTreeAction.
   *
   * @param inputManifest exec path to the input runfiles manifest
   * @param symlinkTreeRoot the root of the symlink tree to be created
   * @param filesetTree true if this is fileset symlink tree,
   *                    false if this is a runfiles symlink tree.
   */
  public SymlinkTreeHelper(Path inputManifest, Path symlinkTreeRoot, boolean filesetTree) {
    this.inputManifest = inputManifest;
    this.symlinkTreeRoot = symlinkTreeRoot;
    this.filesetTree = filesetTree;
  }

  public Path getOutputManifest() {
    return symlinkTreeRoot;
  }

  /**
   * Creates a symlink tree using a CommandBuilder. This means that the symlink tree will always be
   * present on the developer's workstation. Useful when running commands locally.
   *
   * Warning: this method REALLY executes the command on the box Bazel is running on, without any
   * kind of synchronization, locking, or anything else.
   *
   * @param config the configuration that is used for creating the symlink tree.
   * @throws CommandException
   */
  public void createSymlinksUsingCommand(
      Path execRoot, BuildConfiguration config, BinTools binTools)
          throws CommandException {
    List<String> argv = getSpawnArgumentList(execRoot, binTools.getExecPath(BUILD_RUNFILES));
    CommandBuilder builder = new CommandBuilder();
    builder.addArgs(argv);
    builder.setWorkingDir(execRoot);
    builder.build().execute();
  }

  /**
   * Creates symlink tree using appropriate method. At this time tree always created using
   * build-runfiles helper application.
   *
   * @param owner action instance that requested symlink tree creation
   * @param actionExecutionContext Services that are in the scope of the action.
   * @param enableRunfiles
   * @return a list of SpawnResults created during symlink creation, if any
   */
  public List<SpawnResult> createSymlinks(
      ActionExecutionMetadata owner,
      ActionExecutionContext actionExecutionContext,
      BinTools binTools,
      ImmutableMap<String, String> shellEnvironment,
      Artifact inputManifestArtifact,
      boolean enableRunfiles)
          throws ExecException, InterruptedException {
    Preconditions.checkState(
        actionExecutionContext.getInputPath(inputManifestArtifact).equals(inputManifest));
    if (enableRunfiles) {
      Spawn spawn =
          createSpawn(
              owner,
              actionExecutionContext.getExecRoot(),
              binTools,
              shellEnvironment,
              inputManifestArtifact);
      return actionExecutionContext
          .getSpawnActionContext(spawn)
          .exec(spawn, actionExecutionContext);
    } else {
      // Pretend we created the runfiles tree by copying the manifest
      try {
        symlinkTreeRoot.createDirectoryAndParents();
        FileSystemUtils.copyFile(inputManifest, symlinkTreeRoot.getChild("MANIFEST"));
      } catch (IOException e) {
        throw new UserExecException(e.getMessage(), e);
      }
      return ImmutableList.of();
    }
  }

  @VisibleForTesting
  Spawn createSpawn(
      ActionExecutionMetadata owner,
      Path execRoot,
      BinTools binTools,
      ImmutableMap<String, String> environment,
      ActionInput inputManifestArtifact) {
    ActionInput buildRunfiles = binTools.getActionInput(BUILD_RUNFILES);
    return new SimpleSpawn(
        owner,
        getSpawnArgumentList(execRoot, buildRunfiles.getExecPath()),
        environment,
        ImmutableMap.of(
            ExecutionRequirements.LOCAL, "",
            ExecutionRequirements.NO_CACHE, "",
            ExecutionRequirements.NO_SANDBOX, ""),
        ImmutableList.of(inputManifestArtifact, buildRunfiles),
        /*outputs=*/ ImmutableList.of(),
        RESOURCE_SET);
  }

  /**
   * Returns the complete argument list build-runfiles has to be called with.
   */
  private ImmutableList<String> getSpawnArgumentList(Path execRoot, PathFragment buildRunfiles) {
    List<String> args = Lists.newArrayList();
    args.add(buildRunfiles.getPathString());

    if (filesetTree) {
      args.add("--allow_relative");
      args.add("--use_metadata");
    }

    args.add(inputManifest.relativeTo(execRoot).getPathString());
    args.add(symlinkTreeRoot.relativeTo(execRoot).getPathString());

    return ImmutableList.copyOf(args);
  }
}
