| Attached Files |   patch-cdash.patch [^] (1,685 bytes) 2008-11-28 00:25 [Show Content] [Hide Content]diff -r 98d9ec569518 common.php
--- a/common.php	Fri Nov 28 11:16:01 2008 +0800
+++ b/common.php	Fri Nov 28 13:19:03 2008 +0800
@@ -2430,6 +2430,20 @@
   return make_cdash_url($diff_url);
 }
 
+/** Return the hgweb URL */
+function get_hgweb_diff_url($projecturl, $directory, $file, $revision)
+{
+  if($revision != '')
+    {
+      $diff_url = $projecturl."/diff/".$revision."/".($directory ? ("/".$directory) : "")."/".$file;
+    }
+  else
+    {
+      $diff_url = $projecturl."/file/tip/".($directory ? ("/".$directory) : "")."/".$file;
+    }
+  return make_cdash_url($diff_url);
+}
+
 /** Get the diff url based on the type of viewer */
 function get_diff_url($projectid,$projecturl, $directory, $file, $revision='')
 {
@@ -2468,6 +2482,10 @@
   elseif($project_array["cvsviewertype"] == "loggerhead")
     {
     return get_loggerhead_diff_url($projecturl, $directory, $file, $revision);
+    }
+  elseif($project_array["cvsviewertype"] == "hgweb")
+    {
+    return get_hgweb_diff_url($projecturl, $directory, $file, $revision);
     }
   else // default is viewcvs
     {
diff -r 98d9ec569518 createProject.php
--- a/createProject.php	Fri Nov 28 11:16:01 2008 +0800
+++ b/createProject.php	Fri Nov 28 13:19:03 2008 +0800
@@ -544,6 +544,7 @@
 $xml .= AddCVSViewer("viewvc1.1","ViewVC1.1",$project_array['cvsviewertype']);
 $xml .= AddCVSViewer("websvn","WebSVN",$project_array['cvsviewertype']);
 $xml .= AddCVSViewer("loggerhead","Loggerhead",$project_array['cvsviewertype']);
+$xml .= AddCVSViewer("hgweb","hgweb",$project_array['cvsviewertype']);
  
 $xml .= add_XML_value("nrepositories",$nRepositories); // should be at the end
   
 
  patch-cmake.patch.gz [^] (8,135 bytes) 2008-11-28 00:26 
  patch-cmake.patch [^] (35,820 bytes) 2009-06-04 21:26 [Show Content] [Hide Content]diff -r 08cb397f38c6 Modules/CTest.cmake
--- Modules/CTest.cmake.orig	Thu Nov 20 10:57:36 2008 +0800
+++ Modules/CTest.cmake	Tue Nov 25 10:59:41 2008 +0800
@@ -104,6 +104,8 @@
   SET(CVS_UPDATE_OPTIONS "-d -A -P" CACHE STRING 
     "Options passed to the cvs update command.")
   FIND_PROGRAM(SVNCOMMAND svn)
+  FIND_PROGRAM(HGCOMMAND hg)
+
 
   IF(NOT UPDATE_TYPE)
     IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CVS")
@@ -111,6 +113,10 @@
     ELSE(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CVS")
       IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn")
         SET(UPDATE_TYPE svn)
+      ELSE(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn")
+        IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.hg")
+          SET(UPDATE_TYPE hg)
+        ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.hg")
       ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn")
     ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CVS")
   ENDIF(NOT UPDATE_TYPE)
@@ -118,7 +124,7 @@
   IF(NOT UPDATE_TYPE)
     IF(NOT __CTEST_UPDATE_TYPE_COMPLAINED)
       SET(__CTEST_UPDATE_TYPE_COMPLAINED 1 CACHE INTERNAL "Already complained about update type.")
-      MESSAGE(STATUS "CTest cannot determine repository type. Please set UPDATE_TYPE to 'cvs' or 'svn'. CTest update will not work.")
+      MESSAGE(STATUS "CTest cannot determine repository type. Please set UPDATE_TYPE to 'cvs', 'svn' or 'hg'. CTest update will not work.")
     ENDIF(NOT __CTEST_UPDATE_TYPE_COMPLAINED)
   ENDIF(NOT UPDATE_TYPE)
 
@@ -129,6 +135,11 @@
     IF(UPDATE_TYPE MATCHES "[Ss][Vv][Nn]")
       SET(UPDATE_COMMAND "${SVNCOMMAND}")
       SET(UPDATE_OPTIONS "${SVN_UPDATE_OPTIONS}")
+     ELSE(UPDATE_TYPE MATCHES "[Ss][Vv][Nn]")
+       IF(UPDATE_TYPE MATCHES "[Hh][Gg]")
+         SET(UPDATE_COMMAND "${HGCOMMAND}")
+         SET(UPDATE_OPTIONS "${HG_UPDATE_OPTIONS}")
+       ENDIF(UPDATE_TYPE MATCHES "[Hh][Gg]")
     ENDIF(UPDATE_TYPE MATCHES "[Ss][Vv][Nn]")
   ENDIF(UPDATE_TYPE MATCHES "[Cc][Vv][Ss]")
 
@@ -194,8 +205,10 @@
     COVERAGE_COMMAND
     CVSCOMMAND
     SVNCOMMAND
+    HGCOMMAND
     CVS_UPDATE_OPTIONS
     SVN_UPDATE_OPTIONS
+    HG_UPDATE_OPTIONS
     MAKECOMMAND 
     MEMORYCHECK_COMMAND
     MEMORYCHECK_SUPPRESSIONS_FILE
diff -r 08cb397f38c6 Modules/DartConfiguration.tcl.in
--- Modules/DartConfiguration.tcl.in.orig	Thu Nov 20 10:57:36 2008 +0800
+++ Modules/DartConfiguration.tcl.in	Tue Nov 25 10:59:41 2008 +0800
@@ -23,6 +23,7 @@
 DropMethod: @DROP_METHOD@
 TriggerSite: @TRIGGER_SITE@
 ScpCommand: @SCPCOMMAND@
+NightlyIdentLocation: @CTEST_NIGHTLY_IDENT_LOCATION@
 
 # Dashboard start time
 NightlyStartTime: @NIGHTLY_START_TIME@
@@ -39,6 +40,10 @@
 # Subversion options
 SVNCommand: @SVNCOMMAND@
 SVNUpdateOptions: @SVN_UPDATE_OPTIONS@
+
+# Mercurial options
+HGCommand: @HGCOMMAND@
+HGUpdateOptions: @HG_UPDATE_OPTIONS@
 
 # Generic update command
 UpdateCommand: @UPDATE_COMMAND@
diff -r 08cb397f38c6 Source/CTest/cmCTestUpdateCommand.cxx
--- Source/CTest/cmCTestUpdateCommand.cxx.orig	Thu Nov 20 10:57:36 2008 +0800
+++ Source/CTest/cmCTestUpdateCommand.cxx	Tue Nov 25 10:59:41 2008 +0800
@@ -48,6 +48,10 @@
     "SVNCommand", "CTEST_SVN_COMMAND");
   this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
     "SVNUpdateOptions", "CTEST_SVN_UPDATE_OPTIONS");
+  this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
+    "HGCommand", "CTEST_HG_COMMAND");
+  this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
+    "HGUpdateOptions", "CTEST_HG_UPDATE_OPTIONS");
 
   const char* initialCheckoutCommand
     = this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND");
