/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 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 "cmCTestGIT.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>

//----------------------------------------------------------------------------
static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major,
                                      unsigned int minor, unsigned int fix)
{
  // 1.6.5.0 maps to 10605000
  return fix + minor*1000 + major*100000 + epic*10000000;
}

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

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

//----------------------------------------------------------------------------
class cmCTestGIT::OneLineParser: public cmCTestVC::LineParser
{
public:
  OneLineParser(cmCTestGIT* git, const char* prefix,
                std::string& l): Line1(l)
    {
    this->SetLog(&git->Log, prefix);
    }
private:
  std::string& Line1;
  virtual bool ProcessLine()
    {
    // Only the first line is of interest.
    this->Line1 = this->Line;
    return false;
    }
};

//----------------------------------------------------------------------------
std::string cmCTestGIT::GetWorkingRevision()
{
  // Run plumbing "git rev-list" to get work tree revision.
  const char* git = this->CommandLineTool.c_str();
  const char* git_rev_list[] = {git, "rev-list", "-n", "1", "HEAD", "--", 0};
  std::string rev;
  OneLineParser out(this, "rl-out> ", rev);
  OutputLogger err(this->Log, "rl-err> ");
  this->RunChild(git_rev_list, &out, &err);
  return rev;
}

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

//----------------------------------------------------------------------------
void cmCTestGIT::NoteNewRevision()
{
  this->NewRevision = this->GetWorkingRevision();
  cmCTestLog(this->CTest, HANDLER_OUTPUT, "   New revision of repository is: "
             << this->NewRevision << "\n");
}

//----------------------------------------------------------------------------
std::string cmCTestGIT::FindGitDir()
{
  std::string git_dir;

  // Run "git rev-parse --git-dir" to locate the real .git directory.
  const char* git = this->CommandLineTool.c_str();
  char const* git_rev_parse[] = {git, "rev-parse", "--git-dir", 0};
  std::string git_dir_line;
  OneLineParser rev_parse_out(this, "rev-parse-out> ", git_dir_line);
  OutputLogger rev_parse_err(this->Log, "rev-parse-err> ");
  if(this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err))
    {
    git_dir = git_dir_line;
    }
  if(git_dir.empty())
    {
    git_dir = ".git";
    }

  // Git reports a relative path only when the .git directory is in
  // the current directory.
  if(git_dir[0] == '.')
    {
    git_dir = this->SourceDirectory + "/" + git_dir;
    }
#if defined(_WIN32) && !defined(__CYGWIN__)
  else if(git_dir[0] == '/')
    {
    // Cygwin Git reports a full path that Cygwin understands, but we
    // are a Windows application.  Run "cygpath" to get Windows path.
    std::string cygpath_exe = cmSystemTools::GetFilenamePath(git);
    cygpath_exe += "/cygpath.exe";
    if(cmSystemTools::FileExists(cygpath_exe.c_str()))
      {
      char const* cygpath[] = {cygpath_exe.c_str(), "-w", git_dir.c_str(), 0};
      OneLineParser cygpath_out(this, "cygpath-out> ", git_dir_line);
      OutputLogger cygpath_err(this->Log, "cygpath-err> ");
      if(this->RunChild(cygpath, &cygpath_out, &cygpath_err))
        {
        git_dir = git_dir_line;
        }
      }
    }
#endif
  return git_dir;
}

//----------------------------------------------------------------------------
std::string cmCTestGIT::FindTopDir()
{
  std::string top_dir = this->SourceDirectory;

  // Run "git rev-parse --show-cdup" to locate the top of the tree.
  const char* git = this->CommandLineTool.c_str();
  char const* git_rev_parse[] = {git, "rev-parse", "--show-cdup", 0};
  std::string cdup;
  OneLineParser rev_parse_out(this, "rev-parse-out> ", cdup);
  OutputLogger rev_parse_err(this->Log, "rev-parse-err> ");
  if(this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err) &&
     !cdup.empty())
    {
    top_dir += "/";
    top_dir += cdup;
    top_dir = cmSystemTools::CollapseFullPath(top_dir.c_str());
    }
  return top_dir;
}

