summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
authorKen Martin <ken.martin@kitware.com>2004-09-07 13:17:15 (GMT)
committerKen Martin <ken.martin@kitware.com>2004-09-07 13:17:15 (GMT)
commit05d985c08277350c3a1ca5ea6023ac397cf9bf1b (patch)
tree3de2553519af7ff8543538831f2f7017cd44efe7 /Source/CTest
parent9d6ea59a69542b008d296bc4ce42d975f4020d53 (diff)
downloadCMake-05d985c08277350c3a1ca5ea6023ac397cf9bf1b.zip
CMake-05d985c08277350c3a1ca5ea6023ac397cf9bf1b.tar.gz
CMake-05d985c08277350c3a1ca5ea6023ac397cf9bf1b.tar.bz2
some bug fixes for my recent checkins and some more cleanup
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestConfigureHandler.cxx114
-rw-r--r--Source/CTest/cmCTestConfigureHandler.h53
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx66
-rw-r--r--Source/CTest/cmCTestScriptHandler.h5
-rw-r--r--Source/CTest/cmCTestUpdateHandler.cxx407
-rw-r--r--Source/CTest/cmCTestUpdateHandler.h59
6 files changed, 687 insertions, 17 deletions
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
new file mode 100644
index 0000000..65950a7
--- /dev/null
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -0,0 +1,114 @@
+/*=========================================================================
+
+ 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 "cmCTestConfigureHandler.h"
+
+#include "cmCTest.h"
+#include "cmake.h"
+#include <cmsys/Process.h>
+
+
+//----------------------------------------------------------------------
+cmCTestConfigureHandler::cmCTestConfigureHandler()
+{
+ m_Verbose = false;
+ m_CTest = 0;
+}
+
+
+//----------------------------------------------------------------------
+//clearly it would be nice if this were broken up into a few smaller
+//functions and commented...
+int cmCTestConfigureHandler::ConfigureDirectory(cmCTest *ctest_inst)
+{
+ m_CTest = ctest_inst;
+
+ std::cout << "Configure project" << std::endl;
+ std::string cCommand = m_CTest->GetDartConfiguration("ConfigureCommand");
+ if ( cCommand.size() == 0 )
+ {
+ std::cerr << "Cannot find ConfigureCommand key in the DartConfiguration.tcl"
+ << std::endl;
+ return 1;
+ }
+
+ std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory");
+ if ( buildDirectory.size() == 0 )
+ {
+ std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl;
+ return 1;
+ }
+
+ double elapsed_time_start = cmSystemTools::GetTime();
+ std::string output;
+ int retVal = 0;
+ int res = 0;
+ if ( !m_CTest->GetShowOnly() )
+ {
+ std::ofstream os;
+ if ( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Configure.xml", os) )
+ {
+ std::cerr << "Cannot open configure file" << std::endl;
+ return 1;
+ }
+ std::string start_time = m_CTest->CurrentTime();
+
+ std::ofstream ofs;
+ m_CTest->OpenOutputFile("Temporary", "LastConfigure.log", ofs);
+ res = m_CTest->RunMakeCommand(cCommand.c_str(), &output,
+ &retVal, buildDirectory.c_str(),
+ m_Verbose, 0, ofs);
+
+ if ( ofs )
+ {
+ ofs.close();
+ }
+
+ if ( os )
+ {
+ m_CTest->StartXML(os);
+ os << "<Configure>\n"
+ << "\t<StartDateTime>" << start_time << "</StartDateTime>" << std::endl;
+ if ( res == cmsysProcess_State_Exited && retVal )
+ {
+ os << retVal;
+ }
+ os << "<ConfigureCommand>" << cCommand.c_str() << "</ConfigureCommand>" << std::endl;
+ //std::cout << "End" << std::endl;
+ os << "<Log>" << cmCTest::MakeXMLSafe(output) << "</Log>" << std::endl;
+ std::string end_time = m_CTest->CurrentTime();
+ os << "\t<ConfigureStatus>" << retVal << "</ConfigureStatus>\n"
+ << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
+ << "<ElapsedMinutes>"
+ << static_cast<int>(
+ (cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
+ << "</ElapsedMinutes>"
+ << "</Configure>" << std::endl;
+ m_CTest->EndXML(os);
+ }
+ }
+ else
+ {
+ std::cout << "Configure with command: " << cCommand << std::endl;
+ }
+ if (! res || retVal )
+ {
+ std::cerr << "Error(s) when updating the project" << std::endl;
+ return 1;
+ }
+ return 0;
+}
diff --git a/Source/CTest/cmCTestConfigureHandler.h b/Source/CTest/cmCTestConfigureHandler.h
new file mode 100644
index 0000000..5a66c1a
--- /dev/null
+++ b/Source/CTest/cmCTestConfigureHandler.h
@@ -0,0 +1,53 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc. 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 cmCTestConfigureHandler_h
+#define cmCTestConfigureHandler_h
+
+
+#include "cmStandardIncludes.h"
+#include "cmListFileCache.h"
+
+class cmCTest;
+
+/** \class cmCTestConfigureHandler
+ * \brief A class that handles ctest -S invocations
+ *
+ */
+class cmCTestConfigureHandler
+{
+public:
+
+ /*
+ * The main entry point for this class
+ */
+ int ConfigureDirectory(cmCTest *);
+
+ /*
+ * If verbose then more informaiton is printed out
+ */
+ void SetVerbose(bool val) { m_Verbose = val; }
+
+ cmCTestConfigureHandler();
+
+private:
+ bool m_Verbose;
+ cmCTest *m_CTest;
+
+};
+
+#endif
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 04c414a..2d35f97 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -48,7 +48,9 @@ cmCTestScriptHandler::cmCTestScriptHandler()
m_Backup = false;
m_Makefile = 0;
m_LocalGenerator = 0;
-
+ m_CMake = 0;
+ m_GlobalGenerator = 0;
+
// the *60 is becuase the settings are in minutes but GetTime is seconds
m_MinimumInterval = 30*60;
}
@@ -57,16 +59,23 @@ cmCTestScriptHandler::cmCTestScriptHandler()
//----------------------------------------------------------------------
cmCTestScriptHandler::~cmCTestScriptHandler()
{
- if (m_Makefile)
- {
- delete m_Makefile;
- }
+ // local generator owns the makefile
m_Makefile = 0;
if (m_LocalGenerator)
{
delete m_LocalGenerator;
}
m_LocalGenerator = 0;
+ if (m_GlobalGenerator)
+ {
+ delete m_GlobalGenerator;
+ }
+ m_GlobalGenerator = 0;
+ if (m_CMake)
+ {
+ delete m_CMake;
+ }
+ m_CMake = 0;
}
@@ -121,18 +130,20 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
}
// create a cmake instance to read the configuration script
- cmake cm;
- cmGlobalGenerator gg;
- gg.SetCMakeInstance(&cm);
-
// read in the list file to fill the cache
- if (m_LocalGenerator)
+ if (m_CMake)
{
+ delete m_CMake;
+ delete m_GlobalGenerator;
delete m_LocalGenerator;
}
- m_LocalGenerator = gg.CreateLocalGenerator();
- m_LocalGenerator->SetGlobalGenerator(&gg);
+ m_CMake = new cmake;
+ m_GlobalGenerator = new cmGlobalGenerator;
+ m_GlobalGenerator->SetCMakeInstance(m_CMake);
+ m_LocalGenerator = m_GlobalGenerator->CreateLocalGenerator();
+ m_LocalGenerator->SetGlobalGenerator(m_GlobalGenerator);
+
// set a variable with the path to the current script
m_LocalGenerator->GetMakefile()->AddDefinition("CTEST_SCRIPT_DIRECTORY",
cmSystemTools::GetFilenamePath(
@@ -163,14 +174,31 @@ int cmCTestScriptHandler::ExtractVariables()
{
// get some info that should be set
m_Makefile = m_LocalGenerator->GetMakefile();
+
+ m_SourceDir.clear();
+ m_BinaryDir.clear();
+ m_CTestCmd.clear();
- m_SourceDir = m_Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY");
- m_BinaryDir = m_Makefile->GetDefinition("CTEST_BINARY_DIRECTORY");
- m_CTestCmd = m_Makefile->GetDefinition("CTEST_COMMAND");
+ if (m_Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"))
+ {
+ m_SourceDir = m_Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY");
+ }
+ if (m_Makefile->GetDefinition("CTEST_BINARY_DIRECTORY"))
+ {
+ m_BinaryDir = m_Makefile->GetDefinition("CTEST_BINARY_DIRECTORY");
+ }
+ if (m_Makefile->GetDefinition("CTEST_COMMAND"))
+ {
+ m_CTestCmd = m_Makefile->GetDefinition("CTEST_COMMAND");
+ }
m_Backup = m_Makefile->IsOn("CTEST_BACKUP_AND_RESTORE");
// in order to backup and restore we also must have the cvs root
- m_CVSCheckOut = m_Makefile->GetDefinition("CTEST_CVS_CHECKOUT");
+ m_CVSCheckOut.clear();
+ if (m_Makefile->GetDefinition("CTEST_CVS_CHECKOUT"))
+ {
+ m_CVSCheckOut = m_Makefile->GetDefinition("CTEST_CVS_CHECKOUT");
+ }
if (m_Backup && m_CVSCheckOut.empty())
{
cmSystemTools::Error(
@@ -213,7 +241,11 @@ int cmCTestScriptHandler::ExtractVariables()
atof(m_Makefile->GetDefinition("CTEST_CONTINUOUS_MINIMUM_INTERVAL"));
}
- m_CVSCmd = m_Makefile->GetDefinition("CTEST_CVS_COMMAND");
+ m_CVSCmd.clear();
+ if (m_Makefile->GetDefinition("CTEST_CVS_COMMAND"))
+ {
+ m_CVSCmd = m_Makefile->GetDefinition("CTEST_CVS_COMMAND");
+ }
return 0;
}
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index 4a904f7..acddad2 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -24,6 +24,8 @@
class cmMakefile;
class cmLocalGenerator;
+class cmGlobalGenerator;
+class cmake;
/** \class cmCTestScriptHandler
* \brief A class that handles ctest -S invocations
@@ -91,6 +93,9 @@ private:
cmMakefile *m_Makefile;
cmLocalGenerator *m_LocalGenerator;
+ cmGlobalGenerator *m_GlobalGenerator;
+ cmake *m_CMake;
+
};
#endif
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
new file mode 100644
index 0000000..139f7d2
--- /dev/null
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -0,0 +1,407 @@
+/*=========================================================================
+
+ 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 "cmCTestUpdateHandler.h"
+
+#include "cmCTest.h"
+#include "cmake.h"
+#include "cmMakefile.h"
+#include "cmLocalGenerator.h"
+#include "cmGlobalGenerator.h"
+
+//#include <cmsys/RegularExpression.hxx>
+#include <cmsys/Process.h>
+
+// used for sleep
+#ifdef _WIN32
+#include "windows.h"
+#endif
+
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+#include <float.h>
+
+
+//----------------------------------------------------------------------
+cmCTestUpdateHandler::cmCTestUpdateHandler()
+{
+ m_Verbose = false;
+ m_CTest = 0;
+}
+
+
+//----------------------------------------------------------------------
+//clearly it would be nice if this were broken up into a few smaller
+//functions and commented...
+int cmCTestUpdateHandler::UpdateDirectory(cmCTest *ctest_inst)
+{
+ m_CTest = ctest_inst;
+
+ int count = 0;
+ std::string::size_type cc, kk;
+ std::string cvsCommand = m_CTest->GetDartConfiguration("CVSCommand");
+ if ( cvsCommand.size() == 0 )
+ {
+ std::cerr << "Cannot find CVSCommand key in the DartConfiguration.tcl" << std::endl;
+ return -1;
+ }
+ std::string cvsOptions = m_CTest->GetDartConfiguration("CVSUpdateOptions");
+ if ( cvsOptions.size() == 0 )
+ {
+ std::cerr << "Cannot find CVSUpdateOptions key in the DartConfiguration.tcl" << std::endl;
+ return -1;
+ }
+
+ std::string sourceDirectory = m_CTest->GetDartConfiguration("SourceDirectory");
+ if ( sourceDirectory.size() == 0 )
+ {
+ std::cerr << "Cannot find SourceDirectory key in the DartConfiguration.tcl" << std::endl;
+ return -1;
+ }
+
+ std::string extra_update_opts;
+ if ( m_CTest->GetTestModel() == cmCTest::NIGHTLY )
+ {
+ struct tm* t = cmCTest::GetNightlyTime(m_CTest->GetDartConfiguration("NightlyStartTime"),
+ m_Verbose, m_CTest->GetTomorrowTag());
+ char current_time[1024];
+ sprintf(current_time, "%04d-%02d-%02d %02d:%02d:%02d UTC",
+ t->tm_year + 1900,
+ t->tm_mon + 1,
+ t->tm_mday,
+ t->tm_hour,
+ t->tm_min,
+ t->tm_sec);
+ std::string today_update_date = current_time;
+
+ extra_update_opts += "-D \"" + today_update_date +"\"";
+ //std::cout << "Update: " << extra_update_opts << std::endl;
+ }
+
+ std::string command = cvsCommand + " -z3 update " + cvsOptions +
+ " " + extra_update_opts;
+ std::ofstream os;
+ if ( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Update.xml", os) )
+ {
+ std::cerr << "Cannot open log file" << std::endl;
+ }
+ std::string start_time = m_CTest->CurrentTime();
+ double elapsed_time_start = cmSystemTools::GetTime();
+
+ std::string goutput;
+ int retVal = 0;
+ bool res = true;
+ std::ofstream ofs;
+ if ( !m_CTest->GetShowOnly() )
+ {
+ res = cmSystemTools::RunSingleCommand(command.c_str(), &goutput,
+ &retVal, sourceDirectory.c_str(),
+ m_Verbose, 0 /*m_TimeOut*/);
+ if ( m_CTest->OpenOutputFile("Temporary", "LastUpdate.log", ofs) )
+ {
+ ofs << goutput << std::endl;;
+ }
+ }
+ else
+ {
+ std::cout << "Update with command: " << command << std::endl;
+ }
+
+ os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ << "<Update mode=\"Client\" Generator=\"ctest-" << CMake_VERSION_FULL << "\">\n"
+ << "\t<Site>" << m_CTest->GetDartConfiguration("Site") << "</Site>\n"
+ << "\t<BuildName>" << m_CTest->GetDartConfiguration("BuildName")
+ << "</BuildName>\n"
+ << "\t<BuildStamp>" << m_CTest->GetCurrentTag() << "-"
+ << m_CTest->GetTestModelString() << "</BuildStamp>" << std::endl;
+ os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
+ << "\t<UpdateCommand>" << m_CTest->MakeXMLSafe(command)
+ << "</UpdateCommand>\n"
+ << "\t<UpdateReturnStatus>";
+ int failed = 0;
+ if ( !res || retVal )
+ {
+ os << "Update error: ";
+ os << m_CTest->MakeXMLSafe(goutput);
+ std::cerr << "Update with command: " << command << " failed" << std::endl;
+ failed = 1;
+ }
+ os << "</UpdateReturnStatus>" << std::endl;
+ if ( !failed )
+ {
+
+ std::vector<cmStdString> lines;
+ cmSystemTools::Split(goutput.c_str(), lines);
+ std::cout << "Updated; gathering version information" << std::endl;
+ cmsys::RegularExpression date_author("^date: +([^;]+); +author: +([^;]+); +state: +[^;]+;");
+ cmsys::RegularExpression revision("^revision +([^ ]*) *$");
+ cmsys::RegularExpression end_of_file("^=============================================================================$");
+ cmsys::RegularExpression end_of_comment("^----------------------------$");
+ std::string current_path = "<no-path>";
+ bool first_file = true;
+
+ cmCTestUpdateHandler::AuthorsToUpdatesMap authors_files_map;
+ int num_updated = 0;
+ int num_modified = 0;
+ int num_conflicting = 0;
+ for ( cc= 0 ; cc < lines.size(); cc ++ )
+ {
+ const char* line = lines[cc].c_str();
+ char mod = line[0];
+ if ( line[1] == ' ' && mod != '?' )
+ {
+ if ( mod != 'M' && mod != 'C' )
+ {
+ count ++;
+ }
+ const char* file = line + 2;
+ //std::cout << "Line" << cc << ": " << mod << " - " << file << std::endl;
+ std::string logcommand = cvsCommand + " -z3 log -N " + file;
+ //std::cout << "Do log: " << logcommand << std::endl;
+ std::string output;
+ res = cmSystemTools::RunSingleCommand(logcommand.c_str(), &output,
+ &retVal, sourceDirectory.c_str(),
+ m_Verbose, 0 /*m_TimeOut*/);
+ if ( ofs )
+ {
+ ofs << output << std::endl;
+ }
+ if ( res && retVal == 0)
+ {
+ //std::cout << output << std::endl;
+ std::vector<cmStdString> ulines;
+ cmSystemTools::Split(output.c_str(), ulines);
+ std::string::size_type sline = 0;
+ std::string srevision1 = "Unknown";
+ std::string sdate1 = "Unknown";
+ std::string sauthor1 = "Unknown";
+ std::string semail1 = "Unknown";
+ std::string comment1 = "";
+ std::string srevision2 = "Unknown";
+ std::string sdate2 = "Unknown";
+ std::string sauthor2 = "Unknown";
+ std::string comment2 = "";
+ std::string semail2 = "Unknown";
+ bool have_first = false;
+ bool have_second = false;
+ for ( kk = 0; kk < ulines.size(); kk ++ )
+ {
+ const char* clp = ulines[kk].c_str();
+ if ( !have_second && !sline && revision.find(clp) )
+ {
+ if ( !have_first )
+ {
+ srevision1 = revision.match(1);
+ }
+ else
+ {
+ srevision2 = revision.match(1);
+ }
+ }
+ else if ( !have_second && !sline && date_author.find(clp) )
+ {
+ sline = kk + 1;
+ if ( !have_first )
+ {
+ sdate1 = date_author.match(1);
+ sauthor1 = date_author.match(2);
+ }
+ else
+ {
+ sdate2 = date_author.match(1);
+ sauthor2 = date_author.match(2);
+ }
+ }
+ else if ( sline && end_of_comment.find(clp) || end_of_file.find(clp))
+ {
+ if ( !have_first )
+ {
+ have_first = true;
+ }
+ else if ( !have_second )
+ {
+ have_second = true;
+ }
+ sline = 0;
+ }
+ else if ( sline )
+ {
+ if ( !have_first )
+ {
+ comment1 += clp;
+ comment1 += "\n";
+ }
+ else
+ {
+ comment2 += clp;
+ comment2 += "\n";
+ }
+ }
+ }
+ if ( mod == 'M' )
+ {
+ comment1 = "Locally modified file\n";
+ }
+ if ( mod == 'C' )
+ {
+ comment1 = "Conflict while updating\n";
+ }
+ std::string path = cmSystemTools::GetFilenamePath(file);
+ std::string fname = cmSystemTools::GetFilenameName(file);
+ if ( path != current_path )
+ {
+ if ( !first_file )
+ {
+ os << "\t</Directory>" << std::endl;
+ }
+ else
+ {
+ first_file = false;
+ }
+ os << "\t<Directory>\n"
+ << "\t\t<Name>" << path << "</Name>" << std::endl;
+ }
+ if ( mod == 'C' )
+ {
+ num_conflicting ++;
+ os << "\t<Conflicting>" << std::endl;
+ }
+ else if ( mod == 'M' )
+ {
+ num_modified ++;
+ os << "\t<Modified>" << std::endl;
+ }
+ else
+ {
+ num_updated ++;
+ os << "\t<Updated>" << std::endl;
+ }
+ if ( srevision2 == "Unknown" )
+ {
+ srevision2 = srevision1;
+ }
+ os << "\t\t<File Directory=\"" << path << "\">" << fname
+ << "</File>\n"
+ << "\t\t<Directory>" << path << "</Directory>\n"
+ << "\t\t<FullName>" << file << "</FullName>\n"
+ << "\t\t<CheckinDate>" << sdate1 << "</CheckinDate>\n"
+ << "\t\t<Author>" << sauthor1 << "</Author>\n"
+ << "\t\t<Email>" << semail1 << "</Email>\n"
+ << "\t\t<Log>" << cmCTest::MakeXMLSafe(comment1) << "</Log>\n"
+ << "\t\t<Revision>" << srevision1 << "</Revision>\n"
+ << "\t\t<PriorRevision>" << srevision2 << "</PriorRevision>"
+ << std::endl;
+ if ( srevision2 != srevision1 )
+ {
+ os
+ << "\t\t<Revisions>\n"
+ << "\t\t\t<Revision>" << srevision1 << "</Revision>\n"
+ << "\t\t\t<PreviousRevision>" << srevision2 << "</PreviousRevision>\n"
+ << "\t\t\t<Author>" << sauthor1<< "</Author>\n"
+ << "\t\t\t<Date>" << sdate1 << "</Date>\n"
+ << "\t\t\t<Comment>" << cmCTest::MakeXMLSafe(comment1) << "</Comment>\n"
+ << "\t\t\t<Email>" << semail1 << "</Email>\n"
+ << "\t\t</Revisions>\n"
+ << "\t\t<Revisions>\n"
+ << "\t\t\t<Revision>" << srevision2 << "</Revision>\n"
+ << "\t\t\t<PreviousRevision>" << srevision2 << "</PreviousRevision>\n"
+ << "\t\t\t<Author>" << sauthor2<< "</Author>\n"
+ << "\t\t\t<Date>" << sdate2 << "</Date>\n"
+ << "\t\t\t<Comment>" << cmCTest::MakeXMLSafe(comment2) << "</Comment>\n"
+ << "\t\t\t<Email>" << semail2 << "</Email>\n"
+ << "\t\t</Revisions>" << std::endl;
+ }
+ if ( mod == 'C' )
+ {
+ os << "\t</Conflicting>" << std::endl;
+ }
+ else if ( mod == 'M' )
+ {
+ os << "\t</Modified>" << std::endl;
+ }
+ else
+ {
+ os << "\t</Updated>" << std::endl;
+ }
+ cmCTestUpdateHandler::UpdateFiles *u = &authors_files_map[sauthor1];
+ cmCTestUpdateHandler::StringPair p;
+ p.first = path;
+ p.second = fname;
+ u->push_back(p);
+
+ current_path = path;
+ }
+ }
+ }
+ if ( num_updated )
+ {
+ std::cout << "Found " << num_updated << " updated files" << std::endl;
+ }
+ if ( num_modified )
+ {
+ std::cout << "Found " << num_modified << " locally modified files"
+ << std::endl;
+ }
+ if ( num_conflicting )
+ {
+ std::cout << "Found " << num_conflicting << " conflicting files"
+ << std::endl;
+ }
+ if ( !first_file )
+ {
+ os << "\t</Directory>" << std::endl;
+ }
+
+ cmCTestUpdateHandler::AuthorsToUpdatesMap::iterator it;
+ for ( it = authors_files_map.begin();
+ it != authors_files_map.end();
+ it ++ )
+ {
+ os << "\t<Author>\n"
+ << "\t\t<Name>" << it->first << "</Name>" << std::endl;
+ cmCTestUpdateHandler::UpdateFiles *u = &(it->second);
+ for ( cc = 0; cc < u->size(); cc ++ )
+ {
+ os << "\t\t<File Directory=\"" << (*u)[cc].first << "\">"
+ << (*u)[cc].second << "</File>" << std::endl;
+ }
+ os << "\t</Author>" << std::endl;
+ }
+ }
+
+ //std::cout << "End" << std::endl;
+ std::string end_time = m_CTest->CurrentTime();
+ os << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
+ << "<ElapsedMinutes>" <<
+ static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
+ << "</ElapsedMinutes>"
+ << "</Update>" << std::endl;
+
+ if ( ofs )
+ {
+ ofs.close();
+ }
+
+ if (! res || retVal )
+ {
+ std::cerr << "Error(s) when updating the project" << std::endl;
+ std::cerr << "Output: " << goutput << std::endl;
+ return -1;
+ }
+ return count;
+}
diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h
new file mode 100644
index 0000000..14ef61c
--- /dev/null
+++ b/Source/CTest/cmCTestUpdateHandler.h
@@ -0,0 +1,59 @@
+/*=========================================================================
+
+ Program: CMake - Cross-Platform Makefile Generator
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc. 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 cmCTestUpdateHandler_h
+#define cmCTestUpdateHandler_h
+
+
+#include "cmStandardIncludes.h"
+#include "cmListFileCache.h"
+
+class cmCTest;
+
+/** \class cmCTestUpdateHandler
+ * \brief A class that handles ctest -S invocations
+ *
+ */
+class cmCTestUpdateHandler
+{
+public:
+
+ /*
+ * The main entry point for this class
+ */
+ int UpdateDirectory(cmCTest *);
+
+ /*
+ * If verbose then more informaiton is printed out
+ */
+ void SetVerbose(bool val) { m_Verbose = val; }
+
+ cmCTestUpdateHandler();
+
+private:
+ bool m_Verbose;
+ cmCTest *m_CTest;
+
+ // Some structures needed for cvs update
+ struct StringPair :
+ public std::pair<std::string, std::string>{};
+ struct UpdateFiles : public std::vector<StringPair>{};
+ struct AuthorsToUpdatesMap :
+ public std::map<std::string, UpdateFiles>{};
+};
+
+#endif