diff -r 08cb397f38c6 Source/CTest/cmCTestUpdateHandler.cxx
--- Source/CTest/cmCTestUpdateHandler.cxx.orig	Thu Nov 20 10:57:36 2008 +0800
+++ Source/CTest/cmCTestUpdateHandler.cxx	Tue Nov 25 10:59:41 2008 +0800
@@ -29,6 +29,9 @@
 //#include <cmsys/RegularExpression.hxx>
 #include <cmsys/Process.h>
 
+// For curl retrieval (nightly ident)
+#include "cm_curl.h"
+
 // used for sleep
 #ifdef _WIN32
 #include "windows.h"
@@ -43,7 +46,8 @@
 {
   "Unknown",
   "CVS",
-  "SVN"
+  "SVN",
+  "HG"
 };
 
 static const char* cmCTestUpdateHandlerUpdateToString(int type)
@@ -181,6 +185,139 @@
 //----------------------------------------------------------------------
 
 //----------------------------------------------------------------------
+//**********************************************************************
+class cmCTestUpdateHandlerHGXMLParser : public cmXMLParser
+{
+public:
+  struct t_CommitLog
+    {
+    std::string Revision;
+    std::string Author;
+    std::string Email;
+    std::string Date;
+    std::string Message;
+    };
+  cmCTestUpdateHandlerHGXMLParser(cmCTestUpdateHandler* up)
+    : cmXMLParser(), UpdateHandler(up), MinRevision("000000000000"), MaxRevision("000000000000")
+    {
+    }
+    
+    
+  int Parse(const char* str)
+    {
+    this->MinRevision = "000000000000";
+    this->MaxRevision = "000000000000";
+    cmOStringStream correctString;
+    correctString << "<log>\n";
+    correctString << str;
+    correctString << "</log>\n";
+    int res = this->cmXMLParser::Parse(correctString.str().c_str());
+    if ( this->MinRevision == "000000000000" || this->MaxRevision == "000000000000" )
+      {
+      return 0;
+      }
+    return res;
+    }
+
+  typedef std::vector<t_CommitLog> t_VectorOfCommits;
+
+  t_VectorOfCommits* GetCommits() { return &this->Commits; }
+  std::string GetMinRevision() { return this->MinRevision; }
+  std::string GetMaxRevision() { return this->MaxRevision; }
+
+protected:
+  void StartElement(const char* name, const char** atts)
+    {
+    if ( strcmp(name, "logentry") == 0 )
+      {
+      this->CommitLog = t_CommitLog();
+      const char* rev = this->FindAttribute(atts, "revision");
+      if ( rev)
+        {
+        this->CommitLog.Revision = rev;
+        //revision are assumed to be in chronological order
+        if ( this->MinRevision == "000000000000" )
+          {
+          this->MinRevision = this->CommitLog.Revision;
+          }
+        this->MaxRevision = this->CommitLog.Revision;
+        }
+      }
+    this->CharacterData.erase(
+      this->CharacterData.begin(), this->CharacterData.end());
+    }
+  void EndElement(const char* name)
+    {
+    if ( strcmp(name, "logentry") == 0 )
+      {
+      cmCTestLog(this->UpdateHandler->GetCTestInstance(),
+        HANDLER_VERBOSE_OUTPUT,
+        "\tRevision: " << this->CommitLog.Revision<< std::endl
+        << "\tAuthor:   " << this->CommitLog.Author.c_str() << std::endl
+        << "\tEmail:   " << this->CommitLog.Email.c_str() << std::endl
+        << "\tDate:     " << this->CommitLog.Date.c_str() << std::endl
+        << "\tMessage:  " << this->CommitLog.Message.c_str() << std::endl);
+      this->Commits.push_back(this->CommitLog);
+      }
+    else if ( strcmp(name, "author") == 0 )
+      {
+      this->CommitLog.Author.assign(&(*(this->CharacterData.begin())),
+        this->CharacterData.size());
+      }
+    else if ( strcmp(name, "email") == 0 )
+      {
+      this->CommitLog.Email.assign(&(*(this->CharacterData.begin())),
+        this->CharacterData.size());
+      }  
+    else if ( strcmp(name, "date") == 0 )
+      {
+      this->CommitLog.Date.assign(&(*(this->CharacterData.begin())),
+        this->CharacterData.size());
+      }
+    else if ( strcmp(name, "msg") == 0 )
+      {
+      this->CommitLog.Message.assign(&(*(this->CharacterData.begin())),
+        this->CharacterData.size());
+      }
+    this->CharacterData.erase(this->CharacterData.begin(),
+      this->CharacterData.end());
+    }
+  void CharacterDataHandler(const char* data, int length)
+    {
+    this->CharacterData.insert(this->CharacterData.end(), data, data+length);
+    }
+  const char* FindAttribute( const char** atts, const char* attribute )
+    {
+    if ( !atts || !attribute )
+      {
+      return 0;
+      }
+    const char **atr = atts;
+    while ( *atr && **atr && **(atr+1) )
+      {
+      if ( strcmp(*atr, attribute) == 0 )
+        {
+        return *(atr+1);
+        }
+      atr+=2;
+      }
+    return 0;
+    }
+
+private:
+  std::vector<char> CharacterData;
+  cmCTestUpdateHandler* UpdateHandler;
+  t_CommitLog CommitLog;
+
+  t_VectorOfCommits Commits;
+  std::string MinRevision;
+  std::string MaxRevision;
+};
+//**********************************************************************
+//----------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------
 cmCTestUpdateHandler::cmCTestUpdateHandler()
 {
 }
