ENH: Several cleanups and make sure things get propagated where they should. Also, allow to load CTest custom files to the actual ctest -S script
This commit is contained in:
parent
b75166ea45
commit
386900bfdd
|
@ -39,61 +39,8 @@ cmCTestBuildCommand::~cmCTestBuildCommand()
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool cmCTestBuildCommand::InitialPass(
|
cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
|
||||||
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 )
|
|
||||||
{
|
|
||||||
this->CTest->SetCTestConfiguration("BuildDirectory", build_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmCTestGenericHandler* handler
|
cmCTestGenericHandler* handler
|
||||||
= this->CTest->GetInitializedHandler("build");
|
= this->CTest->GetInitializedHandler("build");
|
||||||
if ( !handler )
|
if ( !handler )
|
||||||
|
@ -161,14 +108,7 @@ bool cmCTestBuildCommand::InitialPass(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = handler->ProcessHandler();
|
return handler;
|
||||||
if ( res_var )
|
|
||||||
{
|
|
||||||
cmOStringStream str;
|
|
||||||
str << res;
|
|
||||||
this->Makefile->AddDefinition(res_var, str.str().c_str());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#ifndef cmCTestBuildCommand_h
|
#ifndef cmCTestBuildCommand_h
|
||||||
#define cmCTestBuildCommand_h
|
#define cmCTestBuildCommand_h
|
||||||
|
|
||||||
#include "cmCTestCommand.h"
|
#include "cmCTestHandlerCommand.h"
|
||||||
|
|
||||||
class cmGlobalGenerator;
|
class cmGlobalGenerator;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class cmGlobalGenerator;
|
||||||
*
|
*
|
||||||
* cmCTestBuildCommand defineds the command to build the project.
|
* cmCTestBuildCommand defineds the command to build the project.
|
||||||
*/
|
*/
|
||||||
class cmCTestBuildCommand : public cmCTestCommand
|
class cmCTestBuildCommand : public cmCTestHandlerCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -44,12 +44,6 @@ public:
|
||||||
return ni;
|
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.
|
* The name of the command as specified in CMakeList.txt.
|
||||||
*/
|
*/
|
||||||
|
@ -73,9 +67,12 @@ public:
|
||||||
"Builds the given build directory and stores results in Build.xml.";
|
"Builds the given build directory and stores results in Build.xml.";
|
||||||
}
|
}
|
||||||
|
|
||||||
cmTypeMacro(cmCTestBuildCommand, cmCTestCommand);
|
cmTypeMacro(cmCTestBuildCommand, cmCTestHandlerCommand);
|
||||||
|
|
||||||
cmGlobalGenerator* GlobalGenerator;
|
cmGlobalGenerator* GlobalGenerator;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cmCTestGenericHandler* InitializeHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -222,18 +222,18 @@ void cmCTestBuildHandler::Initialize()
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf)
|
void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf)
|
||||||
{
|
{
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_MATCH",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_MATCH",
|
||||||
this->CustomErrorMatches);
|
this->CustomErrorMatches);
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_EXCEPTION",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_EXCEPTION",
|
||||||
this->CustomErrorExceptions);
|
this->CustomErrorExceptions);
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_MATCH",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_MATCH",
|
||||||
this->CustomWarningMatches);
|
this->CustomWarningMatches);
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_EXCEPTION",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_EXCEPTION",
|
||||||
this->CustomWarningExceptions);
|
this->CustomWarningExceptions);
|
||||||
cmCTest::PopulateCustomInteger(mf,
|
this->CTest->PopulateCustomInteger(mf,
|
||||||
"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS",
|
"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS",
|
||||||
this->MaxErrors);
|
this->MaxErrors);
|
||||||
cmCTest::PopulateCustomInteger(mf,
|
this->CTest->PopulateCustomInteger(mf,
|
||||||
"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS",
|
"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS",
|
||||||
this->MaxWarnings);
|
this->MaxWarnings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,98 +19,35 @@
|
||||||
#include "cmCTest.h"
|
#include "cmCTest.h"
|
||||||
#include "cmCTestGenericHandler.h"
|
#include "cmCTestGenericHandler.h"
|
||||||
|
|
||||||
bool cmCTestConfigureCommand::InitialPass(
|
cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
|
||||||
std::vector<std::string> const& args)
|
|
||||||
{
|
{
|
||||||
const char* source_dir = 0;
|
if ( this->Values[ct_BUILD] )
|
||||||
const char* build_dir = 0;
|
|
||||||
const char* res_var = 0;
|
|
||||||
|
|
||||||
bool havereturn_variable = false;
|
|
||||||
bool havesource = false;
|
|
||||||
bool havebuild = false;
|
|
||||||
for(size_t i=0; i < args.size(); ++i)
|
|
||||||
{
|
{
|
||||||
if ( havereturn_variable )
|
this->CTest->SetCTestConfiguration("BuildDirectory",
|
||||||
{
|
this->Values[ct_BUILD]);
|
||||||
res_var = args[i].c_str();
|
|
||||||
havereturn_variable = false;
|
|
||||||
}
|
|
||||||
else if ( havebuild )
|
|
||||||
{
|
|
||||||
build_dir = args[i].c_str();
|
|
||||||
havebuild = false;
|
|
||||||
}
|
|
||||||
else if ( havesource )
|
|
||||||
{
|
|
||||||
source_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] == "SOURCE")
|
|
||||||
{
|
|
||||||
if ( source_dir )
|
|
||||||
{
|
|
||||||
this->SetError("called with incorrect number of arguments. "
|
|
||||||
"SOURCE specified twice.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
havesource = true;
|
|
||||||
}
|
|
||||||
else if(args[i] == "BUILD")
|
|
||||||
{
|
|
||||||
if ( build_dir )
|
|
||||||
{
|
|
||||||
this->SetError("called with incorrect number of arguments. "
|
|
||||||
"BUILD specified twice.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
havebuild = 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 ( source_dir )
|
|
||||||
{
|
|
||||||
this->CTest->SetCTestConfiguration("SourceDirectory", source_dir);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
source_dir = this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY");
|
this->CTest->SetCTestConfiguration("BuildDirectory",
|
||||||
|
this->Makefile->GetDefinition("CTEST_BINARY_DIRECTORY"));
|
||||||
}
|
}
|
||||||
|
if ( this->Values[ct_SOURCE] )
|
||||||
if ( build_dir )
|
|
||||||
{
|
{
|
||||||
this->CTest->SetCTestConfiguration("BuildDirectory", build_dir);
|
this->CTest->SetCTestConfiguration("SourceDirectory",
|
||||||
|
this->Values[ct_SOURCE]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build_dir = this->Makefile->GetDefinition("CTEST_BINARY_DIRECTORY");
|
this->CTest->SetCTestConfiguration("SourceDirectory",
|
||||||
if ( !build_dir )
|
this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"));
|
||||||
{
|
}
|
||||||
this->SetError("Build directory not specified. Either use BUILD "
|
if ( this->CTest->GetCTestConfiguration("BuildDirectory").empty() )
|
||||||
"argument to CTEST_CONFIGURE command or set CTEST_BINARY_DIRECTORY "
|
{
|
||||||
"variable");
|
this->SetError("Build directory not specified. Either use BUILD "
|
||||||
return false;
|
"argument to CTEST_CONFIGURE command or set CTEST_BINARY_DIRECTORY "
|
||||||
}
|
"variable");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* ctestConfigureCommand
|
const char* ctestConfigureCommand
|
||||||
= this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
|
= this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
|
||||||
|
@ -125,6 +62,15 @@ bool cmCTestConfigureCommand::InitialPass(
|
||||||
= this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
|
= this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
|
||||||
if ( cmakeGeneratorName && *cmakeGeneratorName )
|
if ( cmakeGeneratorName && *cmakeGeneratorName )
|
||||||
{
|
{
|
||||||
|
const std::string& source_dir
|
||||||
|
= this->CTest->GetCTestConfiguration("SourceDirectory");
|
||||||
|
if ( source_dir.empty() )
|
||||||
|
{
|
||||||
|
this->SetError("Source directory not specified. Either use SOURCE "
|
||||||
|
"argument to CTEST_CONFIGURE command or set CTEST_SOURCE_DIRECTORY "
|
||||||
|
"variable");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
std::string cmakeConfigureCommand = "\"";
|
std::string cmakeConfigureCommand = "\"";
|
||||||
cmakeConfigureCommand += this->CTest->GetCMakeExecutable();
|
cmakeConfigureCommand += this->CTest->GetCMakeExecutable();
|
||||||
cmakeConfigureCommand += "\" \"-G";
|
cmakeConfigureCommand += "\" \"-G";
|
||||||
|
@ -152,14 +98,7 @@ bool cmCTestConfigureCommand::InitialPass(
|
||||||
"internal CTest error. Cannot instantiate configure handler");
|
"internal CTest error. Cannot instantiate configure handler");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int res = handler->ProcessHandler();
|
return handler;
|
||||||
if ( res_var )
|
|
||||||
{
|
|
||||||
cmOStringStream str;
|
|
||||||
str << res;
|
|
||||||
this->Makefile->AddDefinition(res_var, str.str().c_str());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
#ifndef cmCTestConfigureCommand_h
|
#ifndef cmCTestConfigureCommand_h
|
||||||
#define cmCTestConfigureCommand_h
|
#define cmCTestConfigureCommand_h
|
||||||
|
|
||||||
#include "cmCTestCommand.h"
|
#include "cmCTestHandlerCommand.h"
|
||||||
|
|
||||||
/** \class cmCTestConfigure
|
/** \class cmCTestConfigure
|
||||||
* \brief Run a ctest script
|
* \brief Run a ctest script
|
||||||
*
|
*
|
||||||
* cmCTestConfigureCommand defineds the command to configures the project.
|
* cmCTestConfigureCommand defineds the command to configures the project.
|
||||||
*/
|
*/
|
||||||
class cmCTestConfigureCommand : public cmCTestCommand
|
class cmCTestConfigureCommand : public cmCTestHandlerCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -41,12 +41,6 @@ public:
|
||||||
return ni;
|
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.
|
* The name of the command as specified in CMakeList.txt.
|
||||||
*/
|
*/
|
||||||
|
@ -72,7 +66,10 @@ public:
|
||||||
"return value.";
|
"return value.";
|
||||||
}
|
}
|
||||||
|
|
||||||
cmTypeMacro(cmCTestConfigureCommand, cmCTestCommand);
|
cmTypeMacro(cmCTestConfigureCommand, cmCTestHandlerCommand);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cmCTestGenericHandler* InitializeHandler();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,61 +19,8 @@
|
||||||
#include "cmCTest.h"
|
#include "cmCTest.h"
|
||||||
#include "cmCTestGenericHandler.h"
|
#include "cmCTestGenericHandler.h"
|
||||||
|
|
||||||
bool cmCTestCoverageCommand::InitialPass(
|
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
|
||||||
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 )
|
|
||||||
{
|
|
||||||
this->CTest->SetCTestConfiguration("BuildDirectory", build_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
|
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
|
||||||
"CoverageCommand", "CTEST_COVERAGE_COMMAND");
|
"CoverageCommand", "CTEST_COVERAGE_COMMAND");
|
||||||
|
|
||||||
|
@ -84,18 +31,7 @@ bool cmCTestCoverageCommand::InitialPass(
|
||||||
this->SetError("internal CTest error. Cannot instantiate test handler");
|
this->SetError("internal CTest error. Cannot instantiate test handler");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
|
return handler;
|
||||||
cmSystemTools::ChangeDirectory(
|
|
||||||
this->CTest->GetCTestConfiguration("BuildDirectory").c_str());
|
|
||||||
int res = handler->ProcessHandler();
|
|
||||||
if ( res_var )
|
|
||||||
{
|
|
||||||
cmOStringStream str;
|
|
||||||
str << res;
|
|
||||||
this->Makefile->AddDefinition(res_var, str.str().c_str());
|
|
||||||
}
|
|
||||||
cmSystemTools::ChangeDirectory(current_dir.c_str());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
#ifndef cmCTestCoverageCommand_h
|
#ifndef cmCTestCoverageCommand_h
|
||||||
#define cmCTestCoverageCommand_h
|
#define cmCTestCoverageCommand_h
|
||||||
|
|
||||||
#include "cmCTestCommand.h"
|
#include "cmCTestHandlerCommand.h"
|
||||||
|
|
||||||
/** \class cmCTestCoverage
|
/** \class cmCTestCoverage
|
||||||
* \brief Run a ctest script
|
* \brief Run a ctest script
|
||||||
*
|
*
|
||||||
* cmCTestCoverageCommand defineds the command to test the project.
|
* cmCTestCoverageCommand defineds the command to test the project.
|
||||||
*/
|
*/
|
||||||
class cmCTestCoverageCommand : public cmCTestCommand
|
class cmCTestCoverageCommand : public cmCTestHandlerCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -41,12 +41,6 @@ public:
|
||||||
return ni;
|
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.
|
* The name of the command as specified in CMakeList.txt.
|
||||||
*/
|
*/
|
||||||
|
@ -72,8 +66,10 @@ public:
|
||||||
"value.";
|
"value.";
|
||||||
}
|
}
|
||||||
|
|
||||||
cmTypeMacro(cmCTestCoverageCommand, cmCTestCommand);
|
cmTypeMacro(cmCTestCoverageCommand, cmCTestHandlerCommand);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cmCTestGenericHandler* InitializeHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -836,7 +836,7 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile *mf)
|
||||||
{
|
{
|
||||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||||
" Add coverage exclude regular expressions." << std::endl);
|
" Add coverage exclude regular expressions." << std::endl);
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_COVERAGE_EXCLUDE",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_COVERAGE_EXCLUDE",
|
||||||
this->CustomCoverageExclude);
|
this->CustomCoverageExclude);
|
||||||
std::vector<cmStdString>::iterator it;
|
std::vector<cmStdString>::iterator it;
|
||||||
for ( it = this->CustomCoverageExclude.begin();
|
for ( it = this->CustomCoverageExclude.begin();
|
||||||
|
|
|
@ -44,6 +44,7 @@ bool cmCTestHandlerCommand::InitialPass(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
|
||||||
cmCTestGenericHandler* handler = this->InitializeHandler();
|
cmCTestGenericHandler* handler = this->InitializeHandler();
|
||||||
if ( !handler )
|
if ( !handler )
|
||||||
{
|
{
|
||||||
|
@ -51,11 +52,31 @@ bool cmCTestHandlerCommand::InitialPass(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmCTestLog(this->CTest, DEBUG, "Populate Custom Vectors" << std::endl;);
|
||||||
|
handler->PopulateCustomVectors(this->Makefile);
|
||||||
|
|
||||||
if ( this->Values[ct_BUILD] )
|
if ( this->Values[ct_BUILD] )
|
||||||
{
|
{
|
||||||
this->CTest->SetCTestConfiguration("BuildDirectory",
|
this->CTest->SetCTestConfiguration("BuildDirectory",
|
||||||
this->Values[ct_BUILD]);
|
this->Values[ct_BUILD]);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->CTest->SetCTestConfiguration("BuildDirectory",
|
||||||
|
this->Makefile->GetDefinition("CTEST_BINARY_DIRECTORY"));
|
||||||
|
}
|
||||||
|
if ( this->Values[ct_SOURCE] )
|
||||||
|
{
|
||||||
|
cmCTestLog(this->CTest, DEBUG,
|
||||||
|
"Set source directory to: " << this->Values[ct_SOURCE] << std::endl);
|
||||||
|
this->CTest->SetCTestConfiguration("SourceDirectory",
|
||||||
|
this->Values[ct_SOURCE]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->CTest->SetCTestConfiguration("SourceDirectory",
|
||||||
|
this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"));
|
||||||
|
}
|
||||||
if ( this->Values[ct_SUBMIT_INDEX] )
|
if ( this->Values[ct_SUBMIT_INDEX] )
|
||||||
{
|
{
|
||||||
if ( this->CTest->GetDartVersion() <= 1 )
|
if ( this->CTest->GetDartVersion() <= 1 )
|
||||||
|
@ -72,7 +93,6 @@ bool cmCTestHandlerCommand::InitialPass(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
|
std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
|
||||||
cmSystemTools::ChangeDirectory(
|
cmSystemTools::ChangeDirectory(
|
||||||
this->CTest->GetCTestConfiguration("BuildDirectory").c_str());
|
this->CTest->GetCTestConfiguration("BuildDirectory").c_str());
|
||||||
|
|
|
@ -161,12 +161,12 @@ void cmCTestMemCheckHandler::GenerateTestCommand(
|
||||||
void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
|
void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
|
||||||
{
|
{
|
||||||
this->cmCTestTestHandler::PopulateCustomVectors(mf);
|
this->cmCTestTestHandler::PopulateCustomVectors(mf);
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK",
|
||||||
this->CustomPreMemCheck);
|
this->CustomPreMemCheck);
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK",
|
||||||
this->CustomPostMemCheck);
|
this->CustomPostMemCheck);
|
||||||
|
|
||||||
cmCTest::PopulateCustomVector(mf,
|
this->CTest->PopulateCustomVector(mf,
|
||||||
"CTEST_CUSTOM_MEMCHECK_IGNORE",
|
"CTEST_CUSTOM_MEMCHECK_IGNORE",
|
||||||
this->CustomTestsIgnore);
|
this->CustomTestsIgnore);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,39 +19,8 @@
|
||||||
#include "cmCTest.h"
|
#include "cmCTest.h"
|
||||||
#include "cmCTestGenericHandler.h"
|
#include "cmCTestGenericHandler.h"
|
||||||
|
|
||||||
bool cmCTestSubmitCommand::InitialPass(
|
cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
|
||||||
std::vector<std::string> const& args)
|
|
||||||
{
|
{
|
||||||
const char* res_var = 0;
|
|
||||||
|
|
||||||
bool havereturn_variable = false;
|
|
||||||
for(size_t i=0; i < args.size(); ++i)
|
|
||||||
{
|
|
||||||
if ( havereturn_variable )
|
|
||||||
{
|
|
||||||
res_var = args[i].c_str();
|
|
||||||
havereturn_variable = 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
|
|
||||||
{
|
|
||||||
cmOStringStream str;
|
|
||||||
str << "called with incorrect number of arguments. Extra argument is: "
|
|
||||||
<< args[i].c_str() << ".";
|
|
||||||
this->SetError(str.str().c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* ctestDropMethod
|
const char* ctestDropMethod
|
||||||
= this->Makefile->GetDefinition("CTEST_DROP_METHOD");
|
= this->Makefile->GetDefinition("CTEST_DROP_METHOD");
|
||||||
const char* ctestDropSite
|
const char* ctestDropSite
|
||||||
|
@ -137,14 +106,7 @@ bool cmCTestSubmitCommand::InitialPass(
|
||||||
this->SetError("internal CTest error. Cannot instantiate submit handler");
|
this->SetError("internal CTest error. Cannot instantiate submit handler");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int res = handler->ProcessHandler();
|
return handler;
|
||||||
if ( res_var )
|
|
||||||
{
|
|
||||||
cmOStringStream str;
|
|
||||||
str << res;
|
|
||||||
this->Makefile->AddDefinition(res_var, str.str().c_str());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#ifndef cmCTestSubmitCommand_h
|
#ifndef cmCTestSubmitCommand_h
|
||||||
#define cmCTestSubmitCommand_h
|
#define cmCTestSubmitCommand_h
|
||||||
|
|
||||||
#include "cmCTestCommand.h"
|
#include "cmCTestHandlerCommand.h"
|
||||||
|
|
||||||
/** \class cmCTestSubmit
|
/** \class cmCTestSubmit
|
||||||
* \brief Run a ctest script
|
* \brief Run a ctest script
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
* cmCTestSubmitCommand defineds the command to submit the test results for
|
* cmCTestSubmitCommand defineds the command to submit the test results for
|
||||||
* the project.
|
* the project.
|
||||||
*/
|
*/
|
||||||
class cmCTestSubmitCommand : public cmCTestCommand
|
class cmCTestSubmitCommand : public cmCTestHandlerCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -42,12 +42,6 @@ public:
|
||||||
return ni;
|
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.
|
* The name of the command as specified in CMakeList.txt.
|
||||||
*/
|
*/
|
||||||
|
@ -71,8 +65,10 @@ public:
|
||||||
"Submits the test results for the project.";
|
"Submits the test results for the project.";
|
||||||
}
|
}
|
||||||
|
|
||||||
cmTypeMacro(cmCTestSubmitCommand, cmCTestCommand);
|
cmTypeMacro(cmCTestSubmitCommand, cmCTestHandlerCommand);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cmCTestGenericHandler* InitializeHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
#include "cmCTestHandlerCommand.h"
|
#include "cmCTestHandlerCommand.h"
|
||||||
|
|
||||||
class cmCTestGenericHandler;
|
|
||||||
|
|
||||||
/** \class cmCTestTest
|
/** \class cmCTestTest
|
||||||
* \brief Run a ctest script
|
* \brief Run a ctest script
|
||||||
*
|
*
|
||||||
|
|
|
@ -385,17 +385,17 @@ void cmCTestTestHandler::Initialize()
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf)
|
void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf)
|
||||||
{
|
{
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_TEST",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_TEST",
|
||||||
this->CustomPreTest);
|
this->CustomPreTest);
|
||||||
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_TEST",
|
this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_TEST",
|
||||||
this->CustomPostTest);
|
this->CustomPostTest);
|
||||||
cmCTest::PopulateCustomVector(mf,
|
this->CTest->PopulateCustomVector(mf,
|
||||||
"CTEST_CUSTOM_TESTS_IGNORE",
|
"CTEST_CUSTOM_TESTS_IGNORE",
|
||||||
this->CustomTestsIgnore);
|
this->CustomTestsIgnore);
|
||||||
cmCTest::PopulateCustomInteger(mf,
|
this->CTest->PopulateCustomInteger(mf,
|
||||||
"CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
|
"CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
|
||||||
this->CustomMaximumPassedTestOutputSize);
|
this->CustomMaximumPassedTestOutputSize);
|
||||||
cmCTest::PopulateCustomInteger(mf,
|
this->CTest->PopulateCustomInteger(mf,
|
||||||
"CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",
|
"CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE",
|
||||||
this->CustomMaximumFailedTestOutputSize);
|
this->CustomMaximumFailedTestOutputSize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,55 +19,20 @@
|
||||||
#include "cmCTest.h"
|
#include "cmCTest.h"
|
||||||
#include "cmCTestGenericHandler.h"
|
#include "cmCTestGenericHandler.h"
|
||||||
|
|
||||||
bool cmCTestUpdateCommand::InitialPass(
|
cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
|
||||||
std::vector<std::string> const& args)
|
|
||||||
{
|
{
|
||||||
const char* source_dir = 0;
|
if ( this->Values[ct_SOURCE] )
|
||||||
const char* res_var = 0;
|
|
||||||
|
|
||||||
bool havereturn_variable = false;
|
|
||||||
bool havesource = false;
|
|
||||||
for(size_t i=0; i < args.size(); ++i)
|
|
||||||
{
|
{
|
||||||
if ( havereturn_variable )
|
this->CTest->SetCTestConfiguration("SourceDirectory",
|
||||||
{
|
this->Values[ct_SOURCE]);
|
||||||
res_var = args[i].c_str();
|
|
||||||
havereturn_variable = false;
|
|
||||||
}
|
|
||||||
else if ( havesource )
|
|
||||||
{
|
|
||||||
source_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] == "SOURCE")
|
|
||||||
{
|
|
||||||
if ( source_dir )
|
|
||||||
{
|
|
||||||
this->SetError("called with incorrect number of arguments. SOURCE "
|
|
||||||
"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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->CTest->SetCTestConfiguration("SourceDirectory",
|
||||||
|
this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"));
|
||||||
|
}
|
||||||
|
std::string source_dir
|
||||||
|
= this->CTest->GetCTestConfiguration("SourceDirectory");
|
||||||
|
|
||||||
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
|
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
|
||||||
"UpdateCommand", "CTEST_UPDATE_COMMAND");
|
"UpdateCommand", "CTEST_UPDATE_COMMAND");
|
||||||
|
@ -97,22 +62,23 @@ bool cmCTestUpdateCommand::InitialPass(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
handler->SetCommand(this);
|
handler->SetCommand(this);
|
||||||
if ( !source_dir )
|
if ( source_dir.empty() )
|
||||||
{
|
{
|
||||||
this->SetError("source directory not specified. Please use SOURCE tag");
|
this->SetError("source directory not specified. Please use SOURCE tag");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
handler->SetOption("SourceDirectory", source_dir.c_str());
|
||||||
if ( initialCheckoutCommand )
|
if ( initialCheckoutCommand )
|
||||||
{
|
{
|
||||||
handler->SetOption("InitialCheckout", initialCheckoutCommand);
|
handler->SetOption("InitialCheckout", initialCheckoutCommand);
|
||||||
}
|
}
|
||||||
if ( (!cmSystemTools::FileExists(source_dir) ||
|
if ( (!cmSystemTools::FileExists(source_dir.c_str()) ||
|
||||||
!cmSystemTools::FileIsDirectory(source_dir))
|
!cmSystemTools::FileIsDirectory(source_dir.c_str()))
|
||||||
&& !initialCheckoutCommand )
|
&& !initialCheckoutCommand )
|
||||||
{
|
{
|
||||||
cmOStringStream str;
|
cmOStringStream str;
|
||||||
str << "cannot find source directory: " << source_dir << ".";
|
str << "cannot find source directory: " << source_dir.c_str() << ".";
|
||||||
if ( !cmSystemTools::FileExists(source_dir) )
|
if ( !cmSystemTools::FileExists(source_dir.c_str()) )
|
||||||
{
|
{
|
||||||
str << " Looks like it is not checked out yet. Please specify "
|
str << " Looks like it is not checked out yet. Please specify "
|
||||||
"CTEST_CHECKOUT_COMMAND.";
|
"CTEST_CHECKOUT_COMMAND.";
|
||||||
|
@ -120,15 +86,7 @@ bool cmCTestUpdateCommand::InitialPass(
|
||||||
this->SetError(str.str().c_str());
|
this->SetError(str.str().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
handler->SetOption("SourceDirectory", source_dir);
|
return handler;
|
||||||
int res = handler->ProcessHandler();
|
|
||||||
if ( res_var )
|
|
||||||
{
|
|
||||||
cmOStringStream str;
|
|
||||||
str << res;
|
|
||||||
this->Makefile->AddDefinition(res_var, str.str().c_str());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
#ifndef cmCTestUpdateCommand_h
|
#ifndef cmCTestUpdateCommand_h
|
||||||
#define cmCTestUpdateCommand_h
|
#define cmCTestUpdateCommand_h
|
||||||
|
|
||||||
#include "cmCTestCommand.h"
|
#include "cmCTestHandlerCommand.h"
|
||||||
|
|
||||||
/** \class cmCTestUpdate
|
/** \class cmCTestUpdate
|
||||||
* \brief Run a ctest script
|
* \brief Run a ctest script
|
||||||
*
|
*
|
||||||
* cmCTestUpdateCommand defineds the command to updates the repository.
|
* cmCTestUpdateCommand defineds the command to updates the repository.
|
||||||
*/
|
*/
|
||||||
class cmCTestUpdateCommand : public cmCTestCommand
|
class cmCTestUpdateCommand : public cmCTestHandlerCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -41,12 +41,6 @@ public:
|
||||||
return ni;
|
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.
|
* The name of the command as specified in CMakeList.txt.
|
||||||
*/
|
*/
|
||||||
|
@ -72,8 +66,10 @@ public:
|
||||||
"modified. If there is a problem, the variable will be -1.";
|
"modified. If there is a problem, the variable will be -1.";
|
||||||
}
|
}
|
||||||
|
|
||||||
cmTypeMacro(cmCTestUpdateCommand, cmCTestCommand);
|
cmTypeMacro(cmCTestUpdateCommand, cmCTestHandlerCommand);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cmCTestGenericHandler* InitializeHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1322,6 +1322,7 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
|
||||||
if(this->CheckArgument(arg, "--debug"))
|
if(this->CheckArgument(arg, "--debug"))
|
||||||
{
|
{
|
||||||
this->Debug = true;
|
this->Debug = true;
|
||||||
|
this->ShowLineNumbers = true;
|
||||||
}
|
}
|
||||||
if(this->CheckArgument(arg, "--show-line-numbers"))
|
if(this->CheckArgument(arg, "--show-line-numbers"))
|
||||||
{
|
{
|
||||||
|
@ -1948,12 +1949,14 @@ void cmCTest::PopulateCustomVector(cmMakefile* mf, const char* def,
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
cmCTestLog(this, DEBUG, "PopulateCustomVector: " << def << std::endl);
|
||||||
std::vector<std::string> slist;
|
std::vector<std::string> slist;
|
||||||
cmSystemTools::ExpandListArgument(dval, slist);
|
cmSystemTools::ExpandListArgument(dval, slist);
|
||||||
std::vector<std::string>::iterator it;
|
std::vector<std::string>::iterator it;
|
||||||
|
|
||||||
for ( it = slist.begin(); it != slist.end(); ++it )
|
for ( it = slist.begin(); it != slist.end(); ++it )
|
||||||
{
|
{
|
||||||
|
cmCTestLog(this, DEBUG, " -- " << it->c_str() << std::endl);
|
||||||
vec.push_back(it->c_str());
|
vec.push_back(it->c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,9 +129,9 @@ public:
|
||||||
//! Set the notes files to be created.
|
//! Set the notes files to be created.
|
||||||
void SetNotesFiles(const char* notes);
|
void SetNotesFiles(const char* notes);
|
||||||
|
|
||||||
static void PopulateCustomVector(cmMakefile* mf, const char* definition,
|
void PopulateCustomVector(cmMakefile* mf, const char* definition,
|
||||||
VectorOfStrings& vec);
|
VectorOfStrings& vec);
|
||||||
static void PopulateCustomInteger(cmMakefile* mf, const char* def,
|
void PopulateCustomInteger(cmMakefile* mf, const char* def,
|
||||||
int& val);
|
int& val);
|
||||||
|
|
||||||
///! Get the current time as string
|
///! Get the current time as string
|
||||||
|
|
|
@ -43,6 +43,8 @@ CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@
|
||||||
CTEST_TEST_KWSYS:BOOL=ON
|
CTEST_TEST_KWSYS:BOOL=ON
|
||||||
")
|
")
|
||||||
|
|
||||||
|
SET(CTEST_CUSTOM_WARNING_MATCH CommandLineArguments)
|
||||||
|
|
||||||
CTEST_START(Nightly)
|
CTEST_START(Nightly)
|
||||||
CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}" RETURN_VALUE res)
|
CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}" RETURN_VALUE res)
|
||||||
CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
|
CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
|
||||||
|
|
Loading…
Reference in New Issue