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

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
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.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Static utilities for managing output directory symlinks.
 */
public class OutputDirectoryLinksUtils {
  // Used in getPrettyPath() method below.
  private static final String[] LINKS = { "bin", "genfiles", "includes" };

  private static final String NO_CREATE_SYMLINKS_PREFIX = "/";

  public static ImmutableList<String> getOutputSymlinkNames(String productName,
      String symlinkPrefix) {
    ImmutableList.Builder<String> builder = ImmutableList.<String>builder();
    // TODO(b/35234395): This symlink is created for backwards compatiblity, remove it once
    // we're sure it won't cause any other issues.
    builder.add(productName + "-out");
    if (!productName.equals(symlinkPrefix)) {
      builder.add(symlinkPrefix + "out");
    }
    return builder.build();
  }

  private static String execRootSymlink(String symlinkPrefix, String workspaceName) {
    return symlinkPrefix + workspaceName;
  }

  /**
   * Attempts to create convenience symlinks in the workspaceDirectory and in execRoot to the output
   * area and to the configuration-specific output directories. Issues a warning if it fails, e.g.
   * because workspaceDirectory is readonly.
   *
   * <p>Configuration-specific output symlinks will be created or updated if and only if the set of
   * {@code targetConfigs} contains only configurations whose output directories match. Otherwise -
   * i.e., if there are multiple configurations with distinct output directories or there were no
   * targets with non-null configurations in the build - any stale symlinks left over from previous
   * invocations will be removed.
   */
  static void createOutputDirectoryLinks(
      String workspaceName,
      Path workspace,
      Path execRoot,
      Path outputPath,
      EventHandler eventHandler,
      Set<BuildConfiguration> targetConfigs,
      String symlinkPrefix,
      String productName) {
    if (NO_CREATE_SYMLINKS_PREFIX.equals(symlinkPrefix)) {
      return;
    }
    List<String> failures = new ArrayList<>();

    // Make the two non-specific links from the workspace to the output area,
    // and the configuration-specific links in both the workspace and the execution root dirs.
    // IMPORTANT: Keep in sync with removeOutputDirectoryLinks below.
    for (String outputSymlinkName : getOutputSymlinkNames(productName, symlinkPrefix)) {
      createLink(workspace, outputSymlinkName, outputPath, failures);
    }

    // Points to execroot
    createLink(workspace, execRootSymlink(
        symlinkPrefix, workspace.getBaseName()), execRoot, failures);
    RepositoryName repositoryName = RepositoryName.createFromValidStrippedName(workspaceName);

    // Set up convenience symlinks iff there's only one useful target for them to point to;
    // otherwise, remove stale symlinks from previous invocations at that path to avoid confusion
    Set<Path> binPaths =
        targetConfigs
            .stream()
            .map(targetConfig -> targetConfig.getBinDirectory(repositoryName).getPath())
            .distinct()
            .collect(toImmutableSet());
    if (binPaths.size() == 1) {
      createLink(workspace, symlinkPrefix + "bin", Iterables.getOnlyElement(binPaths), failures);
    } else {
      removeLink(workspace, symlinkPrefix + "bin", failures);
    }
    Set<Path> testLogsPaths =
        targetConfigs
            .stream()
            .map(targetConfig -> targetConfig.getTestLogsDirectory(repositoryName).getPath())
            .distinct()
            .collect(toImmutableSet());
    if (testLogsPaths.size() == 1) {
      createLink(
          workspace,
          symlinkPrefix + "testlogs",
          Iterables.getOnlyElement(testLogsPaths),
          failures);
    } else {
      removeLink(workspace, symlinkPrefix + "testlogs", failures);
    }
    Set<Path> genfilesPaths =
        targetConfigs
            .stream()
            .map(targetConfig -> targetConfig.getGenfilesDirectory(repositoryName).getPath())
            .distinct()
            .collect(toImmutableSet());
    if (genfilesPaths.size() == 1) {
      createLink(
          workspace,
          symlinkPrefix + "genfiles",
          Iterables.getOnlyElement(genfilesPaths),
          failures);
    } else {
      removeLink(workspace, symlinkPrefix + "genfiles", failures);
    }

    if (!failures.isEmpty()) {
      eventHandler.handle(Event.warn(String.format(
          "failed to create one or more convenience symlinks for prefix '%s':\n  %s",
          symlinkPrefix, Joiner.on("\n  ").join(failures))));
    }
  }