@@ -208,6 +345,10 @@
       {
       return cmCTestUpdateHandler::e_SVN;
       }
+    if ( stype.find("hg") != std::string::npos )
+      {
+        return cmCTestUpdateHandler::e_HG;
+      } 
     }
   else
     {
@@ -221,6 +362,10 @@
     if ( stype.find("svn") != std::string::npos )
       {
       return cmCTestUpdateHandler::e_SVN;
+      }
+    if ( stype.find("hg") != std::string::npos )
+      {
+        return cmCTestUpdateHandler::e_HG;
       }
     }
   std::string sourceDirectory = this->GetOption("SourceDirectory");
@@ -237,8 +382,122 @@
     {
     return cmCTestUpdateHandler::e_CVS;
     }
+  sourceDirectory = this->GetOption("SourceDirectory");
+  sourceDirectory += "/.hg";
+  if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
+    {
+      return cmCTestUpdateHandler::e_HG;
+    }
   return cmCTestUpdateHandler::e_UNKNOWN;
 }
+
+
+typedef std::vector<char> cmCTestUpdateHandlerVectorOfChar;
+
+static size_t
+cmCTestUpdateHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
+  void *data)
+{
+  register int realsize = (int)(size * nmemb);
+
+  cmCTestUpdateHandlerVectorOfChar *vec
+    = static_cast<cmCTestUpdateHandlerVectorOfChar*>(data);
+  const char* chPtr = static_cast<char*>(ptr);
+  vec->insert(vec->end(), chPtr, chPtr + realsize);
+
+  return realsize;
+}
+
+//----------------------------------------------------------------------
+std::string cmCTestUpdateHandler::RetrieveNightlyIdentifier()
+{
+  //TODO: only retrieving with http method for now. Ideally should be integrated
+  // with CDash
+  CURL *curl;
+  CURLcode res;
+  char error_buffer[1024];
+  
+  /* In windows, this will init the winsock stuff */
+  ::curl_global_init(CURL_GLOBAL_ALL);
+  
+  std::string url = "";
+  if ( !this->CTest->GetCTestConfiguration("NightlyIdentLocation").size() > 0 )
+    {
+       cmCTestLog(this->CTest, ERROR_MESSAGE,
+      "Cannot find NightlyIdentLocation information (Mercurial)"
+      << std::endl);
+    }
+  else
+  {
+    url += this->CTest->GetCTestConfiguration("NightlyIdentLocation");
+  }
+    
+  /* get a curl handle */
+  curl = curl_easy_init();  
+  
+  cmStdString turl = url;
+  
+//   char data[12];
+  std::string data;
+  
+  if(curl)
+    {
+    ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+
+    // and give curl the buffer for errors
+    ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
+      
+    ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+        cmCTestUpdateHandlerWriteMemoryCallback);
+    
+    /* we pass our 'chunk' struct to the callback function */
+    cmCTestUpdateHandlerVectorOfChar chunk;
+    cmCTestUpdateHandlerVectorOfChar chunkDebug;
+    ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
+    ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
+    
+    
+    curl_easy_setopt(curl, CURLOPT_URL, turl.c_str());
+    
+    
+    if ( curl_easy_perform(curl) )
+      {
+      cmCTestLog(this->CTest, ERROR_MESSAGE, "   Error when triggering: "
+        << turl.c_str() << std::endl);
+      cmCTestLog(this->CTest, ERROR_MESSAGE, "   Error message was: "
+        << error_buffer << std::endl);
+
+      if(chunk.size())
+        {
+        cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
+                    << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+                    << std::endl);
+        }
+      ::curl_easy_cleanup(curl);
+      ::curl_global_cleanup();
+      return false;
+      }
+      
+    ::curl_easy_cleanup(curl);
+    ::curl_global_cleanup();
+    
+    if (chunk.size() != 12)
+      {
+      cmCTestLog(this->CTest, HANDLER_OUTPUT,
+        "   The retrieve nightly ident size is incorrect: " << chunk.size()
+        << std::endl);
+      }
+    else
+      {
+        
+      data.append(chunk.begin(),chunk.end());
+      return data;
+      }
+    
+    }
+  return "";
+}
+
 
 //----------------------------------------------------------------------
 //clearly it would be nice if this were broken up into a few smaller
