/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2013 Kitware, Inc.

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmCTestP4.h"

#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLSafe.h"

#include <cmsys/RegularExpression.hxx>
#include <cmsys/ios/sstream>
#include <cmsys/Process.h>

#include <sys/types.h>
#include <time.h>
#include <ctype.h>

//----------------------------------------------------------------------------
cmCTestP4::cmCTestP4(cmCTest* ct, std::ostream& log):
  cmCTestGlobalVC(ct, log)
{
  this->PriorRev = this->Unknown;
}

//----------------------------------------------------------------------------
cmCTestP4::~cmCTestP4()
{
}

//----------------------------------------------------------------------------
class cmCTestP4::IdentifyParser: public cmCTestVC::LineParser
{
public:
  IdentifyParser(cmCTestP4* p4, const char* prefix,
                 std::string& rev): Rev(rev)
    {
    this->SetLog(&p4->Log, prefix);
    this->RegexIdentify.compile("^Change ([0-9]+) on");
    }
private:
  std::string& Rev;
  cmsys::RegularExpression RegexIdentify;

  bool ProcessLine()
    {
    if(this->RegexIdentify.find(this->Line))
      {
      this->Rev = this->RegexIdentify.match(1);
      return false;
      }
    return true;
    }
};

//----------------------------------------------------------------------------
class cmCTestP4::ChangesParser: public cmCTestVC::LineParser
{
public:
  ChangesParser(cmCTestP4* p4, const char* prefix) : P4(p4)
    {
    this->SetLog(&P4->Log, prefix);
    this->RegexIdentify.compile("^Change ([0-9]+) on");
    }
private:
  cmsys::RegularExpression RegexIdentify;
  cmCTestP4* P4;

  bool ProcessLine()
    {
    if(this->RegexIdentify.find(this->Line))
      {
      P4->ChangeLists.push_back(this->RegexIdentify.match(1));
      }
    return true;
    }
};

//----------------------------------------------------------------------------
class cmCTestP4::UserParser: public cmCTestVC::LineParser
{
public:
  UserParser(cmCTestP4* p4, const char* prefix) : P4(p4)
    {
    this->SetLog(&P4->Log, prefix);
    this->RegexUser.compile("^(.+) <(.*)> \\((.*)\\) accessed (.*)$");
    }
private:
  cmsys::RegularExpression RegexUser;
  cmCTestP4* P4;

  bool ProcessLine()
    {
    if(this->RegexUser.find(this->Line))
      {
      User NewUser;

      NewUser.UserName = this->RegexUser.match(1);
      NewUser.EMail = this->RegexUser.match(2);
      NewUser.Name = this->RegexUser.match(3);
      NewUser.AccessTime = this->RegexUser.match(4);
      P4->Users[this->RegexUser.match(1)] = NewUser;

      return false;
      }
    return true;
    }
};

//----------------------------------------------------------------------------
/* Diff format:
==== //depot/file#rev - /absolute/path/to/file ====
(diff data)
==== //depot/file2#rev - /absolute/path/to/file2 ====
(diff data)
==== //depot/file3#rev - /absolute/path/to/file3 ====
==== //depot/file4#rev - /absolute/path/to/file4 ====
(diff data)
*/
class cmCTestP4::DiffParser: public cmCTestVC::LineParser
{
public:
  DiffParser(cmCTestP4* p4, const char* prefix)
             : P4(p4), AlreadyNotified(false)
    {
    this->SetLog(&P4->Log, prefix);
    this->RegexDiff.compile("^==== (.*)#[0-9]+ - (.*)");
    }
private:
  cmCTestP4* P4;
  bool AlreadyNotified;
  std::string CurrentPath;
  cmsys::RegularExpression RegexDiff;

  bool ProcessLine()
    {
    if(!this->Line.empty() && this->Line[0] == '='
       && this->RegexDiff.find(this->Line))
      {
        CurrentPath = this->RegexDiff.match(1);
        AlreadyNotified = false;
      }
    else
      {
      if(!AlreadyNotified)
        {
        P4->DoModification(PathModified, CurrentPath);
        AlreadyNotified = true;
        }
      }
    return true;
    }
};

