some bug fixes for my recent checkins and some more cleanup

This commit is contained in:
Ken Martin 2004-09-07 09:17:15 -04:00
parent 9d6ea59a69
commit 05d985c082
9 changed files with 774 additions and 497 deletions

View File

@ -111,6 +111,8 @@ ADD_EXECUTABLE(DumpDocumentation cmDumpDocumentation)
SET(CMTEST_SRCS ctest.cxx cmCTest.cxx
CTest/cmCTestScriptHandler.cxx
CTest/cmCTestUpdateHandler.cxx
CTest/cmCTestConfigureHandler.cxx
)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/Source/CTest)

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -23,7 +23,10 @@
#include "cmGlob.h"
#include "cmDynamicLoader.h"
#include "cmCTestScriptHandler.h"
#include "cmcTestScriptHandler.h"
#include "cmcTestUpdateHandler.h"
#include "cmcTestConfigureHandler.h"
#include "cmCTestSubmit.h"
#include "curl/curl.h"
@ -42,7 +45,9 @@
#define DEBUGOUT std::cout << __LINE__ << " "; std::cout
#define DEBUGERR std::cerr << __LINE__ << " "; std::cerr
static struct tm* GetNightlyTime(std::string str, bool verbose, bool tomorrowtag)
struct tm* cmCTest::GetNightlyTime(std::string str,
bool verbose,
bool tomorrowtag)
{
struct tm* lctime;
time_t tctime = time(0);
@ -137,7 +142,7 @@ std::string cmCTest::CurrentTime()
strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t);
}
//std::cout << "Current_Time: " << current_time << std::endl;
return this->MakeXMLSafe(::CleanString(current_time));
return cmCTest::MakeXMLSafe(::CleanString(current_time));
}
static const char* cmCTestErrorMatches[] = {
@ -410,11 +415,15 @@ cmCTest::cmCTest()
m_MaximumFailedTestResultSize = 200 * 1024;
this->ScriptHandler = new cmCTestScriptHandler;
this->UpdateHandler = new cmCTestUpdateHandler;
this->ConfigureHandler = new cmCTestConfigureHandler;
}
cmCTest::~cmCTest()
{
delete this->ScriptHandler;
delete this->UpdateHandler;
delete this->ConfigureHandler;
}
int cmCTest::Initialize()
@ -492,7 +501,7 @@ int cmCTest::Initialize()
//std::cout << "TestModel: " << m_TestModel << std::endl;
if ( m_TestModel == cmCTest::NIGHTLY )
{
lctime = ::GetNightlyTime(m_DartConfiguration["NightlyStartTime"],
lctime = cmCTest::GetNightlyTime(m_DartConfiguration["NightlyStartTime"],
m_Verbose,
m_TomorrowTag);
}
@ -710,440 +719,6 @@ std::string cmCTest::FindTheExecutable(const char *exe)
return fullPath;
}
int cmCTest::UpdateDirectory()
{
int count = 0;
std::string::size_type cc, kk;
std::string cvsCommand = m_DartConfiguration["CVSCommand"];
if ( cvsCommand.size() == 0 )
{
std::cerr << "Cannot find CVSCommand key in the DartConfiguration.tcl" << std::endl;
return -1;
}
std::string cvsOptions = m_DartConfiguration["CVSUpdateOptions"];
if ( cvsOptions.size() == 0 )
{
std::cerr << "Cannot find CVSUpdateOptions key in the DartConfiguration.tcl" << std::endl;
return -1;
}
std::string sourceDirectory = m_DartConfiguration["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_TestModel == cmCTest::NIGHTLY )
{
struct tm* t = ::GetNightlyTime(m_DartConfiguration["NightlyStartTime"],
m_Verbose,
m_TomorrowTag);
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 ( !this->OpenOutputFile(m_CurrentTag, "Update.xml", os) )
{
std::cerr << "Cannot open log file" << std::endl;
}
std::string start_time = this->CurrentTime();
double elapsed_time_start = cmSystemTools::GetTime();
std::string goutput;
int retVal = 0;
bool res = true;
std::ofstream ofs;
if ( !m_ShowOnly )
{
res = cmSystemTools::RunSingleCommand(command.c_str(), &goutput,
&retVal, sourceDirectory.c_str(),
m_Verbose, 0 /*m_TimeOut*/);
if ( this->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_DartConfiguration["Site"] << "</Site>\n"
<< "\t<BuildName>" << m_DartConfiguration["BuildName"]
<< "</BuildName>\n"
<< "\t<BuildStamp>" << m_CurrentTag << "-"
<< this->GetTestModelString() << "</BuildStamp>" << std::endl;
os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
<< "\t<UpdateCommand>" << this->MakeXMLSafe(command)
<< "</UpdateCommand>\n"
<< "\t<UpdateReturnStatus>";
int failed = 0;
if ( !res || retVal )
{
os << "Update error: ";
os << this->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;
cmCTest::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>" << this->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>" << this->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>" << this->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;
}
cmCTest::UpdateFiles *u = &authors_files_map[sauthor1];
cmCTest::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;
}
cmCTest::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;
cmCTest::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 = this->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;
}
int cmCTest::ConfigureDirectory()
{
std::cout << "Configure project" << std::endl;
std::string cCommand = m_DartConfiguration["ConfigureCommand"];
if ( cCommand.size() == 0 )
{
std::cerr << "Cannot find ConfigureCommand key in the DartConfiguration.tcl"
<< std::endl;
return 1;
}
std::string buildDirectory = m_DartConfiguration["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_ShowOnly )
{
std::ofstream os;
if ( !this->OpenOutputFile(m_CurrentTag, "Configure.xml", os) )
{
std::cerr << "Cannot open configure file" << std::endl;
return 1;
}
std::string start_time = this->CurrentTime();
std::ofstream ofs;
this->OpenOutputFile("Temporary", "LastConfigure.log", ofs);
res = this->RunMakeCommand(cCommand.c_str(), &output,
&retVal, buildDirectory.c_str(),
m_Verbose, 0, ofs);
if ( ofs )
{
ofs.close();
}
if ( os )
{
this->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>" << this->MakeXMLSafe(output) << "</Log>" << std::endl;
std::string end_time = this->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;
this->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;
}
int cmCTest::BuildDirectory()
{
@ -3074,7 +2649,7 @@ int cmCTest::ProcessTests()
}
if ( m_Tests[UPDATE_TEST] || m_Tests[ALL_TEST] )
{
update_count = this->UpdateDirectory();
update_count = this->UpdateHandler->UpdateDirectory(this);
if ( update_count < 0 )
{
res |= cmCTest::UPDATE_ERRORS;
@ -3086,7 +2661,7 @@ int cmCTest::ProcessTests()
}
if ( m_Tests[CONFIGURE_TEST] || m_Tests[ALL_TEST] )
{
if (this->ConfigureDirectory())
if (this->ConfigureHandler->ConfigureDirectory(this))
{
res |= cmCTest::CONFIGURE_ERRORS;
}
@ -3885,6 +3460,8 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
{
this->m_Verbose = true;
this->ScriptHandler->SetVerbose(this->m_Verbose);
this->UpdateHandler->SetVerbose(this->m_Verbose);
this->ConfigureHandler->SetVerbose(this->m_Verbose);
}
if( arg.find("-N",0) == 0 || arg.find("--show-only",0) == 0 )
@ -5060,3 +4637,19 @@ void cmCTest::ExpandTestsToRunInformation(int numTests)
}
std::cout << "\n";
}
std::string cmCTest::GetDartConfiguration(const char *name)
{
return m_DartConfiguration[name];
}
std::string cmCTest::GetCurrentTag()
{
return m_CurrentTag;
}
bool cmCTest::GetShowOnly()
{
return m_ShowOnly;
}

View File

@ -24,6 +24,8 @@
class cmMakefile;
class cmCTestScriptHandler;
class cmCTestUpdateHandler;
class cmCTestConfigureHandler;
class cmCTest
{
@ -52,6 +54,18 @@ public:
*/
int ProcessTests();
/*
* A utility function that returns the nightly time
*/
static struct tm* cmCTest::GetNightlyTime(std::string str,
bool verbose,
bool tomorrowtag);
/*
* Is the tomorrow tag set?
*/
bool GetTomorrowTag() { return m_TomorrowTag; };
/**
* Try to build the project
*/
@ -67,16 +81,6 @@ public:
*/
int CoverageDirectory();
/**
* Do revision control update of directory
*/
int UpdateDirectory();
/**
* Do configure the project
*/
int ConfigureDirectory();
/**
* Do submit testing results
*/
@ -109,10 +113,13 @@ public:
* Set the cmake test mode (experimental, nightly, continuous).
*/
void SetTestModel(int mode);
int GetTestModel() { return m_TestModel; };
std::string GetTestModelString();
static int GetTestModelFromString(const char* str);
std::string GetDartConfiguration(const char *name);
/**
* constructor and destructor
*/
@ -132,7 +139,6 @@ public:
std::string m_ConfigType;
bool m_Verbose;
bool m_DartMode;
bool m_ShowOnly;
bool m_ForceNewCTestProcess;
@ -155,14 +161,46 @@ public:
int GenerateNotesFile(const char* files);
bool OpenOutputFile(const std::string& path,
const std::string& name, std::ofstream& stream);
static std::string MakeXMLSafe(const std::string&);
static std::string MakeURLSafe(const std::string&);
/*
* return the current tag
*/
std::string GetCurrentTag();
///! Get the current time as string
std::string CurrentTime();
///! Should we only show what we would do?
bool GetShowOnly();
//! Start CTest XML output file
void StartXML(std::ostream& ostr);
//! End CTest XML output file
void EndXML(std::ostream& ostr);
//! Run command specialized for make and configure. Returns process status
// and retVal is return value or exception.
int RunMakeCommand(const char* command, std::string* output,
int* retVal, const char* dir, bool verbose, int timeout,
std::ofstream& ofs);
private:
// this is a helper class than handles running test scripts
cmCTestScriptHandler *ScriptHandler;
// these are helper classes
cmCTestScriptHandler *ScriptHandler;
cmCTestUpdateHandler *UpdateHandler;
cmCTestConfigureHandler *ConfigureHandler;
void SetTestsToRunInformation(const char*);
void ExpandTestsToRunInformation(int numPossibleTests);
std::string TestsToRunString;
bool m_ShowOnly;
enum {
FIRST_TEST = 0,
UPDATE_TEST = 1,
@ -260,12 +298,6 @@ private:
typedef std::vector<cmCTestTestProperties> tm_ListOfTests;
// 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>{};
struct cmCTestCoverage
{
@ -381,17 +413,6 @@ private:
std::vector<cmCTestBuildErrorWarning>,
double elapsed_time);
bool OpenOutputFile(const std::string& path,
const std::string& name, std::ofstream& stream);
std::string MakeXMLSafe(const std::string&);
std::string MakeURLSafe(const std::string&);
//! Run command specialized for make and configure. Returns process status
// and retVal is return value or exception.
int RunMakeCommand(const char* command, std::string* output,
int* retVal, const char* dir, bool verbose, int timeout,
std::ofstream& ofs);
//! Run command specialized for tests. Returns process status and retVal is
// return value or exception.
int RunTest(std::vector<const char*> args, std::string* output, int *retVal,
@ -400,12 +421,6 @@ private:
std::string GenerateRegressionImages(const std::string& xml);
const char* GetTestStatus(int status);
//! Start CTest XML output file
void StartXML(std::ostream& ostr);
//! End CTest XML output file
void EndXML(std::ostream& ostr);
//! Create not from files.
int GenerateDartNotesOutput(std::ostream& os, const tm_VectorOfStrings& files);
@ -422,9 +437,6 @@ private:
///! Find the running cmake
void FindRunningCMake(const char* arg0);
///! Get the current time as string
std::string CurrentTime();
///! Maximum size of testing string
std::string::size_type m_MaximumPassedTestResultSize;
std::string::size_type m_MaximumFailedTestResultSize;