/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */

#include "cmInstallScriptHandler.h"

#include <algorithm>
#include <cstddef>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <cm/memory>

#include <cm3p/json/value.h>
#include <cm3p/uv.h>

#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"

#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmInstrumentation.h"
#include "cmInstrumentationInterrupt.h"
#include "cmJSONState.h"
#include "cmProcessOutput.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUVHandlePtr.h"
#include "cmUVProcessChain.h"
#include "cmUVStream.h"

using InstallScript = cmInstallScriptHandler::InstallScript;
using InstallScriptRunner = cmInstallScriptHandler::InstallScriptRunner;

cmInstallScriptHandler::cmInstallScriptHandler(
  std::string binaryDir, std::vector<std::string> components,
  std::string installConfig, std::vector<std::string>& args)
  : Components(std::move(components))
  , BinaryDir(std::move(binaryDir))
{
  if (this->Components.empty()) {
    this->Components.emplace_back(std::string{});
  }

  std::string const& file =
    cmStrCat(this->BinaryDir, "/CMakeFiles/InstallScripts.json");
  this->Parallel = false;

  auto addScript = [this, &args](std::string script, std::string component,
                                 std::string config) -> void {
    this->Scripts.push_back({ script, config, args });
    if (!component.empty()) {
      this->Scripts.back().command.insert(
        this->Scripts.back().command.end() - 1,
        cmStrCat("-DCMAKE_INSTALL_COMPONENT=", component));
    }
    if (!config.empty()) {
      this->Scripts.back().command.insert(
        this->Scripts.back().command.end() - 1,
        cmStrCat("-DCMAKE_INSTALL_CONFIG_NAME=", config));
    }
    this->Scripts.back().command.emplace_back(script);
    this->Directories.push_back(cmSystemTools::GetFilenamePath(script));
  };

  // Trust the parallel install index unless the cache marker is newer.  Both
  // files are written back-to-back while generating this build tree, so any
  // ordering between them lives in a sub-second window that some filesystems
  // (e.g. NFS on AIX) do not resolve by write time.  Compare at whole-second
  // resolution: a genuinely stale index left by an older CMake reconfigure is
  // always at least a configure run (seconds) older, while the sub-second
  // jitter of a single generate step is ignored.
  bool indexIsFresh = false;
  if (cmSystemTools::FileExists(file)) {
    long int const cacheTime = cmSystemTools::ModifiedTime(
      cmStrCat(this->BinaryDir, "/CMakeFiles/cmake.check_cache"));
    indexIsFresh = cacheTime <= cmSystemTools::ModifiedTime(file);
  }
  if (indexIsFresh) {
    Json::Value value;
    cmJSONState state(file, &value);
    this->Parallel = value["Parallel"].asBool();
    if (this->Parallel) {
      args.insert(args.end() - 1, "-DCMAKE_INSTALL_LOCAL_ONLY=1");
    }
    if (installConfig.empty() && value.isMember("Configs")) {
      for (auto const& config : value["Configs"]) {
        this->Configs.push_back(config.asCString());
      }
    } else {
      this->Configs.push_back(installConfig);
    }
    for (auto const& script : value["InstallScripts"]) {
      for (auto const& component : Components) {
        for (auto const& config : Configs) {
          addScript(script.asCString(), component, config);
        }
      }
      if (!this->Parallel) {
        break;
      }
    }
  } else {
    for (auto const& component : Components) {
      addScript(cmStrCat(this->BinaryDir, "/cmake_install.cmake"), component,
                installConfig);
    }
  }
}

bool cmInstallScriptHandler::IsParallel()
{
  return this->Parallel;
}

std::vector<InstallScript> cmInstallScriptHandler::GetScripts() const
{
  return this->Scripts;
}

