/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCTestBZR.h"

#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmProcessTools.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"

#include "cm_expat.h"
#include "cmsys/RegularExpression.hxx"
#include <list>
#include <map>
#include <ostream>
#include <stdlib.h>
#include <vector>

extern "C" int cmBZRXMLParserUnknownEncodingHandler(void* /*unused*/,
                                                    const XML_Char* name,
                                                    XML_Encoding* info)
{
  static const int latin1[] = {
    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
    0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
    0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A,
    0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
    0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C,
    0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
    0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E,
    0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
    0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
    0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
    0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062,
    0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
    0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
    0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D,
    0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020,
    0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F,
    0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC,
    0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, 0x00A0, 0x00A1,
    0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA,
    0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3,
    0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC,
    0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5,
    0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE,
    0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
    0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0,
    0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9,
    0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2,
    0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
    0x00FC, 0x00FD, 0x00FE, 0x00FF
  };

  // The BZR xml output plugin can use some encodings that are not
  // recognized by expat.  This will lead to an error, e.g. "Error
  // parsing bzr log xml: unknown encoding", the following is a
  // workaround for these unknown encodings.
  if (name == std::string("ascii") || name == std::string("cp1252") ||
      name == std::string("ANSI_X3.4-1968")) {
    for (unsigned int i = 0; i < 256; ++i) {
      info->map[i] = latin1[i];
    }
    return 1;
  }

  return 0;
}

cmCTestBZR::cmCTestBZR(cmCTest* ct, std::ostream& log)
  : cmCTestGlobalVC(ct, log)
{
  this->PriorRev = this->Unknown;
  // Even though it is specified in the documentation, with bzr 1.13
  // BZR_PROGRESS_BAR has no effect. In the future this bug might be fixed.
  // Since it doesn't hurt, we specify this environment variable.
  cmSystemTools::PutEnv("BZR_PROGRESS_BAR=none");
}

cmCTestBZR::~cmCTestBZR() = default;

class cmCTestBZR::InfoParser : public cmCTestVC::LineParser
{
public:
  InfoParser(cmCTestBZR* bzr, const char* prefix)
    : BZR(bzr)
    , CheckOutFound(false)
  {
    this->SetLog(&bzr->Log, prefix);
    this->RegexCheckOut.compile("checkout of branch: *([^\t\r\n]+)$");
    this->RegexParent.compile("parent branch: *([^\t\r\n]+)$");
  }

private:
  cmCTestBZR* BZR;
  bool CheckOutFound;
  cmsys::RegularExpression RegexCheckOut;
  cmsys::RegularExpression RegexParent;
  bool ProcessLine() override
  {
    if (this->RegexCheckOut.find(this->Line)) {
      this->BZR->URL = this->RegexCheckOut.match(1);
      CheckOutFound = true;
    } else if (!CheckOutFound && this->RegexParent.find(this->Line)) {
      this->BZR->URL = this->RegexParent.match(1);
    }
    return true;
  }
};

class cmCTestBZR::RevnoParser : public cmCTestVC::LineParser
{
public:
  RevnoParser(cmCTestBZR* bzr, const char* prefix, std::string& rev)
    : Rev(rev)
  {
    this->SetLog(&bzr->Log, prefix);
    this->RegexRevno.compile("^([0-9]+)$");
  }

private:
  std::string& Rev;
  cmsys::RegularExpression RegexRevno;
  bool ProcessLine() override
  {
    if (this->RegexRevno.find(this->Line)) {
      this->Rev = this->RegexRevno.match(1);
    }
    return true;
  }
};

std::string cmCTestBZR::LoadInfo()
{
  // Run "bzr info" to get the repository info from the work tree.
  const char* bzr = this->CommandLineTool.c_str();
  const char* bzr_info[] = { bzr, "info", nullptr };
  InfoParser iout(this, "info-out> ");
  OutputLogger ierr(this->Log, "info-err> ");
  this->RunChild(bzr_info, &iout, &ierr);

  // Run "bzr revno" to get the repository revision number from the work tree.
  const char* bzr_revno[] = { bzr, "revno", nullptr };
  std::string rev;
  RevnoParser rout(this, "revno-out> ", rev);
  OutputLogger rerr(this->Log, "revno-err> ");
  this->RunChild(bzr_revno, &rout, &rerr);

  return rev;
}

bool cmCTestBZR::NoteOldRevision()
{
  this->OldRevision = this->LoadInfo();
  this->Log << "Revision before update: " << this->OldRevision << "\n";
  cmCTestLog(this->CTest, HANDLER_OUTPUT,
             "   Old revision of repository is: " << this->OldRevision
                                                  << "\n");
  this->PriorRev.Rev = this->OldRevision;
  return true;
}

bool cmCTestBZR::NoteNewRevision()
{
  this->NewRevision = this->LoadInfo();
  this->Log << "Revision after update: " << this->NewRevision << "\n";
  cmCTestLog(this->CTest, HANDLER_OUTPUT,
             "   New revision of repository is: " << this->NewRevision
                                                  << "\n");
  this->Log << "URL = " << this->URL << "\n";
  return true;
}

