/*============================================================================
  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 "cmAlgorithms.h"

#include <cmsys/RegularExpression.hxx>
#include <cmsys/Process.h>
#include <cmsys/FStream.hxx>

#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);
    }
  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<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
  for(std::vector<std::string>::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";
  cmsys::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(cmHasLiteralPrefix(this->Line.c_str(), "commit "))
      {
      this->Rev.Rev = this->Line.c_str()+7;
      }
    else if(cmHasLiteralPrefix(this->Line.c_str(), "author "))
      {
      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(cmHasLiteralPrefix(this->Line.c_str(), "committer "))
      {
      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);
    }
}