//----------------------------------------------------------------------------
cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)
{
  std::map<std::string, cmCTestP4::User>::const_iterator it =
          Users.find(username);

  if(it == Users.end())
    {
    std::vector<char const*> p4_users;
    SetP4Options(p4_users);
    p4_users.push_back("users");
    p4_users.push_back("-m");
    p4_users.push_back("1");
    p4_users.push_back(username.c_str());
    p4_users.push_back(0);

    UserParser out(this, "users-out> ");
    OutputLogger err(this->Log, "users-err> ");
    RunChild(&p4_users[0], &out, &err);

    // The user should now be added to the map. Search again.
    it = Users.find(username);
    if(it == Users.end())
      {
      return cmCTestP4::User();
      }
    }

  return it->second;
}

//----------------------------------------------------------------------------
/* Commit format:

Change 1111111 by user@client on 2013/09/26 11:50:36

        text
        text

Affected files ...

... //path/to/file#rev edit
... //path/to/file#rev add
... //path/to/file#rev delete
... //path/to/file#rev integrate
*/
class cmCTestP4::DescribeParser: public cmCTestVC::LineParser
{
public:
  DescribeParser(cmCTestP4* p4, const char* prefix):
      LineParser('\n', false), P4(p4), Section(SectionHeader)
    {
    this->SetLog(&P4->Log, prefix);
    this->RegexHeader.compile("^Change ([0-9]+) by (.+)@(.+) on (.*)$");
    this->RegexDiff.compile("^\\.\\.\\. (.*)#[0-9]+ ([^ ]+)$");
    }
private:
  cmsys::RegularExpression RegexHeader;
  cmsys::RegularExpression RegexDiff;
  cmCTestP4* P4;

  typedef cmCTestP4::Revision Revision;
  typedef cmCTestP4::Change Change;
  std::vector<Change> Changes;
  enum SectionType { SectionHeader, SectionBody, SectionDiffHeader,
                     SectionDiff, SectionCount };
  SectionType Section;
  Revision Rev;

  virtual bool ProcessLine()
    {
    if(this->Line.empty())
      {
      this->NextSection();
      }
    else
      {
      switch(this->Section)
        {
        case SectionHeader:     this->DoHeaderLine(); break;
        case SectionBody:       this->DoBodyLine(); break;
        case SectionDiffHeader: break; // nothing to do
        case SectionDiff:       this->DoDiffLine(); break;
        case SectionCount:      break; // never happens
        }
      }
      return true;
      }

  void NextSection()
    {
    if(this->Section == SectionDiff)
    {
      this->P4->DoRevision(this->Rev, this->Changes);
      this->Rev = Revision();
    }

    this->Section = SectionType((this->Section+1) % SectionCount);
    }

  void DoHeaderLine()
    {
    if(this->RegexHeader.find(this->Line))
      {
      this->Rev.Rev = this->RegexHeader.match(1);
      this->Rev.Date = this->RegexHeader.match(4);

      cmCTestP4::User user = P4->GetUserData(this->RegexHeader.match(2));
      this->Rev.Author = user.Name;
      this->Rev.EMail = user.EMail;

      this->Rev.Committer = this->Rev.Author;
      this->Rev.CommitterEMail = this->Rev.EMail;
      this->Rev.CommitDate = this->Rev.Date;
      }
    }

  void DoBodyLine()
    {
    if(this->Line[0] == '\t')
      {
      this->Rev.Log += this->Line.substr(1);
      }
    this->Rev.Log += "\n";
    }

  void DoDiffLine()
    {
    if(this->RegexDiff.find(this->Line))
    {
    Change change;
    std::string Path = this->RegexDiff.match(1);
    if(Path.length() > 2 && Path[0] == '/' && Path[1] == '/')
      {
      size_t found = Path.find('/', 2);
      if(found != std::string::npos)
        {
        Path = Path.substr(found + 1);
        }
      }

    change.Path = Path;
    std::string action = this->RegexDiff.match(2);

    if(action == "add")
      {
      change.Action = 'A';
      }
    else if(action == "delete")
      {
      change.Action = 'D';
      }
    else if(action == "edit" || action == "integrate")
      {
      change.Action = 'M';
      }

    Changes.push_back(change);
    }
  }
};