//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateByFetchAndReset()
{
  const char* git = this->CommandLineTool.c_str();

  // Use "git fetch" to get remote commits.
  std::vector<char const*> git_fetch;
  git_fetch.push_back(git);
  git_fetch.push_back("fetch");

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

  // Sentinel argument.
  git_fetch.push_back(0);

  // Fetch upstream refs.
  OutputLogger fetch_out(this->Log, "fetch-out> ");
  OutputLogger fetch_err(this->Log, "fetch-err> ");
  if(!this->RunUpdateCommand(&git_fetch[0], &fetch_out, &fetch_err))
    {
    return false;
    }

  // Identify the merge head that would be used by "git pull".
  std::string sha1;
  {
  std::string fetch_head = this->FindGitDir() + "/FETCH_HEAD";
  std::ifstream fin(fetch_head.c_str(), std::ios::in | std::ios::binary);
  if(!fin)
    {
    this->Log << "Unable to open " << fetch_head << "\n";
    return false;
    }
  std::string line;
  while(sha1.empty() && cmSystemTools::GetLineFromStream(fin, line))
    {
    this->Log << "FETCH_HEAD> " << line << "\n";
    if(line.find("\tnot-for-merge\t") == line.npos)
      {
      std::string::size_type pos = line.find('\t');
      if(pos != line.npos)
        {
        sha1 = line.substr(0, pos);
        }
      }
    }
  if(sha1.empty())
    {
    this->Log << "FETCH_HEAD has no upstream branch candidate!\n";
    return false;
    }
  }

  // Reset the local branch to point at that tracked from upstream.
  char const* git_reset[] = {git, "reset", "--hard", sha1.c_str(), 0};
  OutputLogger reset_out(this->Log, "reset-out> ");
  OutputLogger reset_err(this->Log, "reset-err> ");
  return this->RunChild(&git_reset[0], &reset_out, &reset_err);
}

//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateByCustom(std::string const& custom)
{
  std::vector<std::string> git_custom_command;
  cmSystemTools::ExpandListArgument(custom, git_custom_command, true);
  std::vector<char const*> git_custom;
  for(std::vector<std::string>::const_iterator
        i = git_custom_command.begin(); i != git_custom_command.end(); ++i)
    {
    git_custom.push_back(i->c_str());
    }
  git_custom.push_back(0);

  OutputLogger custom_out(this->Log, "custom-out> ");
  OutputLogger custom_err(this->Log, "custom-err> ");
  return this->RunUpdateCommand(&git_custom[0], &custom_out, &custom_err);
}

//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateInternal()
{
  std::string custom = this->CTest->GetCTestConfiguration("GITUpdateCustom");
  if(!custom.empty())
    {
    return this->UpdateByCustom(custom);
    }
  return this->UpdateByFetchAndReset();
}

//----------------------------------------------------------------------------
bool cmCTestGIT::UpdateImpl()
{
  if(!this->UpdateInternal())
    {
    return false;
    }

  std::string top_dir = this->FindTopDir();
  const char* git = this->CommandLineTool.c_str();
  const char* recursive = "--recursive";

  // Git < 1.6.5.0 did not support --recursive
  if(this->GetGitVersion() < cmCTestGITVersion(1,6,5,0))
    {
    recursive = 0;
    // No need to require >= 1.6.5.0 if there are no submodules.
    if(cmSystemTools::FileExists((top_dir + "/.gitmodules").c_str()))
      {
      this->Log << "Git < 1.6.5.0 cannot update submodules recursively\n";
      }
    }

  char const* git_submodule[] = {git, "submodule", "update", recursive, 0};
  OutputLogger submodule_out(this->Log, "submodule-out> ");
  OutputLogger submodule_err(this->Log, "submodule-err> ");
  return this->RunChild(git_submodule, &submodule_out, &submodule_err,
                        top_dir.c_str());
}