int cmInstallScriptHandler::Install(unsigned int j,
                                    cmInstrumentation& instrumentation)
{
  cm::uv_loop_ptr loop;
  loop.init();
  std::vector<InstallScriptRunner> runners;
  runners.reserve(this->Scripts.size());

  std::vector<std::string> instrumentArg;
  if (instrumentation.HasQuery()) {
    instrumentArg = { cmSystemTools::GetCTestCommand(),
                      "--instrument",
                      "--command-type",
                      "install",
                      "--build-dir",
                      this->BinaryDir,
                      "--config",
                      "",
                      "--" };
  }

  for (auto& script : this->Scripts) {
    if (!instrumentArg.empty()) {
      instrumentArg[7] = script.config; // --config <script.config>
    }
    script.command.insert(script.command.begin(), instrumentArg.begin(),
                          instrumentArg.end());
    runners.emplace_back(script);
  }
  std::size_t working = 0;
  std::size_t installed = 0;
  std::size_t i = 0;

  std::function<void()> queueScripts;
  queueScripts = [&runners, &working, &installed, &i, &loop, j,
                  &queueScripts]() {
    if (cmInstrumentationInterrupt::PendingInterruptSignal() != 0) {
      // Interrupted (e.g. Ctrl+C): launch no further scripts.  In-flight
      // children share the process group, receive the signal, and exit on
      // their own, draining the event loop; queueScripts is the single
      // re-entry point for launching, so guarding it here stops all remaining
      // work without killing anything.
      return;
    }
    for (auto queue = std::min(j - working, runners.size() - i); queue > 0;
         --queue) {
      ++working;
      bool started = runners[i].start(
        loop, [&runners, &working, &installed, i, &queueScripts]() {
          runners[i].printResult(++installed, runners.size());
          --working;
          queueScripts();
        });
      if (!started) {
        // The child could not be spawned.  Release its scheduling slot so the
        // remaining scripts still run; it is counted as a failure after the
        // event loop completes.
        --working;
      }
      ++i;
    }
  };
  queueScripts();
  uv_run(loop, UV_RUN_DEFAULT);

  // Aggregate child results.  When an interrupt stopped queueScripts, the
  // runners beyond the dispatched prefix [0, i) were never started (they have
  // a null process handle); those are "not run", not "failed", so exclude
  // them.  With no interrupt every runner was dispatched and this inspects
  // them all, matching the non-interrupt behavior exactly.
  std::size_t const inspect =
    cmInstrumentationInterrupt::PendingInterruptSignal() != 0 ? i
                                                              : runners.size();
  int result = 0;
  for (std::size_t k = 0; k < inspect; ++k) {
    if (runners[k].Failed()) {
      runners[k].printFailure();
      result = 1;
    }
  }

  // Write the install manifest only when every script succeeded.  A failed
  // install must not leave behind a manifest that looks complete.
  if (result == 0) {
    std::string installManifest;
    for (auto const& component : this->Components) {
      if (component.empty()) {
        installManifest = "install_manifest.txt";
      } else {
        cmsys::RegularExpression regEntry;
        if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") &&
            regEntry.find(component)) {
          installManifest = cmStrCat("install_manifest_", component, ".txt");
        } else {
          cmCryptoHash md5(cmCryptoHash::AlgoMD5);
          md5.Initialize();
          installManifest =
            cmStrCat("install_manifest_", md5.HashString(component), ".txt");
        }
      }
      cmGeneratedFileStream fout(
        cmStrCat(this->BinaryDir, '/', installManifest));
      fout.SetCopyIfDifferent(true);
      for (auto const& dir : this->Directories) {
        auto localManifest = cmStrCat(dir, "/install_local_manifest.txt");
        if (cmSystemTools::FileExists(localManifest)) {
          cmsys::ifstream fin(localManifest.c_str());
          std::string line;
          while (std::getline(fin, line)) {
            fout << line << "\n";
          }
        }
      }
    }
  }
  return result;
}

InstallScriptRunner::InstallScriptRunner(InstallScript const& script)
{
  this->Name = cmSystemTools::RelativePath(
    cmSystemTools::GetLogicalWorkingDirectory(), script.path);
  this->Command = script.command;
}

bool InstallScriptRunner::start(cm::uv_loop_ptr& loop,
                                std::function<void()> callback)
{
  cmUVProcessChainBuilder builder;
  builder.AddCommand(this->Command)
    .SetExternalLoop(*loop)
    .SetMergedBuiltinStreams();
  this->Chain = cm::make_unique<cmUVProcessChain>(builder.Start());
  if (!this->Chain->Valid()) {
    return false;
  }
  this->StreamHandler = cmUVStreamRead(
    this->Chain->OutputStream(),
    [this](std::vector<char> data) {
      std::string strdata;
      cmProcessOutput(cmProcessOutput::Auto)
        .DecodeText(data.data(), data.size(), strdata);
      this->Output.push_back(strdata);
    },
    std::move(callback));
  return true;
}

void InstallScriptRunner::printResult(std::size_t n, std::size_t total)
{
  cmSystemTools::Stdout(cmStrCat('[', n, '/', total, "] ", this->Name, '\n'));
  for (auto const& line : this->Output) {
    cmSystemTools::Stdout(line);
  }
}

bool InstallScriptRunner::Failed() const
{
  if (!this->Chain || !this->Chain->Valid()) {
    return true;
  }
  auto const& status = this->Chain->GetStatus(0);
  return status.SpawnResult != 0 || status.TermSignal != 0 ||
    status.ExitStatus != 0;
}

void InstallScriptRunner::printFailure()
{
  std::string detail;
  if (!this->Chain || !this->Chain->Valid()) {
    // The chain never spawned a process (e.g. pipe/loop setup failed).
    detail = "failed to start";
  } else {
    auto const& status = this->Chain->GetStatus(0);
    auto exception = status.GetException();
    switch (exception.first) {
      case cmUVProcessChain::ExceptionCode::None:
        detail = cmStrCat("exited with code ", status.ExitStatus);
        break;
      case cmUVProcessChain::ExceptionCode::Spawn:
        // Prepared, but the process could not be executed.
        detail = cmStrCat("failed to start: ", exception.second);
        break;
      default:
        detail = exception.second;
        break;
    }
  }
  cmSystemTools::Stderr(
    cmStrCat("CMake Error: install script '", this->Name, "' ", detail, '\n'));
}