//----------------------------------------------------------------------------
void cmCTestP4::SetP4Options(std::vector<char const*> &CommandOptions)
{
  if(P4Options.size() == 0)
    {
    const char* p4 = this->CommandLineTool.c_str();
    P4Options.push_back(p4);

    //The CTEST_P4_CLIENT variable sets the P4 client used when issuing
    //Perforce commands, if it's different from the default one.
    std::string client = this->CTest->GetCTestConfiguration("P4Client");
    if(!client.empty())
      {
      P4Options.push_back("-c");
      P4Options.push_back(client);
      }

    //Set the message language to be English, in case the P4 admin
    //has localized them
    P4Options.push_back("-L");
    P4Options.push_back("en");

    //The CTEST_P4_OPTIONS variable adds additional Perforce command line
    //options before the main command
    std::string opts = this->CTest->GetCTestConfiguration("P4Options");
    std::vector<std::string> args =
            cmSystemTools::ParseArguments(opts.c_str());

    for(std::vector<std::string>::const_iterator ai = args.begin();
        ai != args.end(); ++ai)
      {
      P4Options.push_back(*ai);
      }
    }

  CommandOptions.clear();
  for(std::vector<std::string>::iterator i = P4Options.begin();
      i != P4Options.end(); ++i)
    {
    CommandOptions.push_back(i->c_str());
    }
}

//----------------------------------------------------------------------------
std::string cmCTestP4::GetWorkingRevision()
{
  std::vector<char const*> p4_identify;
  SetP4Options(p4_identify);

  p4_identify.push_back("changes");
  p4_identify.push_back("-m");
  p4_identify.push_back("1");
  p4_identify.push_back("-t");

  std::string source = this->SourceDirectory + "/...#have";
  p4_identify.push_back(source.c_str());
  p4_identify.push_back(0);

  std::string rev;
  IdentifyParser out(this, "p4_changes-out> ", rev);
  OutputLogger err(this->Log, "p4_changes-err> ");

  bool result = RunChild(&p4_identify[0], &out, &err);

  // If there was a problem contacting the server return "<unknown>"
  if(!result)
    {
    return "<unknown>";
    }

  if(rev.empty())
    {
    return "0";
    }
  else
    {
    return rev;
    }
}

//----------------------------------------------------------------------------
void cmCTestP4::NoteOldRevision()
{
  this->OldRevision = this->GetWorkingRevision();

  cmCTestLog(this->CTest, HANDLER_OUTPUT, "   Old revision of repository is: "
             << this->OldRevision << "\n");
  this->PriorRev.Rev = this->OldRevision;
}

//----------------------------------------------------------------------------
void cmCTestP4::NoteNewRevision()
{
  this->NewRevision = this->GetWorkingRevision();

  cmCTestLog(this->CTest, HANDLER_OUTPUT, "   New revision of repository is: "
             << this->NewRevision << "\n");
}

