// 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.runtime.commands;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
import com.google.devtools.build.lib.buildtool.OutputDirectoryLinksUtils;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.StarlarkOptionsParser;
import com.google.devtools.build.lib.runtime.commands.events.CleanStartingEvent;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.CleanCommand.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.shell.CommandException;
import com.google.devtools.build.lib.shell.CommandResult;
import com.google.devtools.build.lib.util.CommandBuilder;
import com.google.devtools.build.lib.util.InterruptedFailureDetails;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.ProcessUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
import java.util.logging.LogManager;

/** Implements 'blaze clean'. */
@Command(
    name = "clean",
    builds = true, // Does not, but people expect build options to be there
    allowResidue = true, // Does not, but need to allow so we can ignore Starlark options.
    writeCommandLog = false, // Do not create a command.log, otherwise we couldn't delete it.
    options = {CleanCommand.Options.class},
    help = "resource:clean.txt",
    shortDescription = "Removes output files and optionally stops the server.",
    // TODO(bazel-team): Remove this - we inherit a huge number of unused options.
    inherits = {BuildCommand.class})
public final class CleanCommand implements BlazeCommand {
  /** An interface for special options for the clean command. */
  public static class Options extends OptionsBase {
    @Option(
      name = "expunge",
      defaultValue = "false",
      documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
      effectTags = {OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS},
      help =
          "If true, clean removes the entire working tree for this %{product} instance, "
              + "which includes all %{product}-created temporary and build output files, "
              + "and stops the %{product} server if it is running."
    )
    public boolean expunge;

    @Option(
      name = "expunge_async",
      defaultValue = "null",
      expansion = {"--expunge", "--async"},
      documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
      effectTags = {OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS},
      help =
          "If specified, clean asynchronously removes the entire working tree for "
              + "this %{product} instance, which includes all %{product}-created temporary and "
              + "build output files, and stops the %{product} server if it is running. When "
              + "this command completes, it will be safe to execute new commands in the same "
              + "client, even though the deletion may continue in the background."
    )
    public Void expungeAsync;

    @Option(
      name = "async",
      defaultValue = "false",
      documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
      effectTags = {OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS},
      help =
          "If true, output cleaning is asynchronous. When this command completes, it will be safe "
              + "to execute new commands in the same client, even though the deletion may continue "
              + "in the background."
    )
    public boolean async;

    @Option(
        name = "remove_all_convenience_symlinks",
        defaultValue = "false",
        documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
        effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
        help =
            "If true, all symlinks in the workspace with  the prefix symlink_prefix will be"
                + " deleted. Without this flag, only symlinks with the predefined suffixes are"
                + " cleaned.")
    public boolean removeAllConvenienceSymlinks;
  }

  private final OS os;

  public CleanCommand() {
    this(OS.getCurrent());
  }