@@ -340,10 +599,18 @@
       updateCommand = this->CTest->GetCTestConfiguration("SVNCommand");
       if ( updateCommand.empty() )
         {
-        cmCTestLog(this->CTest, ERROR_MESSAGE,
-          "Cannot find CVSCommand, SVNCommand, or UpdateCommand key in the "
-          "DartConfiguration.tcl" << std::endl);
-        return -1;
+        updateCommand = this->CTest->GetCTestConfiguration("HGCommand");
+        if ( updateCommand.empty() )
+          {
+          cmCTestLog(this->CTest, ERROR_MESSAGE,
+            "Cannot find CVSCommand, SVNCommand, HGCommand or UpdateCommand key in the "
+            "DartConfiguration.tcl" << std::endl);
+          return -1;
+          }
+        else
+          {
+            updateType = e_HG;
+          }  
         }
       else
         {
@@ -382,6 +649,9 @@
     case cmCTestUpdateHandler::e_SVN:
       updateOptions = this->CTest->GetCTestConfiguration("SVNUpdateOptions");
       break;
+    case cmCTestUpdateHandler::e_HG:
+      updateOptions = this->CTest->GetCTestConfiguration("HGUpdateOptions");
+      break;
       }
     }
 
@@ -411,6 +681,20 @@
     case cmCTestUpdateHandler::e_SVN:
       extra_update_opts += "-r \"{" + today_update_date +" +0000}\"";
       break;
+    // 
+    // Date is not enough to identify the mercurial nightly. History is not linear
+    // so date is ambiguous. Nightly version should be specified by hash key.
+    // Hash key is now retrieve on a specific location given by
+    // CTEST_NIGHTLY_IDENT_LOCATION in the configuration file.
+    // Ideally, this should be retrive from the Dart/CDash server.
+    case cmCTestUpdateHandler::e_HG:
+//       extra_update_opts += "-d \"<" + today_update_date +"\"";
+      std::string nightlyVersion = RetrieveNightlyIdentifier();
+      extra_update_opts += "-r "+nightlyVersion;
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "   HG nightly revision "
+        << extra_update_opts.c_str()
+        << std::endl;);
+      break;
       }
     }
 
@@ -428,6 +712,12 @@
   case cmCTestUpdateHandler::e_SVN:
     command = updateCommand + " cleanup";
     break;
+  case cmCTestUpdateHandler::e_HG:
+    //TODO not sure which command to use for hg: purge -f might be to
+    // dangerous but verify seems to be for low level verifications.
+//     command = updateCommand + " purge -f";
+//     command = updateCommand + " verify";
+    break;  
     }
 
   //
@@ -470,6 +760,9 @@
   case cmCTestUpdateHandler::e_SVN:
     command = updateCommand + " info";
     break;
+  case cmCTestUpdateHandler::e_HG:
+    command = updateCommand + " identify";
+    break;
     }
 
   // CVS variables
@@ -477,6 +770,10 @@
   int svn_current_revision = 0;
   int svn_latest_revision = 0;
   int svn_use_status = 0;
+  // HG variables
+  std::string hg_current_revision = "000000000000";
+  std::string hg_latest_revision  = "000000000000";
+  int hg_use_status = 0;
 
   //
   // Get initial repository information if that is possible. With subversion,
@@ -520,6 +817,25 @@
             }
           }
         break;
+      case cmCTestUpdateHandler::e_HG:
+          {
+	  //hg identify output can be in the form of
+	  //4447acec586f tip
+	  //9d5718f9d604
+	  //9d5718f9d604+
+          cmsys::RegularExpression current_revision_regex(
+              "([0-9a-f]+)\\+*( [a-z0-9])*");
+          if ( current_revision_regex.find(goutput.c_str()) )
+            {
+            std::string currentRevisionString
+                = current_revision_regex.match(1);
+            hg_current_revision = currentRevisionString.c_str();
+            cmCTestLog(this->CTest, HANDLER_OUTPUT,
+                        "   Old revision of repository is: " << hg_current_revision
+                            << std::endl);
+            }
+          }
+        break;
         }
       }
     else
