/*============================================================================
  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 <cmsys/RegularExpression.hxx>
#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.empty())
    {
    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());

    P4Options.insert(P4Options.end(), args.begin(), args.end());
    }

  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.empty())
      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);
}