  /**
   * Returns a convenient path to the specified file, relativizing it and using output-dir symlinks
   * if possible.  Otherwise, return a path relative to the workspace directory if possible.
   * Otherwise, return the absolute path.
   *
   * <p>This method must be called after the symlinks are created at the end of a build. If called
   * before, the pretty path may be incorrect if the symlinks end up pointing somewhere new.
   */
  public static PathFragment getPrettyPath(Path file, String workspaceName,
      Path workspaceDirectory, String symlinkPrefix, String productName) {
    for (String link : LINKS) {
      PathFragment result = relativize(file, workspaceDirectory, symlinkPrefix + link);
      if (result != null) {
        return result;
      }
    }

    PathFragment result = relativize(file, workspaceDirectory,
        execRootSymlink(symlinkPrefix, workspaceName));
    if (result != null) {
      return result;
    }

    ImmutableList<String> outputSymlinkNames = getOutputSymlinkNames(productName, symlinkPrefix);
    checkArgument(!outputSymlinkNames.isEmpty());
    result = relativize(file, workspaceDirectory, outputSymlinkNames.get(0));
    if (result != null) {
      return result;
    }

    return file.asFragment();
  }

  // Helper to getPrettyPath.  Returns file, relativized w.r.t. the referent of
  // "linkname", or null if it was a not a child.
  private static PathFragment relativize(Path file, Path workspaceDirectory, String linkname) {
    PathFragment link = PathFragment.create(linkname);
    try {
      Path dir = workspaceDirectory.getRelative(link);
      PathFragment levelOneLinkTarget = dir.readSymbolicLink();
      if (levelOneLinkTarget.isAbsolute() &&
          file.startsWith(dir = file.getRelative(levelOneLinkTarget))) {
        return link.getRelative(file.relativeTo(dir));
      }
    } catch (IOException e) {
      /* ignore */
    }
    return null;
  }

  /**
   * Attempts to remove the convenience symlinks in the workspace directory.
   *
   * <p>Issues a warning if it fails, e.g. because workspaceDirectory is readonly.
   * Also cleans up any child directories created by a custom prefix.
   *
   * @param workspace the runtime's workspace
   * @param eventHandler the error eventHandler
   * @param symlinkPrefix the symlink prefix which should be removed
   * @param productName the product name
   */
  public static void removeOutputDirectoryLinks(String workspaceName, Path workspace,
      EventHandler eventHandler, String symlinkPrefix, String productName) {
    if (NO_CREATE_SYMLINKS_PREFIX.equals(symlinkPrefix)) {
      return;
    }
    List<String> failures = new ArrayList<>();

    for (String outputSymlinkName : getOutputSymlinkNames(productName, symlinkPrefix)) {
      removeLink(workspace, outputSymlinkName, failures);
    }
    removeLink(workspace, execRootSymlink(symlinkPrefix, workspaceName), failures);
    removeLink(workspace, execRootSymlink(symlinkPrefix, workspace.getBaseName()), failures);
    removeLink(workspace, symlinkPrefix + "bin", failures);
    removeLink(workspace, symlinkPrefix + "testlogs", failures);
    removeLink(workspace, symlinkPrefix + "genfiles", failures);
    FileSystemUtils.removeDirectoryAndParents(workspace, PathFragment.create(symlinkPrefix));
    if (!failures.isEmpty()) {
      eventHandler.handle(Event.warn(String.format(
          "failed to remove one or more convenience symlinks for prefix '%s':\n  %s", symlinkPrefix,
          Joiner.on("\n  ").join(failures))));
    }
  }

  /**
   * Helper to createOutputDirectoryLinks that creates a symlink from base + name to target.
   */
  private static boolean createLink(Path base, String name, Path target, List<String> failures) {
    try {
      FileSystemUtils.createDirectoryAndParents(target);
    } catch (IOException e) {
      failures.add(String.format("cannot create directory %s: %s",
          target.getPathString(), e.getMessage()));
      return false;
    }
    try {
      FileSystemUtils.ensureSymbolicLink(base.getRelative(name), target);
    } catch (IOException e) {
      failures.add(String.format("cannot create symbolic link %s -> %s:  %s",
          name, target.getPathString(), e.getMessage()));
      return false;
    }

    return true;
  }

  /**
   * Helper to removeOutputDirectoryLinks that removes one of the Blaze convenience symbolic links.
   */
  private static boolean removeLink(Path base, String name, List<String> failures) {
    Path link = base.getRelative(name);
    try {
      if (link.isSymbolicLink()) {
        ExecutionTool.logger.finest("Removing " + link);
        link.delete();
      }
      return true;
    } catch (IOException e) {
      failures.add(String.format("%s: %s", name, e.getMessage()));
      return false;
    }
  }
}
