Просмотр исходного кода

ENH: Several improvements with the way things are handled. Also, support multiple submited files

Andy Cedilnik 20 лет назад
Родитель
Сommit
1b578d3180

+ 1 - 0
Source/CMakeLists.txt

@@ -212,6 +212,7 @@ SET(CMTEST_SRCS cmCTest.cxx
   CTest/cmCTestCoverageHandler.cxx
   CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
   CTest/cmCTestGenericHandler.cxx
+  CTest/cmCTestHandlerCommand.cxx
   CTest/cmCTestMemCheckCommand.cxx
   CTest/cmCTestMemCheckHandler.cxx
   CTest/cmCTestRunScriptCommand.cxx

+ 1 - 0
Source/CTest/cmCTestBuildAndTestHandler.cxx

@@ -34,6 +34,7 @@ cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
 //----------------------------------------------------------------------
 void cmCTestBuildAndTestHandler::Initialize()
 {
+  this->Superclass::Initialize();
 }
 
 //----------------------------------------------------------------------

+ 1 - 1
Source/CTest/cmCTestBuildCommand.cxx

@@ -91,7 +91,7 @@ bool cmCTestBuildCommand::InitialPass(
     m_CTest->SetCTestConfiguration("BuildDirectory", build_dir);
     }
 
-  cmCTestGenericHandler* handler = m_CTest->GetHandler("build");
+  cmCTestGenericHandler* handler = m_CTest->GetInitializedHandler("build");
   if ( !handler )
     {
     this->SetError("internal CTest error. Cannot instantiate build handler");

+ 4 - 3
Source/CTest/cmCTestBuildHandler.cxx

@@ -189,6 +189,7 @@ cmCTestBuildHandler::cmCTestBuildHandler()
 //----------------------------------------------------------------------
 void cmCTestBuildHandler::Initialize()
 {
+  this->Superclass::Initialize();
   m_StartBuild = "";
   m_EndBuild = "";
   m_CustomErrorMatches.clear();
@@ -282,9 +283,9 @@ int cmCTestBuildHandler::ProcessHandler()
   // Create a last build log
   cmGeneratedFileStream ofs;
   double elapsed_time_start = cmSystemTools::GetTime();
-  if ( !m_CTest->OpenOutputFile("Temporary", "LastBuild.log", ofs) )
+  if ( !this->StartLogFile("Build", ofs) )
     {
-    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create LastBuild.log file" << std::endl);
+    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create build log file" << std::endl);
     }
 
   // Create lists of regular expression strings for errors, error exceptions,
@@ -414,7 +415,7 @@ int cmCTestBuildHandler::ProcessHandler()
 
   // Generate XML output
   cmGeneratedFileStream xofs;
-  if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Build.xml", xofs, true) )
+  if( !this->StartResultingXML("Build", xofs))
     {
     cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create build XML file" << std::endl);
     return -1;

+ 1 - 1
Source/CTest/cmCTestConfigureCommand.cxx

@@ -132,7 +132,7 @@ bool cmCTestConfigureCommand::InitialPass(
       }
     }
 
-  cmCTestGenericHandler* handler = m_CTest->GetHandler("configure");
+  cmCTestGenericHandler* handler = m_CTest->GetInitializedHandler("configure");
   if ( !handler )
     {
     this->SetError("internal CTest error. Cannot instantiate configure handler");

+ 3 - 2
Source/CTest/cmCTestConfigureHandler.cxx

@@ -31,6 +31,7 @@ cmCTestConfigureHandler::cmCTestConfigureHandler()
 //----------------------------------------------------------------------
 void cmCTestConfigureHandler::Initialize()
 {
+  this->Superclass::Initialize();
 }
 
 //----------------------------------------------------------------------
@@ -61,7 +62,7 @@ int cmCTestConfigureHandler::ProcessHandler()
   if ( !m_CTest->GetShowOnly() )
     {
     cmGeneratedFileStream os; 
-    if ( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Configure.xml", os, true) )
+    if ( !this->StartResultingXML("Configure", os) )
       {
       cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot open configure file" << std::endl);
       return 1;
@@ -69,7 +70,7 @@ int cmCTestConfigureHandler::ProcessHandler()
     std::string start_time = m_CTest->CurrentTime();
 
     cmGeneratedFileStream ofs;
-    m_CTest->OpenOutputFile("Temporary", "LastConfigure.log", ofs);
+    this->StartLogFile("Configure", ofs);
     cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Configure with command: " << cCommand.c_str() << std::endl);
     res = m_CTest->RunMakeCommand(cCommand.c_str(), &output, 
       &retVal, buildDirectory.c_str(),

+ 1 - 1
Source/CTest/cmCTestCoverageCommand.cxx

@@ -74,7 +74,7 @@ bool cmCTestCoverageCommand::InitialPass(
   m_CTest->SetCTestConfigurationFromCMakeVariable(m_Makefile,
     "CoverageCommand", "CTEST_COVERAGE_COMMAND");
 
-  cmCTestGenericHandler* handler = m_CTest->GetHandler("coverage");
+  cmCTestGenericHandler* handler = m_CTest->GetInitializedHandler("coverage");
   if ( !handler )
     {
     this->SetError("internal CTest error. Cannot instantiate test handler");

+ 12 - 13
Source/CTest/cmCTestCoverageHandler.cxx

@@ -39,16 +39,16 @@ cmCTestCoverageHandler::cmCTestCoverageHandler()
 //----------------------------------------------------------------------
 void cmCTestCoverageHandler::Initialize()
 {
+  this->Superclass::Initialize();
 }
 
 //----------------------------------------------------------------------
-bool cmCTestCoverageHandler::StartLogFile(cmGeneratedFileStream& covLogFile, int logFileCount)
+bool cmCTestCoverageHandler::StartCoverageLogFile(cmGeneratedFileStream& covLogFile, int logFileCount)
 {
   char covLogFilename[1024];
-  sprintf(covLogFilename, "CoverageLog-%d.xml", logFileCount);
+  sprintf(covLogFilename, "CoverageLog-%d", logFileCount);
   cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Open file: " << covLogFilename << std::endl);
-  if (!m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), 
-      covLogFilename, covLogFile, true))
+  if (!this->StartResultingXML(covLogFilename, covLogFile) )
     {
     cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot open log file: " << covLogFilename << std::endl);
     return false;
@@ -61,7 +61,7 @@ bool cmCTestCoverageHandler::StartLogFile(cmGeneratedFileStream& covLogFile, int
 }
 
 //----------------------------------------------------------------------
-void cmCTestCoverageHandler::EndLogFile(cmGeneratedFileStream& ostr, int logFileCount)
+void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount)
 {
   std::string local_end_time = m_CTest->CurrentTime();
   ostr << "\t<EndDateTime>" << local_end_time << "</EndDateTime>" << std::endl
@@ -161,7 +161,7 @@ int cmCTestCoverageHandler::ProcessHandler()
 
   cmGeneratedFileStream ofs;
   double elapsed_time_start = cmSystemTools::GetTime();
-  if ( !m_CTest->OpenOutputFile("Temporary", "LastCoverage.log", ofs) )
+  if ( !this->StartLogFile("Coverage", ofs) )
     {
     cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create LastCoverage.log file" << std::endl);
     }
@@ -333,10 +333,9 @@ int cmCTestCoverageHandler::ProcessHandler()
   cmGeneratedFileStream covSumFile;
   cmGeneratedFileStream covLogFile;
 
-  if (!m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), 
-      "Coverage.xml", covSumFile, true))
+  if (!this->StartResultingXML("Coverage", covSumFile))
     {
-    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot open coverage summary file: Coverage.xml" << std::endl);
+    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot open coverage summary file." << std::endl);
 
     return -1;
     }
@@ -347,7 +346,7 @@ int cmCTestCoverageHandler::ProcessHandler()
   covSumFile << "<Coverage>" << std::endl
     << "\t<StartDateTime>" << coverage_start_time << "</StartDateTime>" << std::endl;
   int logFileCount = 0;
-  if ( !this->StartLogFile(covLogFile, logFileCount) )
+  if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
     {
     return -1;
     }
@@ -364,9 +363,9 @@ int cmCTestCoverageHandler::ProcessHandler()
     if ( cnt == 100 )
       {
       cnt = 0;
-      this->EndLogFile(covLogFile, logFileCount);
+      this->EndCoverageLogFile(covLogFile, logFileCount);
       logFileCount ++;
-      if ( !this->StartLogFile(covLogFile, logFileCount) )
+      if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
         {
         return -1;
         }
@@ -468,7 +467,7 @@ int cmCTestCoverageHandler::ProcessHandler()
       << "\t</File>" << std::endl;
     cnt ++;
     }
-  this->EndLogFile(covLogFile, logFileCount);
+  this->EndCoverageLogFile(covLogFile, logFileCount);
 
   int total_lines = total_tested + total_untested;
   float percent_coverage = 100 * SAFEDIV(static_cast<float>(total_tested),

+ 2 - 2
Source/CTest/cmCTestCoverageHandler.h

@@ -45,8 +45,8 @@ public:
 private:
   bool ShouldIDoCoverage(const char* file, const char* srcDir,
     const char* binDir);
-  bool StartLogFile(cmGeneratedFileStream& ostr, int logFileCount);
-  void EndLogFile(cmGeneratedFileStream& ostr, int logFileCount);
+  bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
+  void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
 
   struct cmCTestCoverage
     {

+ 57 - 0
Source/CTest/cmCTestGenericHandler.cxx

@@ -17,11 +17,14 @@
 
 #include "cmCTestGenericHandler.h"
 
+#include "cmCTest.h"
+
 //----------------------------------------------------------------------
 cmCTestGenericHandler::cmCTestGenericHandler()
 {
   m_HandlerVerbose = false;
   m_CTest = 0;
+  m_SubmitIndex = 0;
 }
 
 //----------------------------------------------------------------------
@@ -50,6 +53,12 @@ void cmCTestGenericHandler::SetOption(const char* op, const char* value)
   m_Options[op] = value;
 }
 
+//----------------------------------------------------------------------
+void cmCTestGenericHandler::Initialize()
+{
+  m_Options.clear();
+}
+
 //----------------------------------------------------------------------
 const char* cmCTestGenericHandler::GetOption(const char* op)
 {
@@ -62,3 +71,51 @@ const char* cmCTestGenericHandler::GetOption(const char* op)
   return remit->second.c_str();
 }
 
+//----------------------------------------------------------------------
+bool cmCTestGenericHandler::StartResultingXML(const char* name, cmGeneratedFileStream& xofs)
+{
+  if ( !name )
+    {
+    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create resulting XML file without providing the name" << std::endl;);
+    return false;
+    }
+  cmOStringStream ostr;
+  ostr << name;
+  if ( m_SubmitIndex > 0 )
+    {
+    ostr << "_" << m_SubmitIndex;
+    }
+  ostr << ".xml";
+  if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), ostr.str().c_str(), xofs, true) )
+    {
+    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create resulting XML file: " << ostr.str().c_str() << std::endl);
+    return false;
+    }
+  m_CTest->AddSubmitFile(ostr.str().c_str());
+  return true;
+}
+
+//----------------------------------------------------------------------
+bool cmCTestGenericHandler::StartLogFile(const char* name, cmGeneratedFileStream& xofs)
+{
+  if ( !name )
+    {
+    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create log file without providing the name" << std::endl;);
+    return false;
+    }
+  cmOStringStream ostr;
+  ostr << "Last" << name;
+  if ( m_SubmitIndex > 0 )
+    {
+    ostr << "_" << m_SubmitIndex;
+    }
+  ostr << "_" << m_CTest->GetCurrentTag();
+  ostr << ".log";
+  if( !m_CTest->OpenOutputFile("Temporary", ostr.str().c_str(), xofs) )
+    {
+    cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create log file: " << ostr.str().c_str() << std::endl);
+    return false;
+    }
+  return true;
+}
+

+ 9 - 1
Source/CTest/cmCTestGenericHandler.h

@@ -24,6 +24,7 @@
 class cmCTest;
 class cmMakefile;
 class cmCTestCommand;
+class cmGeneratedFileStream;
 
 /** \class cmCTestGenericHandler
  * \brief A superclass of all CTest Handlers
@@ -58,7 +59,7 @@ public:
   /**
    * Initialize handler
    */
-  virtual void Initialize() = 0;
+  virtual void Initialize();
 
   /**
    * Set the CTest instance
@@ -82,12 +83,19 @@ public:
     m_Command = command;
     }
 
+  void SetSubmitIndex(int idx) { m_SubmitIndex = idx; }
+  int GetSubmitIndex() { return m_SubmitIndex; }
+
 protected:
+  bool StartResultingXML(const char* name, cmGeneratedFileStream& xofs);
+  bool StartLogFile(const char* name, cmGeneratedFileStream& xofs);
+  
   bool m_HandlerVerbose;
   cmCTest *m_CTest;
   t_StringToString m_Options;
 
   cmCTestCommand* m_Command;
+  int m_SubmitIndex;
 };
 
 #endif

+ 133 - 0
Source/CTest/cmCTestHandlerCommand.cxx

@@ -0,0 +1,133 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmCTestHandlerCommand.h"
+
+#include "cmCTest.h"
+#include "cmCTestGenericHandler.h"
+
+cmCTestHandlerCommand::cmCTestHandlerCommand()
+{
+  const size_t INIT_SIZE = 100;
+  size_t cc;
+  m_Arguments.reserve(INIT_SIZE);
+  for ( cc = 0; cc < INIT_SIZE; ++ cc )
+    {
+    m_Arguments[cc] = 0;
+    }
+  m_Arguments[ct_RETURN_VALUE] = "RETURN_VALUE";
+  m_Arguments[ct_SOURCE] = "SOURCE";
+  m_Arguments[ct_BUILD] = "BUILD";
+  m_Arguments[ct_SUBMIT_INDEX] = "SUBMIT_INDEX";
+  m_Last = ct_LAST;
+}
+
+bool cmCTestHandlerCommand::InitialPass(
+  std::vector<std::string> const& args)
+{
+  if ( !this->ProcessArguments(args, m_Last, &*m_Arguments.begin(), m_Values) )
+    {
+    return false;
+    }
+
+  cmCTestGenericHandler* handler = this->InitializeHandler();
+  if ( !handler )
+    {
+    this->SetError("internal CTest error. Cannot instantiate test handler");
+    return false;
+    }
+
+  if ( m_Values[ct_BUILD] )
+    {
+    m_CTest->SetCTestConfiguration("BuildDirectory", m_Values[ct_BUILD]);
+    }
+  if ( m_Values[ct_SUBMIT_INDEX] )
+    {
+    if ( m_CTest->GetDartVersion() <= 1 )
+      {
+      cmCTestLog(m_CTest, ERROR_MESSAGE, "Dart before version 2.0 does not support collecting submissions." << std::endl
+        << "Please upgrade the server to Dart 2 or higher, or do not use SUBMIT_INDEX." << std::endl);
+      }
+    else
+      {
+      handler->SetSubmitIndex(atoi(m_Values[ct_SUBMIT_INDEX]));
+      }
+    }
+
+
+  std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
+  cmSystemTools::ChangeDirectory(m_CTest->GetCTestConfiguration("BuildDirectory").c_str());
+  int res = handler->ProcessHandler();
+  if ( m_Values[ct_RETURN_VALUE] && *m_Values[ct_RETURN_VALUE])
+    {
+    cmOStringStream str;
+    str << res;
+    m_Makefile->AddDefinition(m_Values[ct_RETURN_VALUE], str.str().c_str());
+    }
+  cmSystemTools::ChangeDirectory(current_dir.c_str());
+  return true;
+}
+
+bool cmCTestHandlerCommand::ProcessArguments(std::vector<std::string> const& args,
+  int last, const char** strings, std::vector<const char*>& values)
+{
+  int state = 0;
+  int cc;
+  values.resize(last);
+  for ( cc = 0; cc < last; ++ cc )
+    {
+    values[cc] = 0;
+    }
+
+  for(size_t i=0; i < args.size(); ++i)
+    {
+    if ( state > 0 && state < last )
+      {
+      values[state] = args[i].c_str();
+#undef cerr
+      cmCTestLog(m_CTest, DEBUG, "Set " << strings[state] << " to " << args[i].c_str() << std::endl);
+      state = 0;
+      }
+    else
+      {
+      bool found = false;
+      for ( cc = 0; cc < last; ++ cc )
+        {
+        if ( strings[cc] && args[i] == strings[cc] )
+          {
+          state = cc;
+          if ( values[state] )
+            {
+            cmOStringStream ostr;
+            ostr << "called with incorrect number of arguments. " << strings[state] << " specified twice.";
+            this->SetError(ostr.str().c_str());
+            return false;
+            }
+          found = true;
+          break;
+          }
+        }
+      if ( !found )
+        {
+        cmOStringStream str;
+        str << "called with incorrect number of arguments. Extra argument is: " << args[i].c_str() << ".";
+        this->SetError(str.str().c_str());
+        return false;
+        }
+      }
+    }
+  return true;
+}

+ 63 - 0
Source/CTest/cmCTestHandlerCommand.h

@@ -0,0 +1,63 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmCTestHandlerCommand_h
+#define cmCTestHandlerCommand_h
+
+#include "cmCTestCommand.h"
+
+class cmCTestGenericHandler;
+
+/** \class cmCTestHandler
+ * \brief Run a ctest script
+ *
+ * cmCTestHandlerCommand defineds the command to test the project.
+ */
+class cmCTestHandlerCommand : public cmCTestCommand
+{
+public:
+  cmCTestHandlerCommand();
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args);
+
+  cmTypeMacro(cmCTestHandlerCommand, cmCTestCommand);
+
+  enum
+    {
+    ct_NONE,
+    ct_RETURN_VALUE,
+    ct_BUILD,
+    ct_SOURCE,
+    ct_SUBMIT_INDEX,
+    ct_LAST
+    };
+
+protected:
+  virtual cmCTestGenericHandler* InitializeHandler() = 0;
+  bool ProcessArguments(std::vector<std::string> const& args,
+    int last, const char** strings, std::vector<const char*>& values);
+
+  std::string m_ReturnVariable;
+  std::vector<const char*> m_Arguments;
+  std::vector<const char*> m_Values;
+  size_t m_Last;
+};
+
+#endif

+ 4 - 69
Source/CTest/cmCTestMemCheckCommand.cxx

@@ -19,57 +19,10 @@
 #include "cmCTest.h"
 #include "cmCTestGenericHandler.h"
 
-bool cmCTestMemCheckCommand::InitialPass(
-  std::vector<std::string> const& args)
-{
-  const char* build_dir = 0;
-  const char* res_var = 0;
-
-  bool havereturn_variable = false;
-  bool havesource = false;
-  for(size_t i=0; i < args.size(); ++i)
-    {
-    if ( havereturn_variable )
-      {
-      res_var = args[i].c_str();
-      havereturn_variable = false;
-      }
-    else if ( havesource )
-      {
-      build_dir = args[i].c_str();
-      havesource = false;
-      }
-    else if(args[i] == "RETURN_VALUE")
-      {
-      if ( res_var )
-        {
-        this->SetError("called with incorrect number of arguments. RETURN_VALUE specified twice.");
-        return false;
-        }
-      havereturn_variable = true;
-      }    
-    else if(args[i] == "BUILD")
-      {
-      if ( build_dir )
-        {
-        this->SetError("called with incorrect number of arguments. BUILD specified twice.");
-        return false;
-        }
-      havesource = true;
-      }
-    else
-      {
-      cmOStringStream str;
-      str << "called with incorrect number of arguments. Extra argument is: " << args[i].c_str() << ".";
-      this->SetError(str.str().c_str());
-      return false;
-      }
-    }
 
-  if ( build_dir )
-    {
-    m_CTest->SetCTestConfiguration("BuildDirectory", build_dir);
-    }
+cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
+{
+  cmCTestGenericHandler* handler = m_CTest->GetInitializedHandler("memcheck");
 
   m_CTest->SetCTestConfigurationFromCMakeVariable(m_Makefile,
     "MemoryCheckCommand", "CTEST_MEMORYCHECK_COMMAND");
@@ -78,24 +31,6 @@ bool cmCTestMemCheckCommand::InitialPass(
   m_CTest->SetCTestConfigurationFromCMakeVariable(m_Makefile,
     "MemoryCheckSuppressionFile", "CTEST_MEMORYCHECK_SUPPRESSIONS_FILE");
 
-  cmCTestGenericHandler* handler = m_CTest->GetHandler("memcheck");
-  if ( !handler )
-    {
-    this->SetError("internal CTest error. Cannot instantiate test handler");
-    return false;
-    }
-  std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(m_CTest->GetCTestConfiguration("BuildDirectory").c_str());
-  int res = handler->ProcessHandler();
-  if ( res_var )
-    {
-    cmOStringStream str;
-    str << res;
-    m_Makefile->AddDefinition(res_var, str.str().c_str());
-    }
-  cmSystemTools::ChangeDirectory(current_dir.c_str());
-  return true;
+  return handler;
 }
 
-
-

+ 7 - 9
Source/CTest/cmCTestMemCheckCommand.h

@@ -17,14 +17,16 @@
 #ifndef cmCTestMemCheckCommand_h
 #define cmCTestMemCheckCommand_h
 
-#include "cmCTestCommand.h"
+#include "cmCTestTestCommand.h"
+
+class cmCTestGenericHandler;
 
 /** \class cmCTestMemCheck
  * \brief Run a ctest script
  *
  * cmCTestMemCheckCommand defineds the command to test the project.
  */
-class cmCTestMemCheckCommand : public cmCTestCommand
+class cmCTestMemCheckCommand : public cmCTestTestCommand
 {
 public:
 
@@ -41,12 +43,6 @@ public:
     return ni;
     }
 
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  virtual bool InitialPass(std::vector<std::string> const& args);
-
   /**
    * The name of the command as specified in CMakeList.txt.
    */
@@ -72,8 +68,10 @@ public:
       "will hold value.";
     }
 
-  cmTypeMacro(cmCTestMemCheckCommand, cmCTestCommand);
+  cmTypeMacro(cmCTestMemCheckCommand, cmCTestTestCommand);
 
+protected:
+  cmCTestGenericHandler* InitializeActualHandler();
 };
 
 

+ 1 - 0
Source/CTest/cmCTestScriptHandler.cxx

@@ -100,6 +100,7 @@ cmCTestScriptHandler::cmCTestScriptHandler()
 //----------------------------------------------------------------------
 void cmCTestScriptHandler::Initialize()
 {
+  this->Superclass::Initialize();
   m_Backup = false;
   m_EmptyBinDir = false;
   m_EmptyBinDirOnce = false;

+ 3 - 2
Source/CTest/cmCTestStartCommand.cxx

@@ -68,8 +68,9 @@ bool cmCTestStartCommand::InitialPass(
   m_CTest->SetCTestConfiguration("SourceDirectory", src_dir);
   m_CTest->SetCTestConfiguration("BuildDirectory", bld_dir); 
 
-  cmCTestLog(m_CTest, OUTPUT, "Run dashboard with model " << smodel << std::endl
-    << "   Source directory: " << src_dir << std::endl << "   Build directory: " << bld_dir << std::endl);
+  cmCTestLog(m_CTest, HANDLER_OUTPUT, "Run dashboard with model " << smodel << std::endl
+    << "   Source directory: " << src_dir << std::endl
+    << "   Build directory: " << bld_dir << std::endl);
 
   m_Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", "OFF");
   m_CTest->SetSuppressUpdatingCTestConfiguration(true);

+ 1 - 1
Source/CTest/cmCTestSubmitCommand.cxx

@@ -98,7 +98,7 @@ bool cmCTestSubmitCommand::InitialPass(
     m_CTest->GenerateNotesFile(newNotesFiles);
     }
 
-  cmCTestGenericHandler* handler = m_CTest->GetHandler("submit");
+  cmCTestGenericHandler* handler = m_CTest->GetInitializedHandler("submit");
   if ( !handler )
     {
     this->SetError("internal CTest error. Cannot instantiate submit handler");

+ 46 - 31
Source/CTest/cmCTestSubmitHandler.cxx

@@ -70,6 +70,7 @@ cmCTestSubmitHandler::cmCTestSubmitHandler() : m_HTTPProxy(), m_FTPProxy()
 //----------------------------------------------------------------------------
 void cmCTestSubmitHandler::Initialize()
 {
+  this->Superclass::Initialize();
   m_HTTPProxy = "";
   m_HTTPProxyType = 0;
   m_HTTPProxyAuth = "";
@@ -80,7 +81,7 @@ void cmCTestSubmitHandler::Initialize()
 
 //----------------------------------------------------------------------------
 bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix, 
-  const std::vector<cmStdString>& files,
+  const std::set<cmStdString>& files,
   const cmStdString& remoteprefix, 
   const cmStdString& url)
 {
@@ -92,8 +93,8 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
   /* In windows, this will init the winsock stuff */
   ::curl_global_init(CURL_GLOBAL_ALL);
 
-  cmStdString::size_type cc;
-  for ( cc = 0; cc < files.size(); cc ++ )
+  cmCTest::tm_SetOfStrings::iterator file;
+  for ( file = files.begin(); file != files.end(); ++file )
     {
     /* get a curl handle */
     curl = curl_easy_init();
@@ -119,12 +120,15 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
       // enable uploading
       ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1) ;
 
-      cmStdString local_file = localprefix + "/" + files[cc];
-      cmStdString upload_as = url + "/" + remoteprefix + files[cc];
+      cmStdString local_file = localprefix + "/" + *file;
+      cmStdString upload_as = url + "/" + remoteprefix + *file;
 
       struct stat st;
       if ( ::stat(local_file.c_str(), &st) )
         {
+        cmCTestLog(m_CTest, ERROR_MESSAGE, "   Cannot find file: " << local_file.c_str() << std::endl);
+        ::curl_easy_cleanup(curl);
+        ::curl_global_cleanup(); 
         return false;
         }
 
@@ -192,7 +196,7 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
 //----------------------------------------------------------------------------
 // Uploading files is simpler
 bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix, 
-  const std::vector<cmStdString>& files,
+  const std::set<cmStdString>& files,
   const cmStdString& remoteprefix, 
   const cmStdString& url)
 {
@@ -204,8 +208,9 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
   /* In windows, this will init the winsock stuff */
   ::curl_global_init(CURL_GLOBAL_ALL);
 
-  cmStdString::size_type cc, kk;
-  for ( cc = 0; cc < files.size(); cc ++ )
+  cmStdString::size_type kk;
+  cmCTest::tm_SetOfStrings::iterator file;
+  for ( file = files.begin(); file != files.end(); ++file )
     {
     /* get a curl handle */
     curl = curl_easy_init();
@@ -241,8 +246,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
       ::curl_easy_setopt(curl, CURLOPT_PUT, 1);
       ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
 
-      cmStdString local_file = localprefix + "/" + files[cc];
-      cmStdString remote_file = remoteprefix + files[cc];
+      cmStdString local_file = localprefix + "/" + *file;
+      cmStdString remote_file = remoteprefix + *file;
 
       *m_LogFile << "\tUpload file: " << local_file.c_str() << " to "
           << remote_file.c_str() << std::endl;
@@ -277,6 +282,9 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
       struct stat st;
       if ( ::stat(local_file.c_str(), &st) )
         {
+        cmCTestLog(m_CTest, ERROR_MESSAGE, "   Cannot find file: " << local_file.c_str() << std::endl);
+        ::curl_easy_cleanup(curl);
+        ::curl_global_cleanup(); 
         return false;
         }
 
@@ -339,7 +347,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
 }
 
 //----------------------------------------------------------------------------
-bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::vector<cmStdString>& files,
+bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<cmStdString>& files,
   const cmStdString& remoteprefix, 
   const cmStdString& url)
 {
@@ -349,8 +357,8 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::vector<cmStdString>& file
   /* In windows, this will init the winsock stuff */
   ::curl_global_init(CURL_GLOBAL_ALL);
 
-  cmStdString::size_type cc, kk;
-  for ( cc = 0; cc < files.size(); cc ++ )
+  cmCTest::tm_SetOfStrings::iterator file;
+  for ( file = files.begin(); file != files.end(); ++file )
     {
     /* get a curl handle */
     curl = curl_easy_init();
@@ -393,11 +401,12 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::vector<cmStdString>& file
       ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
       ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
 
-      cmStdString file = remoteprefix + files[cc];
+      cmStdString rfile = remoteprefix + *file;
       cmStdString ofile = "";
-      for ( kk = 0; kk < file.size(); kk ++ )
+      cmStdString::iterator kk;
+      for ( kk = rfile.begin(); kk < rfile.end(); ++ kk)
         {
-        char c = file[kk];
+        char c = *kk;
         char hex[4] = { 0, 0, 0, 0 };
         hex[0] = c;
         switch ( c )
@@ -456,7 +465,7 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::vector<cmStdString>& file
 bool cmCTestSubmitHandler::SubmitUsingSCP(
   const cmStdString& scp_command, 
   const cmStdString& localprefix, 
-  const std::vector<cmStdString>& files,
+  const std::set<cmStdString>& files,
   const cmStdString& remoteprefix, 
   const cmStdString& url)
 {
@@ -477,19 +486,17 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(
 
   int problems = 0;
 
-  std::vector<cmStdString>::const_iterator it;
-  for ( it = files.begin();
-    it != files.end();
-    it ++ )
+  cmCTest::tm_SetOfStrings::iterator file;
+  for ( file = files.begin(); file != files.end(); ++file )
     {
     int retVal;
 
     std::string lfname = localprefix;
     cmSystemTools::ConvertToUnixSlashes(lfname);
-    lfname += "/" + *it;
+    lfname += "/" + *file;
     lfname = cmSystemTools::ConvertToOutputPath(lfname.c_str());
     argv[1] = lfname.c_str();
-    std::string rfname = url + "/" + remoteprefix + *it;
+    std::string rfname = url + "/" + remoteprefix + *file;
     argv[2] = rfname.c_str();
     cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \"" 
       << argv[2] << "\"" << std::endl);
@@ -548,7 +555,7 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(
 
 //----------------------------------------------------------------------------
 bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix, 
-  const std::vector<cmStdString>& files,
+  const std::set<cmStdString>& files,
   const cmStdString& remoteprefix, 
   const cmStdString& url)
 {
@@ -565,12 +572,12 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix,
 
   /* Call the famous server at UserLand. */
   cmCTestLog(m_CTest, HANDLER_OUTPUT, "   Submitting to: " << realURL.c_str() << " (" << remoteprefix.c_str() << ")" << std::endl);
-  std::vector<cmStdString>::const_iterator it;
-  for ( it = files.begin(); it != files.end(); ++it )
+  cmCTest::tm_SetOfStrings::iterator file;
+  for ( file = files.begin(); file != files.end(); ++file )
     {
     xmlrpc_value *result;
 
-    std::string local_file = localprefix + "/" + *it;
+    std::string local_file = localprefix + "/" + *file;
     cmCTestLog(m_CTest, HANDLER_OUTPUT, "   Submit file: " << local_file.c_str() << std::endl);
     struct stat st;
     if ( ::stat(local_file.c_str(), &st) )
@@ -705,9 +712,9 @@ int cmCTestSubmitHandler::ProcessHandler()
     cmCTestLog(m_CTest, HANDLER_OUTPUT, "   Use FTP Proxy: " << m_FTPProxy << std::endl);
     }
   cmGeneratedFileStream ofs;
-  m_CTest->OpenOutputFile("Temporary", "LastSubmit.log", ofs);
+  this->StartLogFile("Submit", ofs);
 
-  cmCTest::tm_VectorOfStrings files;
+  cmCTest::tm_SetOfStrings files;
   std::string prefix = this->GetSubmitResultsPrefix();
   // TODO:
   // Check if test is enabled
@@ -729,7 +736,7 @@ int cmCTestSubmitHandler::ProcessHandler()
         {
         gfiles[cc] = gfiles[cc].substr(glen);
         cmCTestLog(m_CTest, DEBUG, "Glob file: " << gfiles[cc].c_str() << std::endl);
-        files.push_back(gfiles[cc]);
+        files.insert(gfiles[cc]);
         }
       }
     else
@@ -741,11 +748,19 @@ int cmCTestSubmitHandler::ProcessHandler()
   m_CTest->AddIfExists(files, "Purify.xml");
   m_CTest->AddIfExists(files, "Notes.xml");
 
+  cmCTest::tm_SetOfStrings::iterator it;
+  for ( it = m_CTest->GetSubmitFiles()->begin();
+   it != m_CTest->GetSubmitFiles()->end();
+   ++ it )
+    {
+    files.insert(files.end(), *it);
+    }
+
   if ( ofs )
     {
     ofs << "Upload files:" << std::endl;
     int cnt = 0;
-    cmCTest::tm_VectorOfStrings::iterator it;
+    cmCTest::tm_SetOfStrings::iterator it;
     for ( it = files.begin(); it != files.end(); ++ it )
       {
       ofs << cnt << "\t" << it->c_str() << std::endl;

+ 5 - 5
Source/CTest/cmCTestSubmitHandler.h

@@ -47,25 +47,25 @@ private:
    * Submit file using various ways
    */
   bool SubmitUsingFTP(const cmStdString& localprefix, 
-                      const std::vector<cmStdString>& files,
+                      const std::set<cmStdString>& files,
                       const cmStdString& remoteprefix, 
                       const cmStdString& url);
   bool SubmitUsingHTTP(const cmStdString& localprefix, 
-                       const std::vector<cmStdString>& files,
+                       const std::set<cmStdString>& files,
                        const cmStdString& remoteprefix, 
                        const cmStdString& url);
   bool SubmitUsingSCP(const cmStdString& scp_command,
                       const cmStdString& localprefix, 
-                      const std::vector<cmStdString>& files,
+                      const std::set<cmStdString>& files,
                       const cmStdString& remoteprefix, 
                       const cmStdString& url);
 
-  bool TriggerUsingHTTP(const std::vector<cmStdString>& files,
+  bool TriggerUsingHTTP(const std::set<cmStdString>& files,
                         const cmStdString& remoteprefix, 
                         const cmStdString& url);
 
   bool SubmitUsingXMLRPC(const cmStdString& localprefix, 
-                       const std::vector<cmStdString>& files,
+                       const std::set<cmStdString>& files,
                        const cmStdString& remoteprefix, 
                        const cmStdString& url);
 

+ 26 - 59
Source/CTest/cmCTestTestCommand.cxx

@@ -19,75 +19,42 @@
 #include "cmCTest.h"
 #include "cmCTestGenericHandler.h"
 
-bool cmCTestTestCommand::InitialPass(
-  std::vector<std::string> const& args)
+cmCTestTestCommand::cmCTestTestCommand()
 {
-  const char* build_dir = 0;
-  const char* res_var = 0;
+  m_Arguments[ctt_START] = "START";
+  m_Arguments[ctt_END] = "END";
+  m_Arguments[ctt_STRIDE] = "STRIDE";
+  m_Arguments[ctt_LAST] = 0;
+  m_Last = ctt_LAST;
+}
 
-  bool havereturn_variable = false;
-  bool havesource = false;
-  for(size_t i=0; i < args.size(); ++i)
+cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
+{
+  cmCTestGenericHandler* handler = m_CTest->GetInitializedHandler("test");
+  if ( m_Values[ctt_START] || m_Values[ctt_END] || m_Values[ctt_STRIDE] )
     {
-    if ( havereturn_variable )
-      {
-      res_var = args[i].c_str();
-      havereturn_variable = false;
-      }
-    else if ( havesource )
+    cmOStringStream testsToRunString;
+    if ( m_Values[ctt_START] )
       {
-      build_dir = args[i].c_str();
-      havesource = false;
+      testsToRunString << m_Values[ctt_START];
       }
-    else if(args[i] == "RETURN_VALUE")
+    testsToRunString << ",";
+    if ( m_Values[ctt_END] )
       {
-      if ( res_var )
-        {
-        this->SetError("called with incorrect number of arguments. RETURN_VALUE specified twice.");
-        return false;
-        }
-      havereturn_variable = true;
-      }    
-    else if(args[i] == "BUILD")
-      {
-      if ( build_dir )
-        {
-        this->SetError("called with incorrect number of arguments. BUILD specified twice.");
-        return false;
-        }
-      havesource = true;
+      testsToRunString << m_Values[ctt_END];
       }
-    else
+    testsToRunString << ",";
+    if ( m_Values[ctt_STRIDE] )
       {
-      cmOStringStream str;
-      str << "called with incorrect number of arguments. Extra argument is: " << args[i].c_str() << ".";
-      this->SetError(str.str().c_str());
-      return false;
+      testsToRunString << m_Values[ctt_STRIDE];
       }
+    handler->SetOption("TestsToRunInformation", testsToRunString.str().c_str());
     }
-
-  if ( build_dir )
-    {
-    m_CTest->SetCTestConfiguration("BuildDirectory", build_dir);
-    }
-
-  cmCTestGenericHandler* handler = m_CTest->GetHandler("test");
-  if ( !handler )
-    {
-    this->SetError("internal CTest error. Cannot instantiate test handler");
-    return false;
-    }
-  std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(m_CTest->GetCTestConfiguration("BuildDirectory").c_str());
-  int res = handler->ProcessHandler();
-  if ( res_var )
-    {
-    cmOStringStream str;
-    str << res;
-    m_Makefile->AddDefinition(res_var, str.str().c_str());
-    }
-  cmSystemTools::ChangeDirectory(current_dir.c_str());
-  return true;
+  return handler;
 }
 
+cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler()
+{
+  return m_CTest->GetInitializedHandler("test");
+}
 

+ 18 - 10
Source/CTest/cmCTestTestCommand.h

@@ -17,18 +17,20 @@
 #ifndef cmCTestTestCommand_h
 #define cmCTestTestCommand_h
 
-#include "cmCTestCommand.h"
+#include "cmCTestHandlerCommand.h"
+
+class cmCTestGenericHandler;
 
 /** \class cmCTestTest
  * \brief Run a ctest script
  *
  * cmCTestTestCommand defineds the command to test the project.
  */
-class cmCTestTestCommand : public cmCTestCommand
+class cmCTestTestCommand : public cmCTestHandlerCommand
 {
 public:
 
-  cmCTestTestCommand() {}
+  cmCTestTestCommand();
   
   /**
    * This is a virtual constructor for the command.
@@ -41,12 +43,6 @@ public:
     return ni;
     }
 
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  virtual bool InitialPass(std::vector<std::string> const& args);
-
   /**
    * The name of the command as specified in CMakeList.txt.
    */
@@ -71,8 +67,20 @@ public:
       "second argument is a variable that will hold value.";
     }
 
-  cmTypeMacro(cmCTestTestCommand, cmCTestCommand);
+  cmTypeMacro(cmCTestTestCommand, cmCTestHandlerCommand);
+
+protected:
+  cmCTestGenericHandler* InitializeActualHandler();
+  cmCTestGenericHandler* InitializeHandler();
 
+  enum {
+    ctt_BUILD = ct_LAST,
+    ctt_RETURN_VALUE,
+    ctt_START,
+    ctt_END,
+    ctt_STRIDE,
+    ctt_LAST
+  };
 };
 
 

+ 5 - 5
Source/CTest/cmCTestTestHandler.cxx

@@ -296,6 +296,8 @@ cmCTestTestHandler::cmCTestTestHandler()
 //----------------------------------------------------------------------
 void cmCTestTestHandler::Initialize()
 {
+  this->Superclass::Initialize();
+
   m_ElapsedTestingTime = -1;
 
   m_TestResults.clear();
@@ -435,7 +437,7 @@ int cmCTestTestHandler::ProcessHandler()
       cmGeneratedFileStream ofs;
 
       cmCTestLog(m_CTest, ERROR_MESSAGE, std::endl << "The following tests FAILED:" << std::endl);
-      m_CTest->OpenOutputFile("Temporary", "LastTestsFailed.log", ofs);
+      this->StartLogFile("TestsFailed", ofs);
 
       std::vector<cmCTestTestHandler::cmCTestTestResult>::iterator ftit;
       for(ftit = m_TestResults.begin();
@@ -456,8 +458,7 @@ int cmCTestTestHandler::ProcessHandler()
   if ( m_CTest->GetProduceXML() )
     {
     cmGeneratedFileStream xmlfile;
-    if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), 
-        (m_MemCheck ? "DynamicAnalysis.xml" : "Test.xml"), xmlfile, true) )
+    if( !this->StartResultingXML((m_MemCheck ? "DynamicAnalysis" : "Test"), xmlfile) )
       {
       cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot create " << (m_MemCheck ? "memory check" : "testing")
         << " XML file" << std::endl);
@@ -492,8 +493,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
   cmGeneratedFileStream ofs;
   cmGeneratedFileStream *olog = 0;
   if ( !m_CTest->GetShowOnly() && tmsize > 0 && 
-    m_CTest->OpenOutputFile("Temporary", 
-      (m_MemCheck?"LastMemCheck.log":"LastTest.log"), ofs) )
+    this->StartResultingXML((m_MemCheck?"MemCheck":"Test"), ofs) )
     {
     olog = &ofs;
     }

+ 1 - 1
Source/CTest/cmCTestUpdateCommand.cxx

@@ -76,7 +76,7 @@ bool cmCTestUpdateCommand::InitialPass(
     initialCheckoutCommand = m_Makefile->GetDefinition("CTEST_CVS_CHECKOUT");
     }
 
-  cmCTestGenericHandler* handler = m_CTest->GetHandler("update");
+  cmCTestGenericHandler* handler = m_CTest->GetInitializedHandler("update");
   if ( !handler )
     {
     this->SetError("internal CTest error. Cannot instantiate update handler");

+ 3 - 2
Source/CTest/cmCTestUpdateHandler.cxx

@@ -178,6 +178,7 @@ cmCTestUpdateHandler::cmCTestUpdateHandler()
 //----------------------------------------------------------------------
 void cmCTestUpdateHandler::Initialize()
 {
+  this->Superclass::Initialize();
 }
 
 //----------------------------------------------------------------------
@@ -252,7 +253,7 @@ int cmCTestUpdateHandler::ProcessHandler()
   cmGeneratedFileStream ofs;
   if ( !m_CTest->GetShowOnly() )
     {
-    m_CTest->OpenOutputFile("Temporary", "LastUpdate.log", ofs);
+    this->StartLogFile("Update", ofs);
     }
 
   cmCTestLog(m_CTest, HANDLER_OUTPUT, "Updating the repository" << std::endl);
@@ -439,7 +440,7 @@ int cmCTestUpdateHandler::ProcessHandler()
   // Now update repository and remember what files were updated
   // 
   cmGeneratedFileStream os; 
-  if ( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Update.xml", os, true) )
+  if ( !this->StartResultingXML("Update", os) )
     {
     cmCTestLog(m_CTest, ERROR_MESSAGE, "Cannot open log file" << std::endl);
     }

+ 38 - 3
Source/cmCTest.cxx

@@ -228,6 +228,7 @@ cmCTest::cmCTest()
   m_OutputLogFile          = 0;
   m_OutputLogFileLastTag   = -1;
   m_SuppressUpdatingCTestConfiguration = false;
+  m_DartVersion            = 1;
 
   int cc; 
   for ( cc=0; cc < cmCTest::LAST_TEST; cc ++ )
@@ -280,6 +281,10 @@ int cmCTest::Initialize(const char* binary_dir, bool new_tag, bool verbose_tag)
 
   if ( m_ProduceXML )
     {
+    cmCTestLog(this, OUTPUT,
+      "   Site: " << this->GetCTestConfiguration("Site") << std::endl
+      << "   Build name: " << this->GetCTestConfiguration("BuildName") << std::endl
+      );
     cmCTestLog(this, DEBUG, "Produce XML is on" << std::endl);
     if ( this->GetCTestConfiguration("NightlyStartTime").empty() )
       {
@@ -393,6 +398,8 @@ bool cmCTest::InitializeFromCommand(cmCTestCommand* command, bool first)
 
   const char* src_dir = this->GetCTestConfiguration("SourceDirectory").c_str();
   const char* bld_dir = this->GetCTestConfiguration("BuildDirectory").c_str();
+  m_DartVersion = 1;
+  m_SubmitFiles.clear();
 
   cmMakefile* mf = command->GetMakefile();
   std::string fname = src_dir;
@@ -424,6 +431,16 @@ bool cmCTest::InitializeFromCommand(cmCTestCommand* command, bool first)
   this->SetCTestConfigurationFromCMakeVariable(mf, "NightlyStartTime", "CTEST_NIGHTLY_START_TIME");
   this->SetCTestConfigurationFromCMakeVariable(mf, "Site", "CTEST_SITE");
   this->SetCTestConfigurationFromCMakeVariable(mf, "BuildName", "CTEST_BUILD_NAME");
+  const char* dartVersion = mf->GetDefinition("CTEST_DART_SERVER_VERSION");
+  if ( dartVersion )
+    {
+    m_DartVersion = atoi(dartVersion);
+    if ( m_DartVersion < 0 )
+      {
+      cmCTestLog(this, ERROR_MESSAGE, "Invalid Dart server version: " << dartVersion << ". Please specify the version number." << std::endl);
+      return false;
+      }
+    }
 
   if ( !this->Initialize(bld_dir, true, false) )
     {
@@ -630,11 +647,11 @@ bool cmCTest::OpenOutputFile(const std::string& path,
 }
 
 //----------------------------------------------------------------------
-bool cmCTest::AddIfExists(tm_VectorOfStrings& files, const char* file)
+bool cmCTest::AddIfExists(tm_SetOfStrings& files, const char* file)
 {
   if ( this->CTestFileExists(file) )
     {
-    files.push_back(file);
+    files.insert(file);
     }
   else
     {
@@ -642,7 +659,7 @@ bool cmCTest::AddIfExists(tm_VectorOfStrings& files, const char* file)
     name += ".gz";
     if ( this->CTestFileExists(name.c_str()) )
       {
-      files.push_back(name.c_str());
+      files.insert(name.c_str());
       }
     else
       {
@@ -660,6 +677,18 @@ bool cmCTest::CTestFileExists(const std::string& filename)
   return cmSystemTools::FileExists(testingDir.c_str());
 }
 
+//----------------------------------------------------------------------
+cmCTestGenericHandler* cmCTest::GetInitializedHandler(const char* handler)
+{
+  cmCTest::t_TestingHandlers::iterator it = m_TestingHandlers.find(handler);
+  if ( it == m_TestingHandlers.end() )
+    {
+    return 0;
+    }
+  it->second->Initialize();
+  return it->second;
+}
+
 //----------------------------------------------------------------------
 cmCTestGenericHandler* cmCTest::GetHandler(const char* handler)
 {
@@ -1858,6 +1887,12 @@ bool cmCTest::GetProduceXML()
   return m_ProduceXML;
 }
 
+//----------------------------------------------------------------------
+void cmCTest::AddSubmitFile(const char* name)
+{
+  m_SubmitFiles.insert(name);
+}
+
 //----------------------------------------------------------------------
 bool cmCTest::SetCTestConfigurationFromCMakeVariable(cmMakefile* mf, const char* dconfig, const char* cmake_var)
 {

+ 14 - 1
Source/cmCTest.h

@@ -49,6 +49,7 @@ class cmCTest
 {
 public:
   typedef std::vector<cmStdString> tm_VectorOfStrings;
+  typedef std::set<cmStdString> tm_SetOfStrings;
 
   ///! Process Command line arguments
   int Run(std::vector<std::string>const&, std::string* output = 0);
@@ -96,7 +97,7 @@ public:
    * Check if CTest file exists
    */
   bool CTestFileExists(const std::string& filename);
-  bool AddIfExists(tm_VectorOfStrings& files, const char* file);
+  bool AddIfExists(tm_SetOfStrings& files, const char* file);
 
   /**
    * Set the cmake test
@@ -231,6 +232,7 @@ public:
    * Get the handler object
    */
   cmCTestGenericHandler* GetHandler(const char* handler);
+  cmCTestGenericHandler* GetInitializedHandler(const char* handler);
 
   /*
    * Set the CTest variable from CMake variable
@@ -267,6 +269,13 @@ public:
   //! Add log to the output
   void Log(int logType, const char* file, int line, const char* msg);
 
+  //! Get the version of dart server
+  int GetDartVersion() { return m_DartVersion; }
+
+  //! Add file to be submitted
+  void AddSubmitFile(const char* name);
+  tm_SetOfStrings* GetSubmitFiles() { return &m_SubmitFiles; }
+
 private:
   std::string m_ConfigType;
   bool m_Verbose;
@@ -350,6 +359,10 @@ private:
   bool m_ShowLineNumbers;
   bool m_Quiet;
 
+  int  m_DartVersion;
+
+  std::set<cmStdString> m_SubmitFiles;
+
   
   cmGeneratedFileStream* m_OutputLogFile;
   int                    m_OutputLogFileLastTag;

+ 1 - 0
Source/kwsys/CTestConfig.cmake

@@ -1,2 +1,3 @@
 SET (CTEST_PROJECT_NAME "kwsys")
 SET (CTEST_NIGHTLY_START_TIME "21:00:00 EDT")
+SET (CTEST_DART_SERVER_VERSION "2")