//----------------------------------------------------------------------------
unsigned int cmCTestGIT::GetGitVersion()
{
  if(!this->CurrentGitVersion)
    {
    const char* git = this->CommandLineTool.c_str();
    char const* git_version[] = {git, "--version", 0};
    std::string version;
    OneLineParser version_out(this, "version-out> ", version);
    OutputLogger version_err(this->Log, "version-err> ");
    unsigned int v[4] = {0,0,0,0};
    if(this->RunChild(git_version, &version_out, &version_err) &&
       sscanf(version.c_str(), "git version %u.%u.%u.%u",
              &v[0], &v[1], &v[2], &v[3]) >= 3)
      {
      this->CurrentGitVersion = cmCTestGITVersion(v[0], v[1], v[2], v[3]);
      }
    }
  return this->CurrentGitVersion;
}

//----------------------------------------------------------------------------
/* Diff format:

   :src-mode dst-mode src-sha1 dst-sha1 status\0
   src-path\0
   [dst-path\0]

   The format is repeated for every file changed.  The [dst-path\0]
   line appears only for lines with status 'C' or 'R'.  See 'git help
   diff-tree' for details.
*/
class cmCTestGIT::DiffParser: public cmCTestVC::LineParser
{
public:
  DiffParser(cmCTestGIT* git, const char* prefix):
    LineParser('\0', false), GIT(git), DiffField(DiffFieldNone)
    {
    this->SetLog(&git->Log, prefix);
    }

  typedef cmCTestGIT::Change Change;
  std::vector<Change> Changes;
protected:
  cmCTestGIT* GIT;
  enum DiffFieldType { DiffFieldNone, DiffFieldChange,
                       DiffFieldSrc, DiffFieldDst };
  DiffFieldType DiffField;
  Change CurChange;

  void DiffReset()
    {
    this->DiffField = DiffFieldNone;
    this->Changes.clear();
    }

  virtual bool ProcessLine()
    {
    if(this->Line[0] == ':')
      {
      this->DiffField = DiffFieldChange;
      this->CurChange = Change();
      }
    if(this->DiffField == DiffFieldChange)
      {
      // :src-mode dst-mode src-sha1 dst-sha1 status
      if(this->Line[0] != ':')
        {
        this->DiffField = DiffFieldNone;
        return true;
        }
      const char* src_mode_first = this->Line.c_str()+1;
      const char* src_mode_last  = this->ConsumeField(src_mode_first);
      const char* dst_mode_first = this->ConsumeSpace(src_mode_last);
      const char* dst_mode_last  = this->ConsumeField(dst_mode_first);
      const char* src_sha1_first = this->ConsumeSpace(dst_mode_last);
      const char* src_sha1_last  = this->ConsumeField(src_sha1_first);
      const char* dst_sha1_first = this->ConsumeSpace(src_sha1_last);
      const char* dst_sha1_last  = this->ConsumeField(dst_sha1_first);
      const char* status_first   = this->ConsumeSpace(dst_sha1_last);
      const char* status_last    = this->ConsumeField(status_first);
      if(status_first != status_last)
        {
        this->CurChange.Action = *status_first;
        this->DiffField = DiffFieldSrc;
        }
      else
        {
        this->DiffField = DiffFieldNone;
        }
      }
    else if(this->DiffField == DiffFieldSrc)
      {
      // src-path
      if(this->CurChange.Action == 'C')
        {
        // Convert copy to addition of destination.
        this->CurChange.Action = 'A';
        this->DiffField = DiffFieldDst;
        }
      else if(this->CurChange.Action == 'R')
        {
        // Convert rename to deletion of source and addition of destination.
        this->CurChange.Action = 'D';
        this->CurChange.Path = this->Line;
        this->Changes.push_back(this->CurChange);

        this->CurChange = Change('A');
        this->DiffField = DiffFieldDst;
        }
      else
        {
        this->CurChange.Path = this->Line;
        this->Changes.push_back(this->CurChange);
        this->DiffField = this->DiffFieldNone;
        }
      }
    else if(this->DiffField == DiffFieldDst)
      {
      // dst-path
      this->CurChange.Path = this->Line;
      this->Changes.push_back(this->CurChange);
      this->DiffField = this->DiffFieldNone;
      }
    return true;
    }