@@ -550,6 +866,7 @@
   if ( !this->CTest->GetShowOnly() )
     {
     command = "";
+    std::string commandExtra = "";
     switch( updateType )
       {
     case cmCTestUpdateHandler::e_CVS:
@@ -580,6 +897,51 @@
         ofs << "  Command: " << command.c_str() << std::endl;
         res = this->CTest->RunCommand(command.c_str(), &partialOutput,
           &errors, &retVal, sourceDirectory, 0 /*this->TimeOut*/);
+        ofs << "  Output: " << partialOutput.c_str() << std::endl;
+        ofs << "  Errors: " << errors.c_str() << std::endl;
+        goutput += partialOutput;
+        res = res && res1;
+        ofs << "  Total output of update: " << goutput.c_str() << std::endl;
+        }
+    case cmCTestUpdateHandler::e_HG:
+        {
+        //pull
+        std::string partialOutput;
+        command = updateCommand + " pull -v ";
+        ofs << "* Pull Changes: " << std::endl;
+        ofs << "  Command: " << command.c_str() << std::endl;
+        bool res1 = this->CTest->RunCommand(command.c_str(), &partialOutput,
+                                            &errors,
+                                            &retVal, sourceDirectory, 0 /*this->TimeOut*/);
+        ofs << "  Output: " << partialOutput.c_str() << std::endl;
+        ofs << "  Errors: " << errors.c_str() << std::endl;
+        goutput = partialOutput;
+        //update
+        command = updateCommand + " update -v " + updateOptions +
+            " " + extra_update_opts;
+        ofs << "* Update repository: " << std::endl;
+        ofs << "  Command: " << command.c_str() << std::endl;
+        res = this->CTest->RunCommand(command.c_str(), &partialOutput,
+                                      &errors, &retVal, sourceDirectory, 0 /*this->TimeOut*/);
+        ofs << "  Output: " << partialOutput.c_str() << std::endl;
+        ofs << "  Errors: " << errors.c_str() << std::endl;
+        goutput += partialOutput;
+        //identify new version
+        commandExtra = updateCommand + " identify ";
+        ofs << "* Identify repository: " << std::endl;
+        ofs << "  Command: " << commandExtra.c_str() << std::endl;
+        res = this->CTest->RunCommand(commandExtra.c_str(), &partialOutput,
+                                      &errors, &retVal, sourceDirectory, 0 /*this->TimeOut*/);
+        ofs << "  Output: " << partialOutput.c_str() << std::endl;
+        ofs << "  Errors: " << errors.c_str() << std::endl;
+        goutput += "changeset:   ";
+        goutput += partialOutput;
+        //TODO: not too sure on how to adapt svn status to hg
+        commandExtra = updateCommand + " log --removed -l 1 --template '00 {node|short} \"{author|person}\" {author|email} {files}\n' ";
+        ofs << "* Status repository: " << std::endl;
+        ofs << "  Command: " << commandExtra.c_str() << std::endl;
+        res = this->CTest->RunCommand(commandExtra.c_str(), &partialOutput,
+                                      &errors, &retVal, sourceDirectory, 0 /*this->TimeOut*/);
         ofs << "  Output: " << partialOutput.c_str() << std::endl;
         ofs << "  Errors: " << errors.c_str() << std::endl;
         goutput += partialOutput;
@@ -638,10 +1000,21 @@
     "^ *([0-9]+)  *([0-9]+)  *([^ ]+)  *([^ ][^\t\r\n]*)[ \t\r\n]*$");
   cmsys::RegularExpression svn_latest_revision_regex(
     "(Updated to|At) revision ([0-9]+)\\.");
+  
+  // HG style regular expressions
+  cmsys::RegularExpression hg_status_line_regex(
+    "^ *([0-9a-f]+)  *([0-9a-f]+)  *([^ ]+)  *([^ ]+) *([^ ][^\t\r\n]*)[ \t\r\n]*$");//TODO check if the adaptation is correct to catch the email
+  cmsys::RegularExpression hg_latest_revision_regex(
+      "changeset:   ([0-9a-f]+)\\+*( [a-z0-9])*");
 
-  cmsys::RegularExpression file_removed_line(
-    "cvs update: `(.*)' is no longer in the repository");
-  cmsys::RegularExpression file_update_line("([A-Z])  *(.*)");
+
+  cmsys::RegularExpression file_removed_line_hg = cmsys::RegularExpression("(removing) (.*)");
+  cmsys::RegularExpression file_update_line_hg = cmsys::RegularExpression("(getting) (.*)");
+
+  cmsys::RegularExpression file_removed_line = cmsys::RegularExpression(
+      "cvs update: `(.*)' is no longer in the repository");
+  cmsys::RegularExpression file_update_line = cmsys::RegularExpression("([A-Z])  *(.*)");
+
   std::string current_path = "<no-path>";
   bool first_file = true;
 
@@ -675,15 +1048,57 @@
         << std::endl);
       }
     }
-
+  // In HG (mercurial), get the latest revision
+    if ( updateType == cmCTestUpdateHandler::e_HG )
+    {
+      for ( cc= 0; cc < lines.size(); cc ++ )
+      {
+        const char* line = lines[cc].c_str();
+        if ( hg_latest_revision_regex.find(line) )
+        {
+          hg_latest_revision = hg_latest_revision_regex.match(1).c_str();
+        }
+      }
+      if ( hg_latest_revision == "0000000000000" )
+      {
+        cmCTestLog(this->CTest, ERROR_MESSAGE,
+                   "Problem determining the current "
+                       "revision of the repository from output:" << std::endl
+                       << goutput.c_str() << std::endl);
+      }
+      else
+      {
+        cmCTestLog(this->CTest, HANDLER_OUTPUT,
+                   "   Current revision of repository is: " << hg_latest_revision
+                       << std::endl);
+      }
+    }
+    
   cmCTestLog(this->CTest, HANDLER_OUTPUT,
     "   Gathering version information (each . represents one updated file):"
     << std::endl);
   int file_count = 0;
   std::string removed_line;