class cmCTestBZR::LogParser
  : public cmCTestVC::OutputLogger
  , private cmXMLParser
{
public:
  LogParser(cmCTestBZR* bzr, const char* prefix)
    : OutputLogger(bzr->Log, prefix)
    , BZR(bzr)
    , EmailRegex("(.*) <([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+)>")
  {
    this->InitializeParser();
  }
  ~LogParser() override { this->CleanupParser(); }

  int InitializeParser() override
  {
    int res = cmXMLParser::InitializeParser();
    if (res) {
      XML_SetUnknownEncodingHandler(static_cast<XML_Parser>(this->Parser),
                                    cmBZRXMLParserUnknownEncodingHandler,
                                    nullptr);
    }
    return res;
  }

private:
  cmCTestBZR* BZR;

  typedef cmCTestBZR::Revision Revision;
  typedef cmCTestBZR::Change Change;
  Revision Rev;
  std::vector<Change> Changes;
  Change CurChange;
  std::vector<char> CData;

  cmsys::RegularExpression EmailRegex;

  bool ProcessChunk(const char* data, int length) override
  {
    this->OutputLogger::ProcessChunk(data, length);
    this->ParseChunk(data, length);
    return true;
  }

  void StartElement(const std::string& name, const char** /*atts*/) override
  {
    this->CData.clear();
    if (name == "log") {
      this->Rev = Revision();
      this->Changes.clear();
    }
    // affected-files can contain blocks of
    // modified, unknown, renamed, kind-changed, removed, conflicts, added
    else if (name == "modified" || name == "renamed" ||
             name == "kind-changed") {
      this->CurChange = Change();
      this->CurChange.Action = 'M';
    } else if (name == "added") {
      this->CurChange = Change();
      this->CurChange = 'A';
    } else if (name == "removed") {
      this->CurChange = Change();
      this->CurChange = 'D';
    } else if (name == "unknown" || name == "conflicts") {
      // Should not happen here
      this->CurChange = Change();
    }
  }

  void CharacterDataHandler(const char* data, int length) override
  {
    this->CData.insert(this->CData.end(), data, data + length);
  }

  void EndElement(const std::string& name) override
  {
    if (name == "log") {
      this->BZR->DoRevision(this->Rev, this->Changes);
    } else if (!this->CData.empty() &&
               (name == "file" || name == "directory")) {
      this->CurChange.Path.assign(&this->CData[0], this->CData.size());
      cmSystemTools::ConvertToUnixSlashes(this->CurChange.Path);
      this->Changes.push_back(this->CurChange);
    } else if (!this->CData.empty() && name == "symlink") {
      // symlinks have an arobase at the end in the log
      this->CurChange.Path.assign(&this->CData[0], this->CData.size() - 1);
      cmSystemTools::ConvertToUnixSlashes(this->CurChange.Path);
      this->Changes.push_back(this->CurChange);
    } else if (!this->CData.empty() && name == "committer") {
      this->Rev.Author.assign(&this->CData[0], this->CData.size());
      if (this->EmailRegex.find(this->Rev.Author)) {
        this->Rev.Author = this->EmailRegex.match(1);
        this->Rev.EMail = this->EmailRegex.match(2);
      }
    } else if (!this->CData.empty() && name == "timestamp") {
      this->Rev.Date.assign(&this->CData[0], this->CData.size());
    } else if (!this->CData.empty() && name == "message") {
      this->Rev.Log.assign(&this->CData[0], this->CData.size());
    } else if (!this->CData.empty() && name == "revno") {
      this->Rev.Rev.assign(&this->CData[0], this->CData.size());
    }
    this->CData.clear();
  }

  void ReportError(int /*line*/, int /*column*/, const char* msg) override
  {
    this->BZR->Log << "Error parsing bzr log xml: " << msg << "\n";
  }
};

class cmCTestBZR::UpdateParser : public cmCTestVC::LineParser
{
public:
  UpdateParser(cmCTestBZR* bzr, const char* prefix)
    : BZR(bzr)
  {
    this->SetLog(&bzr->Log, prefix);
    this->RegexUpdate.compile("^([-+R?XCP ])([NDKM ])([* ]) +(.+)$");
  }

private:
  cmCTestBZR* BZR;
  cmsys::RegularExpression RegexUpdate;

  bool ProcessChunk(const char* first, int length) override
  {
    bool last_is_new_line = (*first == '\r' || *first == '\n');

    const char* const last = first + length;
    for (const char* c = first; c != last; ++c) {
      if (*c == '\r' || *c == '\n') {
        if (!last_is_new_line) {
          // Log this line.
          if (this->Log && this->Prefix) {
            *this->Log << this->Prefix << this->Line << "\n";
          }

          // Hand this line to the subclass implementation.
          if (!this->ProcessLine()) {
            this->Line.clear();
            return false;
          }

          this->Line.clear();
          last_is_new_line = true;
        }
      } else {
        // Append this character to the line under construction.
        this->Line.append(1, *c);
        last_is_new_line = false;
      }
    }
    return true;
  }