  const char* ConsumeSpace(const char* c)
    {
    while(*c && isspace(*c)) { ++c; }
    return c;
    }
  const char* ConsumeField(const char* c)
    {
    while(*c && !isspace(*c)) { ++c; }
    return c;
    }
};

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

   commit ...\n
   tree ...\n
   parent ...\n
   author ...\n
   committer ...\n
   \n
       Log message indented by (4) spaces\n
       (even blank lines have the spaces)\n
 [[
   \n
   [Diff format]
 OR
   \0
 ]]

   The header may have more fields.  See 'git help diff-tree'.
*/
class cmCTestGIT::CommitParser: public cmCTestGIT::DiffParser
{
public:
  CommitParser(cmCTestGIT* git, const char* prefix):
    DiffParser(git, prefix), Section(SectionHeader)
    {
    this->Separator = SectionSep[this->Section];
    }

private:
  typedef cmCTestGIT::Revision Revision;
  enum SectionType { SectionHeader, SectionBody, SectionDiff, SectionCount };
  static char const SectionSep[SectionCount];
  SectionType Section;
  Revision Rev;

  struct Person
  {
    std::string Name;
    std::string EMail;
    unsigned long Time;
    long TimeZone;
    Person(): Name(), EMail(), Time(0), TimeZone(0) {}
  };

  void ParsePerson(const char* str, Person& person)
    {
    // Person Name <person@domain.com> 1234567890 +0000
    const char* c = str;
    while(*c && isspace(*c)) { ++c; }

    const char* name_first = c;
    while(*c && *c != '<') { ++c; }
    const char* name_last = c;
    while(name_last != name_first && isspace(*(name_last-1))) { --name_last; }
    person.Name.assign(name_first, name_last-name_first);

    const char* email_first = *c? ++c : c;
    while(*c && *c != '>') { ++c; }
    const char* email_last = *c? c++ : c;
    person.EMail.assign(email_first, email_last-email_first);

    person.Time = strtoul(c, (char**)&c, 10);
    person.TimeZone = strtol(c, (char**)&c, 10);
    }

  virtual bool ProcessLine()
    {
    if(this->Line.empty())
      {
      if(this->Section == SectionBody && this->LineEnd == '\0')
        {
        // Skip SectionDiff
        this->NextSection();
        }
      this->NextSection();
      }
    else
      {
      switch(this->Section)
        {
        case SectionHeader: this->DoHeaderLine(); break;
        case SectionBody:   this->DoBodyLine(); break;
        case SectionDiff:   this->DiffParser::ProcessLine(); break;
        case SectionCount:  break; // never happens
        }
      }
    return true;
    }

  void NextSection()
    {
    this->Section = SectionType((this->Section+1) % SectionCount);
    this->Separator = SectionSep[this->Section];
    if(this->Section == SectionHeader)
      {
      this->GIT->DoRevision(this->Rev, this->Changes);
      this->Rev = Revision();
      this->DiffReset();
      }
    }

  void DoHeaderLine()
    {
    // Look for header fields that we need.
    if(strncmp(this->Line.c_str(), "commit ", 7) == 0)
      {
      this->Rev.Rev = this->Line.c_str()+7;
      }
    else if(strncmp(this->Line.c_str(), "author ", 7) == 0)
      {
      Person author;
      this->ParsePerson(this->Line.c_str()+7, author);
      this->Rev.Author = author.Name;
      this->Rev.EMail = author.EMail;
      this->Rev.Date = this->FormatDateTime(author);
      }
    else if(strncmp(this->Line.c_str(), "committer ", 10) == 0)
      {
      Person committer;
      this->ParsePerson(this->Line.c_str()+10, committer);
      this->Rev.Committer = committer.Name;
      this->Rev.CommitterEMail = committer.EMail;
      this->Rev.CommitDate = this->FormatDateTime(committer);
      }
    }