+
   for ( cc= 0; cc < lines.size(); cc ++ )
     {
     const char* line = lines[cc].c_str();
+
+    //Adapt hg output to SVN/CVS format
+    if (updateType == cmCTestUpdateHandler::e_HG)
+      {
+      if (file_update_line_hg.find(line))
+	{
+	removed_line = "U " + file_update_line_hg.match(2);
+        line = removed_line.c_str();
+	}
+      if (file_removed_line_hg.find(line))
+	{
+	removed_line = "D " + file_removed_line_hg.match(2);
+        line = removed_line.c_str();
+	}
+      }
+    
     if ( file_removed_line.find(line) )
       {
       removed_line = "D " + file_removed_line.match(1);
@@ -699,6 +1114,7 @@
       std::string upChar = file_update_line.match(1);
       std::string upFile = file_update_line.match(2);
       char mod = upChar[0];
+
       bool modifiedOrConflict = false;
       if ( mod == 'X')
         {
@@ -738,6 +1154,25 @@
               " status  --verbose \"" + file + "\"";
             svn_use_status = 1;
             }
+          break;
+        case cmCTestUpdateHandler::e_HG:
+          if ( hg_latest_revision != "0000000000000" &&
+            hg_latest_revision != hg_current_revision )
+            {
+            std::string hgXMLTemplate = "'<logentry\n   revision=\"{node|short}\">\n<author>{author|person}</author>\n<email>{author|email}</email>\n<date>{date|isodate}</date>\n<msg>{desc}</msg>\n</logentry>\n'";
+            cmOStringStream logCommandStream;
+            logCommandStream << updateCommand << " log --removed -r "
+              << hg_current_revision << ":" << hg_latest_revision
+              << " --template " << hgXMLTemplate << " \"" << file << "\"";
+            logcommand = logCommandStream.str();
+            }
+          else
+            {
+            logcommand = updateCommand +
+              " log -l 1 --template '00 {node|short} \"{author|person}\" {author|email} {files}\n' \"" + file + "\"";
+            hg_use_status = 1;
+            }
+
           break;
           }
         cmCTestLog(this->CTest, DEBUG, "Do log: " << logcommand << std::endl);
@@ -894,6 +1329,78 @@
                   mRevStream << minrev;
                   srevision2 = mRevStream.str();
                   sauthor2 = it->Author;
+                  comment2 = it->Message;
+                  sdate2 = it->Date;
+                  }
+                }
+              }
+            }
+          }
+          else if ( updateType == cmCTestUpdateHandler::e_HG )
+          {
+          if ( hg_use_status )
+            {
+            cmOStringStream str;
+            str << hg_current_revision;
+            srevision1 = str.str();
+            if (!hg_status_line_regex.find(output))
+              {
+              cmCTestLog(this->CTest, ERROR_MESSAGE,
+                "Bad output from HG status command: " << output
+                << std::endl);
+              }
+            else if ( hg_status_line_regex.match(5) != file )
+              {
+              cmCTestLog(this->CTest, ERROR_MESSAGE,
+                "Bad output from HG status command. "
+                "The file name returned: \""
+                << hg_status_line_regex.match(5)
+                << "\" was different than the file specified: \"" << file
+                << "\"" << std::endl);
+              }
+            else
+              {
+              srevision1 = hg_status_line_regex.match(2);
+              std::string latest_revision = 
+                hg_status_line_regex.match(2).c_str();
+              if ( hg_current_revision != latest_revision )
+                {
+                srevision2 = str.str();
+                }
+              sauthor1 = hg_status_line_regex.match(3);
+              semail1 = hg_status_line_regex.match(4);
+              }
+            }
+          else
+            {
+            cmCTestUpdateHandlerHGXMLParser parser(this);
+          if ( parser.Parse(output.c_str()) )
+              {
+              std::string minrev = parser.GetMinRevision();
+              std::string maxrev = parser.GetMaxRevision();
+              cmCTestUpdateHandlerHGXMLParser::
+                t_VectorOfCommits::iterator it;
+              for ( it = parser.GetCommits()->begin();
+                it != parser.GetCommits()->end();
+                ++ it )
+                {
+                if ( it->Revision == maxrev )
+                  {
+                  cmOStringStream mRevStream;
+                  mRevStream << maxrev;
+                  srevision1 = mRevStream.str();
+                  sauthor1 = it->Author;
+                  semail1 = it->Email;
+                  comment1 = it->Message;
+                  sdate1 = it->Date;
+                  }
+                else if ( it->Revision == minrev )
+                  {
+                  cmOStringStream mRevStream;
+                  mRevStream << minrev;
+                  srevision2 = mRevStream.str();
+                  sauthor2 = it->Author;
+                  semail2 = it->Email;
                   comment2 = it->Message;
                   sdate2 = it->Date;
                   }
diff -r 08cb397f38c6 Source/CTest/cmCTestUpdateHandler.h
--- Source/CTest/cmCTestUpdateHandler.h.orig	Thu Nov 20 10:57:36 2008 +0800
+++ Source/CTest/cmCTestUpdateHandler.h	Tue Nov 25 10:59:41 2008 +0800
@@ -46,6 +46,7 @@
     e_UNKNOWN = 0,
     e_CVS,
     e_SVN,
+    e_HG,
     e_LAST
   };
 
@@ -64,6 +65,10 @@
 
   // Determine the type of version control
   int DetermineType(const char* cmd, const char* type);
+  
+  // Retrieve the nightly identifier (for mercurial)
+  std::string RetrieveNightlyIdentifier();
+  
 };
 
 #if defined(__sgi) && !defined(__GNUC__)
diff -r 08cb397f38c6 Source/cmCTest.cxx
--- Source/cmCTest.cxx.orig	Thu Nov 20 10:57:36 2008 +0800
+++ Source/cmCTest.cxx	Tue Nov 25 10:59:41 2008 +0800
@@ -485,6 +485,9 @@
   this->SetCTestConfigurationFromCMakeVariable(mf, "Site", "CTEST_SITE");
   this->SetCTestConfigurationFromCMakeVariable(mf, "BuildName",
     "CTEST_BUILD_NAME");
+  this->SetCTestConfigurationFromCMakeVariable(mf, "NightlyIdentLocation",
+    "CTEST_NIGHTLY_IDENT_LOCATION");
+
   const char* dartVersion = mf->GetDefinition("CTEST_DART_SERVER_VERSION");
   if ( dartVersion )
     {
diff -r 08cb397f38c6 Tests/CTestTest3/test.cmake.in
--- Tests/CTestTest3/test.cmake.in.orig	Thu Nov 20 10:57:36 2008 +0800
+++ Tests/CTestTest3/test.cmake.in	Tue Nov 25 10:59:41 2008 +0800
@@ -8,54 +8,60 @@
   MESSAGE("###################################################")
 ENDMACRO(PROJECT_START)
 
-# Project 1
-PROJECT_START("KWSys from CVS")
+SET(cvscommand "@CVSCOMMAND@")
+#set(cvscommand FALSE) # turn this off until end of testing
+IF(cvscommand)
+  # Project 1
+  PROJECT_START("KWSys from CVS")
+  
+  # Settings:
+  SET(CTEST_DASHBOARD_ROOT                "@CMake_BINARY_DIR@/Tests/CTestTest3")
+  SET(CTEST_SITE                          "@SITE@")
+  SET(CTEST_BUILD_NAME                    "KWSys-@BUILDNAME@-CTest3-CVS")
+  
+  # ---
+  SET(CTEST_SOURCE_DIRECTORY              "${CTEST_DASHBOARD_ROOT}/CVS/KWSys")
+  SET(CTEST_BINARY_DIRECTORY              "${CTEST_DASHBOARD_ROOT}/CVS/KWSysBin")
+  SET(CTEST_UPDATE_COMMAND                "@CVSCOMMAND@")
+  SET(CTEST_CMAKE_GENERATOR               "@CMAKE_GENERATOR@")
+  SET(CTEST_BUILD_CONFIGURATION           "$ENV{CMAKE_CONFIG_TYPE}")
+  SET(CTEST_MEMORYCHECK_COMMAND           "@MEMORYCHECK_COMMAND@")
+  SET(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "@MEMORYCHECK_SUPPRESSIONS_FILE@")
+  SET(CTEST_MEMORYCHECK_COMMAND_OPTIONS   "@MEMORYCHECK_COMMAND_OPTIONS@")
+  SET(CTEST_COVERAGE_COMMAND              "@COVERAGE_COMMAND@")
+  SET(CTEST_NOTES_FILES                   "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}")
+  SET(CTEST_CHECKOUT_COMMAND              "\"${CTEST_UPDATE_COMMAND}\" -q -z3 \"-d:pserver:anoncvs@www.cmake.org:/cvsroot/KWSys\" co -r CTest-Testing-Tag KWSys")
+  
+  CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY})
+  
+  FILE(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "
+  CMAKE_CXX_FLAGS:STRING=@CMAKE_CXX_FLAGS@
+  CMAKE_C_FLAGS:STRING=@CMAKE_C_FLAGS@
+  CMAKE_C_COMPILER:STRING=@CMAKE_C_COMPILER@
+  CMAKE_CXX_COMPILER:STRING=@CMAKE_CXX_COMPILER@
+  CMAKE_C_COMPILER_ARG1:STRING=@CMAKE_C_COMPILER_ARG1@
+  CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@
+  
+  # This one is needed for testing advanced ctest features
+  CTEST_TEST_KWSYS:BOOL=ON
+  ")
+  
+  SET(CTEST_CUSTOM_WARNING_MATCH CommandLineArguments)
+  
+  CTEST_START(Nightly)
+  CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}" RETURN_VALUE res)
+  CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_READ_CUSTOM_FILES("${CTEST_BINARY_DIRECTORY}")
+  CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_SUBMIT(RETURN_VALUE res)
+ELSE(cvscommand)
+  MESSAGE("Cannot find CVS command: ${cvscommand}")
+ENDIF(cvscommand)
 
-# Settings:
-SET(CTEST_DASHBOARD_ROOT                "@CMake_BINARY_DIR@/Tests/CTestTest3")
-SET(CTEST_SITE                          "@SITE@")
-SET(CTEST_BUILD_NAME                    "KWSys-@BUILDNAME@-CTest3-CVS")
-
-# ---
-SET(CTEST_SOURCE_DIRECTORY              "${CTEST_DASHBOARD_ROOT}/CVS/KWSys")
-SET(CTEST_BINARY_DIRECTORY              "${CTEST_DASHBOARD_ROOT}/CVS/KWSysBin")
-SET(CTEST_UPDATE_COMMAND                "@CVSCOMMAND@")
-SET(CTEST_CMAKE_GENERATOR               "@CMAKE_GENERATOR@")
-SET(CTEST_BUILD_CONFIGURATION           "$ENV{CMAKE_CONFIG_TYPE}")
-SET(CTEST_MEMORYCHECK_COMMAND           "@MEMORYCHECK_COMMAND@")
-SET(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "@MEMORYCHECK_SUPPRESSIONS_FILE@")
-SET(CTEST_MEMORYCHECK_COMMAND_OPTIONS   "@MEMORYCHECK_COMMAND_OPTIONS@")
-SET(CTEST_COVERAGE_COMMAND              "@COVERAGE_COMMAND@")
-SET(CTEST_NOTES_FILES                   "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}")
-SET(CTEST_CHECKOUT_COMMAND              "\"${CTEST_UPDATE_COMMAND}\" -q -z3 \"-d:pserver:anoncvs@www.cmake.org:/cvsroot/KWSys\" co -r CTest-Testing-Tag KWSys")
-
-CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY})
-
-FILE(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "
-CMAKE_CXX_FLAGS:STRING=@CMAKE_CXX_FLAGS@
-CMAKE_C_FLAGS:STRING=@CMAKE_C_FLAGS@
-CMAKE_C_COMPILER:STRING=@CMAKE_C_COMPILER@
-CMAKE_CXX_COMPILER:STRING=@CMAKE_CXX_COMPILER@
-CMAKE_C_COMPILER_ARG1:STRING=@CMAKE_C_COMPILER_ARG1@
-CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@
-
-# This one is needed for testing advanced ctest features
-CTEST_TEST_KWSYS:BOOL=ON
-")
-
-SET(CTEST_CUSTOM_WARNING_MATCH CommandLineArguments)
-
-CTEST_START(Nightly)
-CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}" RETURN_VALUE res)
-CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
-CTEST_READ_CUSTOM_FILES("${CTEST_BINARY_DIRECTORY}")
-CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
-CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
-CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
-CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
-CTEST_SUBMIT(RETURN_VALUE res)
-
-#SET(svncommand "@SVNCOMMAND@")
+SET(svncommand "@SVNCOMMAND@")
 set(svncommand FALSE) # turn this off until namic svn cmake is back
 IF(svncommand)
   # Project 2