  bool ProcessLine() override
  {
    if (this->RegexUpdate.find(this->Line)) {
      this->DoPath(this->RegexUpdate.match(1)[0],
                   this->RegexUpdate.match(2)[0],
                   this->RegexUpdate.match(3)[0], this->RegexUpdate.match(4));
    }
    return true;
  }

  void DoPath(char c0, char c1, char c2, std::string path)
  {
    if (path.empty()) {
      return;
    }
    cmSystemTools::ConvertToUnixSlashes(path);

    const std::string dir = cmSystemTools::GetFilenamePath(path);
    const std::string name = cmSystemTools::GetFilenameName(path);

    if (c0 == 'C') {
      this->BZR->Dirs[dir][name].Status = PathConflicting;
      return;
    }

    if (c1 == 'M' || c1 == 'K' || c1 == 'N' || c1 == 'D' || c2 == '*') {
      this->BZR->Dirs[dir][name].Status = PathUpdated;
      return;
    }
  }
};

bool cmCTestBZR::UpdateImpl()
{
  // Get user-specified update options.
  std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
  if (opts.empty()) {
    opts = this->CTest->GetCTestConfiguration("BZRUpdateOptions");
  }
  std::vector<std::string> args = cmSystemTools::ParseArguments(opts);

  // TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)

  // Use "bzr pull" to update the working tree.
  std::vector<char const*> bzr_update;
  bzr_update.push_back(this->CommandLineTool.c_str());
  bzr_update.push_back("pull");

  for (std::string const& arg : args) {
    bzr_update.push_back(arg.c_str());
  }

  bzr_update.push_back(this->URL.c_str());

  bzr_update.push_back(nullptr);

  // For some reason bzr uses stderr to display the update status.
  OutputLogger out(this->Log, "pull-out> ");
  UpdateParser err(this, "pull-err> ");
  return this->RunUpdateCommand(&bzr_update[0], &out, &err);
}

bool cmCTestBZR::LoadRevisions()
{
  cmCTestLog(this->CTest, HANDLER_OUTPUT,
             "   Gathering version information (one . per revision):\n"
             "    "
               << std::flush);

  // We are interested in every revision included in the update.
  this->Revisions.clear();
  std::string revs;
  if (atoi(this->OldRevision.c_str()) <= atoi(this->NewRevision.c_str())) {
    // DoRevision takes care of discarding the information about OldRevision
    revs = this->OldRevision + ".." + this->NewRevision;
  } else {
    return true;
  }

  // Run "bzr log" to get all global revisions of interest.
  const char* bzr = this->CommandLineTool.c_str();
  const char* bzr_log[] = {
    bzr, "log", "-v", "-r", revs.c_str(), "--xml", this->URL.c_str(), nullptr
  };
  {
    LogParser out(this, "log-out> ");
    OutputLogger err(this->Log, "log-err> ");
    this->RunChild(bzr_log, &out, &err);
  }
  cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
  return true;
}

class cmCTestBZR::StatusParser : public cmCTestVC::LineParser
{
public:
  StatusParser(cmCTestBZR* bzr, const char* prefix)
    : BZR(bzr)
  {
    this->SetLog(&bzr->Log, prefix);
    this->RegexStatus.compile("^([-+R?XCP ])([NDKM ])([* ]) +(.+)$");
  }

private:
  cmCTestBZR* BZR;
  cmsys::RegularExpression RegexStatus;
  bool ProcessLine() override
  {
    if (this->RegexStatus.find(this->Line)) {
      this->DoPath(this->RegexStatus.match(1)[0],
                   this->RegexStatus.match(2)[0],
                   this->RegexStatus.match(3)[0], this->RegexStatus.match(4));
    }
    return true;
  }

  void DoPath(char c0, char c1, char c2, std::string path)
  {
    if (path.empty()) {
      return;
    }
    cmSystemTools::ConvertToUnixSlashes(path);

    if (c0 == 'C') {
      this->BZR->DoModification(PathConflicting, path);
      return;
    }

    if (c0 == '+' || c0 == 'R' || c0 == 'P' || c1 == 'M' || c1 == 'K' ||
        c1 == 'N' || c1 == 'D' || c2 == '*') {
      this->BZR->DoModification(PathModified, path);
      return;
    }
  }
};

bool cmCTestBZR::LoadModifications()
{
  // Run "bzr status" which reports local modifications.
  const char* bzr = this->CommandLineTool.c_str();
  const char* bzr_status[] = { bzr, "status", "-SV", nullptr };
  StatusParser out(this, "status-out> ");
  OutputLogger err(this->Log, "status-err> ");
  this->RunChild(bzr_status, &out, &err);
  return true;
}