  @VisibleForTesting
  public CleanCommand(OS os) {
    this.os = os;
  }

  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  @Override
  public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) {
    // Assert that the only residue is starlark options and ignore them.
    Pair<ImmutableList<String>, ImmutableList<String>> starlarkOptionsAndResidue =
        StarlarkOptionsParser.removeStarlarkOptions(options.getResidue());
    ImmutableList<String> removedStarlarkOptions = starlarkOptionsAndResidue.getFirst();
    ImmutableList<String> residue = starlarkOptionsAndResidue.getSecond();
    if (!removedStarlarkOptions.isEmpty()) {
      env.getReporter()
          .handle(
              Event.warn(
                  "Blaze clean does not support starlark options. Ignoring options: "
                      + removedStarlarkOptions));
    }
    if (!residue.isEmpty()) {
      String message = "Unrecognized arguments: " + Joiner.on(' ').join(residue);
      env.getReporter().handle(Event.error(message));
      return BlazeCommandResult.failureDetail(
          createFailureDetail(message, Code.ARGUMENTS_NOT_RECOGNIZED));
    }

    env.getEventBus().post(new NoBuildEvent());
    Options cleanOptions = options.getOptions(Options.class);
    boolean async = canUseAsync(cleanOptions.async, cleanOptions.expunge, os, env.getReporter());
    env.getEventBus().post(new CleanStartingEvent(options));

    try {
      String symlinkPrefix =
          options
              .getOptions(BuildRequestOptions.class)
              .getSymlinkPrefix(env.getRuntime().getProductName());
      return actuallyClean(
          env,
          env.getOutputBase(),
          cleanOptions.expunge,
          async,
          symlinkPrefix,
          cleanOptions.removeAllConvenienceSymlinks);
    } catch (CleanException e) {
      env.getReporter().handle(Event.error(e.getMessage()));
      return BlazeCommandResult.failureDetail(e.getFailureDetail());
    } catch (InterruptedException e) {
      String message = "clean interrupted";
      env.getReporter().handle(Event.error(message));
      return BlazeCommandResult.detailedExitCode(
          InterruptedFailureDetails.detailedExitCode(message));
    }
  }

  @VisibleForTesting
  public static boolean canUseAsync(boolean async, boolean expunge, OS os, Reporter reporter) {
    // TODO(dmarting): Deactivate expunge_async on non-Linux platform until we completely fix it
    // for non-Linux platforms (https://github.com/bazelbuild/bazel/issues/1906).
    // MacOS and FreeBSD support setsid(2) but don't have /usr/bin/setsid, so if we wanted to
    // support --expunge_async on these platforms, we'd have to write a wrapper that calls setsid(2)
    // and exec(2).
    boolean asyncSupport = os == OS.LINUX;
    if (async && !asyncSupport) {
      String fallbackName = expunge ? "--expunge" : "synchronous clean";
      reporter.handle(
          Event.info(
              null /*location*/,
              "--async cannot be used on non-Linux platforms, falling back to " + fallbackName));
      async = false;
    }

    String cleanBanner =
        (async || !asyncSupport)
            ? "Starting clean."
            : "Starting clean (this may take a while). "
                + "Consider using --async if the clean takes more than several minutes.";
    reporter.handle(Event.info(/* location= */ null, cleanBanner));

    return async;
  }

  private static void asyncClean(CommandEnvironment env, Path path, String pathItemName)
      throws IOException, CommandException, InterruptedException {
    String tempBaseName =
        path.getBaseName() + "_tmp_" + ProcessUtils.getpid() + "_" + UUID.randomUUID();

    // Keeping tempOutputBase in the same directory ensures it remains in the
    // same file system, and therefore the mv will be atomic and fast.
    Path tempPath = path.getParentDirectory().getChild(tempBaseName);
    path.renameTo(tempPath);
    env.getReporter()
        .handle(Event.info(null, pathItemName + " moved to " + tempPath + " for deletion"));

    String command =
        String.format(
            "/usr/bin/find %s -type d -not -perm -u=rwx -exec /bin/chmod -f u=rwx {} +; /bin/rm"
                + " -rf %s",
            tempBaseName, tempBaseName);
    logger.atInfo().log("Executing daemonic shell command %s", command);

    // Daemonize the shell to ensure that the shell exits even while the "rm
    // -rf" command continues.
    CommandResult result =
        new CommandBuilder()
            .addArg(
                env.getBlazeWorkspace().getBinTools().getEmbeddedPath("daemonize").getPathString())
            .addArgs("-l", "/dev/null")
            .addArgs("-p", "/dev/null")
            .addArg("--")
            .addArgs("/bin/sh", "/bin/sh", "-c", command)
            .setWorkingDir(tempPath.getParentDirectory())
            .build()
            .execute();
    logger.atInfo().log("Shell command status: %s", result.getTerminationStatus());
  }

  private BlazeCommandResult actuallyClean(
      CommandEnvironment env,
      Path outputBase,
      boolean expunge,
      boolean async,
      String symlinkPrefix,
      boolean removeAllConvenienceSymlinks)
      throws CleanException, InterruptedException {
    BlazeRuntime runtime = env.getRuntime();
    if (env.getOutputService() != null) {
      try {
        env.getOutputService().clean();
      } catch (ExecException e) {
        throw new CleanException(Code.OUTPUT_SERVICE_CLEAN_FAILURE, e);
      }
    }
    try {
      env.getBlazeWorkspace().clearCaches();
    } catch (IOException e) {
      throw new CleanException(Code.ACTION_CACHE_CLEAN_FAILURE, e);
    }
    if (expunge && !async) {
      logger.atInfo().log("Expunging...");
      runtime.prepareForAbruptShutdown();
      // Close java.log.
      LogManager.getLogManager().reset();
      // Close the default stdout/stderr.
      try {
        if (FileDescriptor.out.valid()) {
          new FileOutputStream(FileDescriptor.out).close();
        }
        if (FileDescriptor.err.valid()) {
          new FileOutputStream(FileDescriptor.err).close();
        }
      } catch (IOException e) {
        throw new CleanException(Code.OUT_ERR_CLOSE_FAILURE, e);
      }
      // Close the redirected stdout/stderr.
      System.out.close();
      System.err.close();
      // Delete the big subdirectories with the important content first--this
      // will take the most time. Then quickly delete the little locks, logs
      // and links right before we exit. Once the lock file is gone there will
      // be a small possibility of a server race if a client is waiting, but
      // all significant files will be gone by then.
      try {
        outputBase.deleteTreesBelow();
        outputBase.deleteTree();
      } catch (IOException e) {
        throw new CleanException(Code.OUTPUT_BASE_DELETE_FAILURE, e);
      }
    } else if (expunge) {
      logger.atInfo().log("Expunging asynchronously...");
      runtime.prepareForAbruptShutdown();
      try {
        asyncClean(env, outputBase, "Output base");
      } catch (IOException e) {
        throw new CleanException(Code.OUTPUT_BASE_TEMP_MOVE_FAILURE, e);
      } catch (CommandException e) {
        throw new CleanException(Code.ASYNC_OUTPUT_BASE_DELETE_FAILURE, e);
      }
    } else {
      logger.atInfo().log("Output cleaning...");
      env.getBlazeWorkspace().resetEvaluator();
      Path execroot = outputBase.getRelative("execroot");
      if (execroot.exists()) {
        logger.atFinest().log("Cleaning %s%s", execroot, async ? " asynchronously..." : "");
        if (async) {
          try {
            asyncClean(env, execroot, "Output tree");
          } catch (IOException e) {
            throw new CleanException(Code.EXECROOT_TEMP_MOVE_FAILURE, e);
          } catch (CommandException e) {
            throw new CleanException(Code.ASYNC_EXECROOT_DELETE_FAILURE, e);
          }
        } else {
          try {
            execroot.deleteTreesBelow();
          } catch (IOException e) {
            throw new CleanException(Code.EXECROOT_DELETE_FAILURE, e);
          }
        }
      }
    }
    // remove convenience links
    OutputDirectoryLinksUtils.removeOutputDirectoryLinks(
        runtime.getRuleClassProvider().getSymlinkDefinitions(),
        env.getWorkspace(),
        env.getOutputBase(),
        env.getReporter(),
        symlinkPrefix,
        env.getRuntime().getProductName(),
        removeAllConvenienceSymlinks);

    // shutdown on expunge cleans
    if (expunge) {
      return BlazeCommandResult.shutdownOnSuccess();
    }
    System.gc();
    return BlazeCommandResult.success();
  }

  private static class CleanException extends Exception {
    private final FailureDetails.CleanCommand.Code detailedCode;

    private CleanException(FailureDetails.CleanCommand.Code detailedCode, Exception e) {
      super(Strings.nullToEmpty(e.getMessage()), e);
      this.detailedCode = detailedCode;
    }

    private FailureDetail getFailureDetail() {
      return createFailureDetail(getMessage(), detailedCode);
    }
  }

  private static FailureDetail createFailureDetail(String message, Code detailedCode) {
    return FailureDetail.newBuilder()
        .setMessage(message)
        .setCleanCommand(FailureDetails.CleanCommand.newBuilder().setCode(detailedCode))
        .build();
  }
}