@@ -105,3 +111,57 @@
 ELSE(svncommand)
   MESSAGE("Cannot find SVN command: ${svncommand}")
 ENDIF(svncommand)
+
+SET(hgcommand "@HGCOMMAND@")
+IF(hgcommand)
+# Project 3
+PROJECT_START("kwsys from hg")
+
+
+# Settings:
+  SET(CTEST_DASHBOARD_ROOT                "@CMake_BINARY_DIR@/Tests/CTestTest3")
+  SET(CTEST_SITE                          "@SITE@")
+  SET(CTEST_BUILD_NAME                    "OTB-@BUILDNAME@-CTest3-SVN")
+
+# ---
+  SET(CTEST_SOURCE_DIRECTORY              "${CTEST_DASHBOARD_ROOT}/HG/kwsys")
+  SET(CTEST_BINARY_DIRECTORY              "${CTEST_DASHBOARD_ROOT}/HG/kwsysBin")
+  SET(CTEST_UPDATE_COMMAND                "@HGCOMMAND@")
+  SET(CTEST_CMAKE_GENERATOR               "@CMAKE_GENERATOR@")
+  SET(CTEST_BUILD_CONFIGURATION           "$ENV{CMAKE_CONFIG_TYPE}")
+  SET(CTEST_MEMORYCHECK_COMMAND           "@MEMORYCHECK_COMMAND@")
+  SET(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "@MEMORYCHECK_SUPPRESSIONS_FILE@")
+  SET(CTEST_MEMORYCHECK_COMMAND_OPTIONS   "@MEMORYCHECK_COMMAND_OPTIONS@")
+  SET(CTEST_COVERAGE_COMMAND              "@COVERAGE_COMMAND@")
+  SET(CTEST_NOTES_FILES                   "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}")
+  SET(CTEST_CHECKOUT_COMMAND              "\"${CTEST_UPDATE_COMMAND}\" clone -r 6bca74edb696 \"/home/christop/opensource/kwsys\" ")
+
+# This definition is added compared to the cvs test (different source version?)
+  SET(CTEST_PROJECT_NAME "kwsys")
+
+  CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY})
+
+  FILE(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "
+  CMAKE_CXX_FLAGS:STRING=@CMAKE_CXX_FLAGS@
+  CMAKE_C_FLAGS:STRING=@CMAKE_C_FLAGS@
+  CMAKE_C_COMPILER:STRING=@CMAKE_C_COMPILER@
+  CMAKE_CXX_COMPILER:STRING=@CMAKE_CXX_COMPILER@
+  CMAKE_C_COMPILER_ARG1:STRING=@CMAKE_C_COMPILER_ARG1@
+  CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@
+
+# This one is needed for testing advanced ctest features
+  CTEST_TEST_KWSYS:BOOL=ON
+  ")
+
+  CTEST_START(Experimental)
+  CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}" RETURN_VALUE res)
+  CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+  CTEST_SUBMIT(RETURN_VALUE res)
+  
+ELSE(hgcommand)
+  MESSAGE("Cannot find HG command: ${hgcommand}")
+ENDIF(hgcommand)
 
  patch-cdash-2.6.4.patch.gz [^] (652 bytes) 2009-06-04 21:28 
  patch-cmake-2.6.4.patch.gz [^] (8,108 bytes) 2009-06-04 21:29 
  patch-cmake-CVS-after-refactoring-tmp.tgz [^] (7,561 bytes) 2009-07-10 05:41 |