//----------------------------------------------------------------------------
void cmCTestP4::LoadRevisions()
{
  std::vector<char const*> p4_changes;
  SetP4Options(p4_changes);

  // Use 'p4 changes ...@old,new' to get a list of changelists
  std::string range = this->SourceDirectory + "/...";

  // If any revision is unknown it means we couldn't contact the server.
  // Do not process updates
  if(this->OldRevision == "<unknown>" || this->NewRevision == "<unknown>")
    {
    cmCTestLog(this->CTest, HANDLER_OUTPUT, "   At least one of the revisions "
               << "is unknown. No repository changes will be reported.\n");
    return;
    }

  range.append("@").append(this->OldRevision)
       .append(",").append(this->NewRevision);

  p4_changes.push_back("changes");
  p4_changes.push_back(range.c_str());
  p4_changes.push_back(0);

  ChangesParser out(this, "p4_changes-out> ");
  OutputLogger err(this->Log, "p4_changes-err> ");

  ChangeLists.clear();
  this->RunChild(&p4_changes[0], &out, &err);

  if(ChangeLists.size() == 0)
      return;

  //p4 describe -s ...@1111111,2222222
  std::vector<char const*> p4_describe;
  for(std::vector<std::string>::reverse_iterator i = ChangeLists.rbegin();
      i != ChangeLists.rend(); ++i)
    {
    SetP4Options(p4_describe);
    p4_describe.push_back("describe");
    p4_describe.push_back("-s");
    p4_describe.push_back(i->c_str());
    p4_describe.push_back(0);

    DescribeParser outDescribe(this, "p4_describe-out> ");
    OutputLogger errDescribe(this->Log, "p4_describe-err> ");
    this->RunChild(&p4_describe[0], &outDescribe, &errDescribe);
    }
}

//----------------------------------------------------------------------------
void cmCTestP4::LoadModifications()
{
  std::vector<char const*> p4_diff;
  SetP4Options(p4_diff);

  p4_diff.push_back("diff");

  //Ideally we would use -Od but not all clients support it
  p4_diff.push_back("-dn");
  std::string source = this->SourceDirectory + "/...";
  p4_diff.push_back(source.c_str());
  p4_diff.push_back(0);

  DiffParser out(this, "p4_diff-out> ");
  OutputLogger err(this->Log, "p4_diff-err> ");
  this->RunChild(&p4_diff[0], &out, &err);
}

//----------------------------------------------------------------------------
bool cmCTestP4::UpdateCustom(const std::string& custom)
{
  std::vector<std::string> p4_custom_command;
  cmSystemTools::ExpandListArgument(custom, p4_custom_command, true);

  std::vector<char const*> p4_custom;
  for(std::vector<std::string>::const_iterator
        i = p4_custom_command.begin(); i != p4_custom_command.end(); ++i)
    {
    p4_custom.push_back(i->c_str());
    }
  p4_custom.push_back(0);

  OutputLogger custom_out(this->Log, "p4_customsync-out> ");
  OutputLogger custom_err(this->Log, "p4_customsync-err> ");

  return this->RunUpdateCommand(&p4_custom[0], &custom_out, &custom_err);
}

//----------------------------------------------------------------------------
bool cmCTestP4::UpdateImpl()
{
  std::string custom = this->CTest->GetCTestConfiguration("P4UpdateCustom");
  if(!custom.empty())
    {
    return this->UpdateCustom(custom);
    }

  // If we couldn't get a revision number before updating, abort.
  if(this->OldRevision == "<unknown>")
    {
    this->UpdateCommandLine = "Unknown current revision";
    cmCTestLog(this->CTest, ERROR_MESSAGE, "   Unknown current revision\n");
    return false;
    }

  std::vector<char const*> p4_sync;
  SetP4Options(p4_sync);

  p4_sync.push_back("sync");

  // Get user-specified update options.
  std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions");
  if(opts.empty())
    {
    opts = this->CTest->GetCTestConfiguration("P4UpdateOptions");
    }
  std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
  for(std::vector<std::string>::const_iterator ai = args.begin();
      ai != args.end(); ++ai)
    {
    p4_sync.push_back(ai->c_str());
    }

  std::string source = this->SourceDirectory + "/...";

  // Specify the start time for nightly testing.
  if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
    {
    std::string date = this->GetNightlyTime();
    //CTest reports the date as YYYY-MM-DD, Perforce needs it as YYYY/MM/DD
    std::replace(date.begin(), date.end(), '-', '/');

    //Revision specification: /...@"YYYY/MM/DD HH:MM:SS"
    source.append("@\"").append(date).append("\"");
    }

  p4_sync.push_back(source.c_str());
  p4_sync.push_back(0);

  OutputLogger out(this->Log, "p4_sync-out> ");
  OutputLogger err(this->Log, "p4_sync-err> ");

  return this->RunUpdateCommand(&p4_sync[0], &out, &err);
}