  void DoBodyLine()
    {
    // Commit log lines are indented by 4 spaces.
    if(this->Line.size() >= 4)
      {
      this->Rev.Log += this->Line.substr(4);
      }
    this->Rev.Log += "\n";
    }

  std::string FormatDateTime(Person const& person)
    {
    // Convert the time to a human-readable format that is also easy
    // to machine-parse: "CCYY-MM-DD hh:mm:ss".
    time_t seconds = static_cast<time_t>(person.Time);
    struct tm* t = gmtime(&seconds);
    char dt[1024];
    sprintf(dt, "%04d-%02d-%02d %02d:%02d:%02d",
            t->tm_year+1900, t->tm_mon+1, t->tm_mday,
            t->tm_hour, t->tm_min, t->tm_sec);
    std::string out = dt;

    // Add the time-zone field "+zone" or "-zone".
    char tz[32];
    if(person.TimeZone >= 0)
      {
      sprintf(tz, " +%04ld", person.TimeZone);
      }
    else
      {
      sprintf(tz, " -%04ld", -person.TimeZone);
      }
    out += tz;
    return out;
    }
};

char const cmCTestGIT::CommitParser::SectionSep[SectionCount] =
{'\n', '\n', '\0'};

//----------------------------------------------------------------------------
void cmCTestGIT::LoadRevisions()
{
  // Use 'git rev-list ... | git diff-tree ...' to get revisions.
  std::string range = this->OldRevision + ".." + this->NewRevision;
  const char* git = this->CommandLineTool.c_str();
  const char* git_rev_list[] =
    {git, "rev-list", "--reverse", range.c_str(), "--", 0};
  const char* git_diff_tree[] =
    {git, "diff-tree", "--stdin", "--always", "-z", "-r", "--pretty=raw",
     "--encoding=utf-8", 0};
  this->Log << this->ComputeCommandLine(git_rev_list) << " | "
            << this->ComputeCommandLine(git_diff_tree) << "\n";

  cmsysProcess* cp = cmsysProcess_New();
  cmsysProcess_AddCommand(cp, git_rev_list);
  cmsysProcess_AddCommand(cp, git_diff_tree);
  cmsysProcess_SetWorkingDirectory(cp, this->SourceDirectory.c_str());

  CommitParser out(this, "dt-out> ");
  OutputLogger err(this->Log, "dt-err> ");
  this->RunProcess(cp, &out, &err);

  // Send one extra zero-byte to terminate the last record.
  out.Process("", 1);

  cmsysProcess_Delete(cp);
}

//----------------------------------------------------------------------------
void cmCTestGIT::LoadModifications()
{
  const char* git = this->CommandLineTool.c_str();

  // Use 'git update-index' to refresh the index w.r.t. the work tree.
  const char* git_update_index[] = {git, "update-index", "--refresh", 0};
  OutputLogger ui_out(this->Log, "ui-out> ");
  OutputLogger ui_err(this->Log, "ui-err> ");
  this->RunChild(git_update_index, &ui_out, &ui_err);

  // Use 'git diff-index' to get modified files.
  const char* git_diff_index[] = {git, "diff-index", "-z", "HEAD", "--", 0};
  DiffParser out(this, "di-out> ");
  OutputLogger err(this->Log, "di-err> ");
  this->RunChild(git_diff_index, &out, &err);

  for(std::vector<Change>::const_iterator ci = out.Changes.begin();
      ci != out.Changes.end(); ++ci)
    {
    this->DoModification(PathModified, ci->Path);
    }
}
