summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-01-22 16:16:45 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2015-01-22 16:16:45 (GMT)
commitc0298947ff664d200b7b2a86ac6e84c1c76e2fb1 (patch)
treed9135d12346455924110e834f63a34c27aee40c3 /Source
parent57f4c8346206d129d2ec6576b3fb0b7862566311 (diff)
parentf3e0b6f1eb8deba06e6072156bd9b247a559c9be (diff)
downloadCMake-c0298947ff664d200b7b2a86ac6e84c1c76e2fb1.zip
CMake-c0298947ff664d200b7b2a86ac6e84c1c76e2fb1.tar.gz
CMake-c0298947ff664d200b7b2a86ac6e84c1c76e2fb1.tar.bz2
Merge topic 'cdash_upload_file_mode'
f3e0b6f1 CTestCoverageCollectGCOV: Add module to run gcov 6dd980e0 ctest_submit: Make CDASH_UPLOAD mode arguments more strict 5dc33f89 ctest_submit: Add CDASH_UPLOAD mode to upload files to CDash
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/CTest/cmCTestCurl.cxx271
-rw-r--r--Source/CTest/cmCTestCurl.h52
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx100
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h9
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx167
-rw-r--r--Source/CTest/cmCTestSubmitHandler.h5
7 files changed, 577 insertions, 28 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index af4c7cf..c04cf9a 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -537,6 +537,7 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestConfigureHandler.cxx
CTest/cmCTestCoverageCommand.cxx
CTest/cmCTestCoverageHandler.cxx
+ CTest/cmCTestCurl.cxx
CTest/cmParseMumpsCoverage.cxx
CTest/cmParseCacheCoverage.cxx
CTest/cmParseGTMCoverage.cxx
diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
new file mode 100644
index 0000000..b0d26cc
--- /dev/null
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -0,0 +1,271 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2015 Kitware, Inc.
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmCTestCurl.h"
+
+#include "cmSystemTools.h"
+#include "cmCTest.h"
+
+cmCTestCurl::cmCTestCurl(cmCTest* ctest)
+{
+ this->CTest = ctest;
+ this->SetProxyType();
+ this->UseHttp10 = false;
+ // In windows, this will init the winsock stuff
+ ::curl_global_init(CURL_GLOBAL_ALL);
+ // default is to verify https
+ this->VerifyPeerOff = false;
+ this->VerifyHostOff = false;
+ this->TimeOutSeconds = 0;
+}
+
+namespace
+{
+static size_t
+curlWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
+ void *data)
+{
+ int realsize = (int)(size * nmemb);
+
+ std::vector<char> *vec
+ = static_cast<std::vector<char>* >(data);
+ const char* chPtr = static_cast<char*>(ptr);
+ vec->insert(vec->end(), chPtr, chPtr + realsize);
+ return realsize;
+}
+
+static size_t
+curlDebugCallback(CURL *, curl_infotype, char *chPtr,
+ size_t size, void *data)
+{
+ std::vector<char> *vec
+ = static_cast<std::vector<char>* >(data);
+ vec->insert(vec->end(), chPtr, chPtr + size);
+
+ return size;
+}
+
+}
+
+void cmCTestCurl::SetCurlOptions(std::vector<std::string> const& args)
+{
+ for( std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i)
+ {
+ if(*i == "CURLOPT_SSL_VERIFYPEER_OFF")
+ {
+ this->VerifyPeerOff = true;
+ }
+ if(*i == "CURLOPT_SSL_VERIFYHOST_OFF")
+ {
+ this->VerifyHostOff = true;
+ }
+ }
+}
+
+bool cmCTestCurl::InitCurl()
+{
+ this->Curl = curl_easy_init();
+ if(!this->Curl)
+ {
+ return false;
+ }
+ if(this->VerifyPeerOff)
+ {
+ curl_easy_setopt(this->Curl, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+ if(this->VerifyHostOff)
+ {
+ curl_easy_setopt(this->Curl, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+ if(this->HTTPProxy.size())
+ {
+ curl_easy_setopt(this->Curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
+ curl_easy_setopt(this->Curl, CURLOPT_PROXYTYPE, this->HTTPProxyType);
+ if (this->HTTPProxyAuth.size() > 0)
+ {
+ curl_easy_setopt(this->Curl, CURLOPT_PROXYUSERPWD,
+ this->HTTPProxyAuth.c_str());
+ }
+ }
+ if(this->UseHttp10)
+ {
+ curl_easy_setopt(this->Curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ }
+ // enable HTTP ERROR parsing
+ curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1);
+ return true;
+}
+
+
+bool cmCTestCurl::UploadFile(std::string const& local_file,
+ std::string const& url,
+ std::string const& fields,
+ std::string& response)
+{
+ response = "";
+ if(!this->InitCurl())
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Initialization of curl failed");
+ return false;
+ }
+ /* enable uploading */
+ curl_easy_setopt(this->Curl, CURLOPT_UPLOAD, 1);
+ // if there is little to no activity for too long stop submitting
+ if(this->TimeOutSeconds)
+ {
+ ::curl_easy_setopt(this->Curl, CURLOPT_LOW_SPEED_LIMIT, 1);
+ ::curl_easy_setopt(this->Curl, CURLOPT_LOW_SPEED_TIME,
+ this->TimeOutSeconds);
+ }
+ /* HTTP PUT please */
+ ::curl_easy_setopt(this->Curl, CURLOPT_PUT, 1);
+ ::curl_easy_setopt(this->Curl, CURLOPT_VERBOSE, 1);
+
+ FILE* ftpfile = cmsys::SystemTools::Fopen(local_file, "rb");
+ if(!ftpfile)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Could not open file for upload: " << local_file << "\n");
+ return false;
+ }
+ // set the url
+ std::string upload_url = url;
+ upload_url += "?";
+ upload_url += fields;
+ ::curl_easy_setopt(this->Curl, CURLOPT_URL, upload_url.c_str());
+ // now specify which file to upload
+ ::curl_easy_setopt(this->Curl, CURLOPT_INFILE, ftpfile);
+ unsigned long filelen = cmSystemTools::FileLength(local_file);
+ // and give the size of the upload (optional)
+ ::curl_easy_setopt(this->Curl, CURLOPT_INFILESIZE,
+ static_cast<long>(filelen));
+ ::curl_easy_setopt(this->Curl, CURLOPT_WRITEFUNCTION,
+ curlWriteMemoryCallback);
+ ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGFUNCTION,
+ curlDebugCallback);
+ std::vector<char> responseData;
+ std::vector<char> debugData;
+ ::curl_easy_setopt(this->Curl, CURLOPT_FILE, (void *)&responseData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, (void *)&debugData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1);
+ // Now run off and do what you've been told!
+ ::curl_easy_perform(this->Curl);
+ ::fclose(ftpfile);
+ ::curl_global_cleanup();
+
+ if ( responseData.size() > 0 )
+ {
+ response = std::string(responseData.begin(), responseData.end());
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Curl response: [" << response << "]\n");
+ }
+ std::string curlDebug;
+ if ( debugData.size() > 0 )
+ {
+ curlDebug = std::string(debugData.begin(), debugData.end());
+ cmCTestLog(this->CTest, DEBUG, "Curl debug: [" << curlDebug << "]\n");
+ }
+ if(response.size() == 0)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "No response from server.\n" <<
+ curlDebug);
+ return false;
+ }
+ return true;
+}
+
+bool cmCTestCurl::HttpRequest(std::string const& url,
+ std::string const& fields,
+ std::string& response)
+{
+ response = "";
+ cmCTestLog(this->CTest, DEBUG, "HttpRequest\n"
+ << "url: " << url << "\n"
+ << "fields " << fields << "\n");
+ if(!this->InitCurl())
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Initialization of curl failed");
+ return false;
+ }
+ curl_easy_setopt(this->Curl, CURLOPT_POST, 1);
+ curl_easy_setopt(this->Curl, CURLOPT_POSTFIELDS, fields.c_str());
+ ::curl_easy_setopt(this->Curl, CURLOPT_URL, url.c_str());
+ ::curl_easy_setopt(this->Curl, CURLOPT_FOLLOWLOCATION, 1);
+ //set response options
+ ::curl_easy_setopt(this->Curl, CURLOPT_WRITEFUNCTION,
+ curlWriteMemoryCallback);
+ ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGFUNCTION,
+ curlDebugCallback);
+ std::vector<char> responseData;
+ std::vector<char> debugData;
+ ::curl_easy_setopt(this->Curl, CURLOPT_FILE, (void *)&responseData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, (void *)&debugData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1);
+
+ CURLcode res = ::curl_easy_perform(this->Curl);
+
+ ::curl_easy_cleanup(this->Curl);
+ ::curl_global_cleanup();
+ if ( responseData.size() > 0 )
+ {
+ response = std::string(responseData.begin(), responseData.end());
+ cmCTestLog(this->CTest, DEBUG, "Curl response: [" << response << "]\n");
+ }
+ if ( debugData.size() > 0 )
+ {
+ std::string curlDebug = std::string(debugData.begin(), debugData.end());
+ cmCTestLog(this->CTest, DEBUG, "Curl debug: [" << curlDebug << "]\n");
+ }
+ cmCTestLog(this->CTest, DEBUG, "Curl res: " << res << "\n");
+ return (res == 0);
+}
+
+void cmCTestCurl::SetProxyType()
+{
+ if ( cmSystemTools::GetEnv("HTTP_PROXY") )
+ {
+ this->HTTPProxy = cmSystemTools::GetEnv("HTTP_PROXY");
+ if ( cmSystemTools::GetEnv("HTTP_PROXY_PORT") )
+ {
+ this->HTTPProxy += ":";
+ this->HTTPProxy += cmSystemTools::GetEnv("HTTP_PROXY_PORT");
+ }
+ if ( cmSystemTools::GetEnv("HTTP_PROXY_TYPE") )
+ {
+ // this is the default
+ this->HTTPProxyType = CURLPROXY_HTTP;
+ std::string type = cmSystemTools::GetEnv("HTTP_PROXY_TYPE");
+ // HTTP/SOCKS4/SOCKS5
+ if ( type == "HTTP" )
+ {
+ this->HTTPProxyType = CURLPROXY_HTTP;
+ }
+ else if ( type == "SOCKS4" )
+ {
+ this->HTTPProxyType = CURLPROXY_SOCKS4;
+ }
+ else if ( type == "SOCKS5" )
+ {
+ this->HTTPProxyType = CURLPROXY_SOCKS5;
+ }
+ }
+ if ( cmSystemTools::GetEnv("HTTP_PROXY_USER") )
+ {
+ this->HTTPProxyAuth = cmSystemTools::GetEnv("HTTP_PROXY_USER");
+ }
+ if ( cmSystemTools::GetEnv("HTTP_PROXY_PASSWD") )
+ {
+ this->HTTPProxyAuth += ":";
+ this->HTTPProxyAuth += cmSystemTools::GetEnv("HTTP_PROXY_PASSWD");
+ }
+ }
+}
diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h
new file mode 100644
index 0000000..5bb8b41
--- /dev/null
+++ b/Source/CTest/cmCTestCurl.h
@@ -0,0 +1,52 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2015 Kitware, Inc.
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmCTestCurl_h
+#define cmCTestCurl_h
+
+#include "cmStandardIncludes.h"
+
+#include "cm_curl.h"
+
+class cmCTest;
+
+class cmCTestCurl
+{
+public:
+ cmCTestCurl(cmCTest*);
+ bool UploadFile(std::string const& url,
+ std::string const& file,
+ std::string const& fields,
+ std::string& response);
+ bool HttpRequest(std::string const& url,
+ std::string const& fields,
+ std::string& response);
+ // currently only supports CURLOPT_SSL_VERIFYPEER_OFF
+ // and CURLOPT_SSL_VERIFYHOST_OFF
+ void SetCurlOptions(std::vector<std::string> const& args);
+ void SetUseHttp10On() { this->UseHttp10 = true;}
+ void SetTimeOutSeconds(int s) { this->TimeOutSeconds = s;}
+protected:
+ void SetProxyType();
+ bool InitCurl();
+private:
+ cmCTest* CTest;
+ CURL* Curl;
+ std::string HTTPProxyAuth;
+ std::string HTTPProxy;
+ curl_proxytype HTTPProxyType;
+ bool VerifyHostOff;
+ bool VerifyPeerOff;
+ bool UseHttp10;
+ int TimeOutSeconds;
+};
+
+#endif
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index 4005a63..cc3514f 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -27,7 +27,8 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
= this->Makefile->GetDefinition("CTEST_TRIGGER_SITE");
bool ctestDropSiteCDash
= this->Makefile->IsOn("CTEST_DROP_SITE_CDASH");
-
+ const char* ctestProjectName
+ = this->Makefile->GetDefinition("CTEST_PROJECT_NAME");
if ( !ctestDropMethod )
{
ctestDropMethod = "http";
@@ -43,7 +44,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// error: CDash requires CTEST_DROP_LOCATION definition
// in CTestConfig.cmake
}
-
+ this->CTest->SetCTestConfiguration("ProjectName", ctestProjectName);
this->CTest->SetCTestConfiguration("DropMethod", ctestDropMethod);
this->CTest->SetCTestConfiguration("DropSite", ctestDropSite);
this->CTest->SetCTestConfiguration("DropLocation", ctestDropLocation);
@@ -144,44 +145,75 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
static_cast<cmCTestSubmitHandler*>(handler)->SetOption("InternalTest",
this->InternalTest ? "ON" : "OFF");
+ if (this->CDashUpload)
+ {
+ static_cast<cmCTestSubmitHandler*>(handler)->
+ SetOption("CDashUploadFile", this->CDashUploadFile.c_str());
+ static_cast<cmCTestSubmitHandler*>(handler)->
+ SetOption("CDashUploadType", this->CDashUploadType.c_str());
+ }
return handler;
}
+//----------------------------------------------------------------------------
+bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ this->CDashUpload = !args.empty() && args[0] == "CDASH_UPLOAD";
+ return this->cmCTestHandlerCommand::InitialPass(args, status);
+}
//----------------------------------------------------------------------------
bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
{
- // Look for arguments specific to this command.
- if(arg == "PARTS")
+ if (this->CDashUpload)
{
- this->ArgumentDoing = ArgumentDoingParts;
- this->PartsMentioned = true;
- return true;
- }
+ if(arg == "CDASH_UPLOAD")
+ {
+ this->ArgumentDoing = ArgumentDoingCDashUpload;
+ return true;
+ }
- if(arg == "FILES")
- {
- this->ArgumentDoing = ArgumentDoingFiles;
- this->FilesMentioned = true;
- return true;
+ if(arg == "CDASH_UPLOAD_TYPE")
+ {
+ this->ArgumentDoing = ArgumentDoingCDashUploadType;
+ return true;
+ }
}
-
- if(arg == "RETRY_COUNT")
+ else
{
- this->ArgumentDoing = ArgumentDoingRetryCount;
- return true;
- }
+ // Look for arguments specific to this command.
+ if(arg == "PARTS")
+ {
+ this->ArgumentDoing = ArgumentDoingParts;
+ this->PartsMentioned = true;
+ return true;
+ }
- if(arg == "RETRY_DELAY")
- {
- this->ArgumentDoing = ArgumentDoingRetryDelay;
- return true;
- }
+ if(arg == "FILES")
+ {
+ this->ArgumentDoing = ArgumentDoingFiles;
+ this->FilesMentioned = true;
+ return true;
+ }
- if(arg == "INTERNAL_TEST_CHECKSUM")
- {
- this->InternalTest = true;
- return true;
+ if(arg == "RETRY_COUNT")
+ {
+ this->ArgumentDoing = ArgumentDoingRetryCount;
+ return true;
+ }
+
+ if(arg == "RETRY_DELAY")
+ {
+ this->ArgumentDoing = ArgumentDoingRetryDelay;
+ return true;
+ }
+
+ if(arg == "INTERNAL_TEST_CHECKSUM")
+ {
+ this->InternalTest = true;
+ return true;
+ }
}
// Look for other arguments.
@@ -240,6 +272,20 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
return true;
}
+ if(this->ArgumentDoing == ArgumentDoingCDashUpload)
+ {
+ this->ArgumentDoing = ArgumentDoingNone;
+ this->CDashUploadFile = arg;
+ return true;
+ }
+
+ if(this->ArgumentDoing == ArgumentDoingCDashUploadType)
+ {
+ this->ArgumentDoing = ArgumentDoingNone;
+ this->CDashUploadType = arg;
+ return true;
+ }
+
// Look for other arguments.
return this->Superclass::CheckArgumentValue(arg);
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index 3673fbd..19e8eaf 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -32,6 +32,7 @@ public:
this->InternalTest = false;
this->RetryCount = "";
this->RetryDelay = "";
+ this->CDashUpload = false;
}
/**
@@ -45,6 +46,9 @@ public:
return ni;
}
+ virtual bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus &status);
+
/**
* The name of the command as specified in CMakeList.txt.
*/
@@ -64,6 +68,8 @@ protected:
ArgumentDoingFiles,
ArgumentDoingRetryDelay,
ArgumentDoingRetryCount,
+ ArgumentDoingCDashUpload,
+ ArgumentDoingCDashUploadType,
ArgumentDoingLast2
};
@@ -74,6 +80,9 @@ protected:
cmCTest::SetOfStrings Files;
std::string RetryCount;
std::string RetryDelay;
+ bool CDashUpload;
+ std::string CDashUploadFile;
+ std::string CDashUploadType;
};
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index bc6fb31..11e3343 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -10,7 +10,8 @@
See the License for more information.
============================================================================*/
#include "cmCTestSubmitHandler.h"
-
+#include "cmCTestScriptHandler.h"
+#include "cmake.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmGeneratedFileStream.h"
@@ -23,8 +24,10 @@
// For XML-RPC submission
#include "cm_xmlrpc.h"
+#include <cm_jsoncpp_reader.h>
// For curl submission
#include "cm_curl.h"
+#include "cmCTestCurl.h"
#include <sys/stat.h>
@@ -1055,9 +1058,171 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC(std::string const&,
}
#endif
+void cmCTestSubmitHandler::ConstructCDashURL(std::string& dropMethod,
+ std::string& url)
+{
+ dropMethod = this->CTest->GetCTestConfiguration("DropMethod");
+ url = dropMethod;
+ url += "://";
+ if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
+ {
+ url += this->CTest->GetCTestConfiguration("DropSiteUser");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetCTestConfiguration("DropSiteUser").c_str());
+ if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
+ {
+ url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
+ }
+ url += "@";
+ }
+ url += this->CTest->GetCTestConfiguration("DropSite") +
+ this->CTest->GetCTestConfiguration("DropLocation");
+}
+
+
+int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
+ std::string const& typeString)
+{
+ if (file.empty())
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Upload file not specified\n");
+ return -1;
+ }
+ if (!cmSystemTools::FileExists(file))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Upload file not found: '" << file << "'\n");
+ return -1;
+ }
+ cmCTestCurl curl(this->CTest);
+ std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(curlopt, args);
+ curl.SetCurlOptions(args);
+ curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
+ std::string dropMethod;
+ std::string url;
+ this->ConstructCDashURL(dropMethod, url);
+ std::string::size_type pos = url.find("submit.php?");
+ url = url.substr(0, pos+10);
+ if ( ! (dropMethod == "http" || dropMethod == "https" ) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Only http and https are supported for CDASH_UPLOAD\n");
+ return -1;
+ }
+ char md5sum[33];
+ md5sum[32] = 0;
+ cmSystemTools::ComputeFileMD5(file, md5sum);
+ // 1. request the buildid and check to see if the file
+ // has already been uploaded
+ // TODO I added support for subproject. You would need to add
+ // a "&subproject=subprojectname" to the first POST.
+ cmCTestScriptHandler* ch =
+ static_cast<cmCTestScriptHandler*>(this->CTest->GetHandler("script"));
+ cmake* cm = ch->GetCMake();
+ const char* subproject = cm->GetProperty("SubProject", cmProperty::GLOBAL);
+ // TODO: Encode values for a URL instead of trusting caller.
+ std::ostringstream str;
+ str << "project="
+ << this->CTest->GetCTestConfiguration("ProjectName") << "&";
+ if(subproject)
+ {
+ str << "subproject=" << subproject << "&";
+ }
+ str << "stamp=" << this->CTest->GetCurrentTag() << "-"
+ << this->CTest->GetTestModelString() << "&"
+ << "model=" << this->CTest->GetTestModelString() << "&"
+ << "build=" << this->CTest->GetCTestConfiguration("BuildName") << "&"
+ << "site=" << this->CTest->GetCTestConfiguration("Site") << "&"
+ << "track=" << this->CTest->GetTestModelString() << "&"
+ << "starttime=" << (int)cmSystemTools::GetTime() << "&"
+ << "endtime=" << (int)cmSystemTools::GetTime() << "&"
+ << "datafilesmd5[0]=" << md5sum << "&"
+ << "type=" << typeString;
+ std::string fields = str.str();
+ cmCTestLog(this->CTest, DEBUG, "fields: " << fields << "\nurl:"
+ << url << "\nfile: " << file << "\n");
+ std::string response;
+ if(!curl.HttpRequest(url, fields, response))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error in HttpRequest\n" << response);
+ return -1;
+ }
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Request upload response: [" << response << "]\n");
+ Json::Value json;
+ Json::Reader reader;
+ if(!reader.parse(response, json))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error parsing json string [" << response << "]\n"
+ << reader.getFormattedErrorMessages() << "\n");
+ return -1;
+ }
+ if(json["status"].asInt() != 0)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Bad status returned from CDash: "
+ << json["status"].asInt());
+ return -1;
+ }
+ if(json["datafilesmd5"].isArray())
+ {
+ int datares = json["datafilesmd5"][0].asInt();
+ if(datares == 1)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "File already exists on CDash, skip upload "
+ << file << "\n");
+ return 0;
+ }
+ }
+ else
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "bad datafilesmd5 value in response "
+ << response << "\n");
+ return -1;
+ }
+
+ std::string upload_as = cmSystemTools::GetFilenameName(file);
+ std::ostringstream fstr;
+ fstr << "type=" << typeString << "&"
+ << "md5=" << md5sum << "&"
+ << "filename=" << upload_as << "&"
+ << "buildid=" << json["buildid"].asString();
+ if(!curl.UploadFile(file, url, fstr.str(), response))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error uploading to CDash. "
+ << file << " " << url << " " << fstr.str());
+ return -1;
+ }
+ if(!reader.parse(response, json))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error parsing json string [" << response << "]\n"
+ << reader.getFormattedErrorMessages() << "\n");
+ return -1;
+ }
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Upload file response: [" << response << "]\n");
+ return 0;
+}
+
//----------------------------------------------------------------------------
int cmCTestSubmitHandler::ProcessHandler()
{
+ const char* cdashUploadFile = this->GetOption("CDashUploadFile");
+ const char* cdashUploadType = this->GetOption("CDashUploadType");
+ if(cdashUploadFile && cdashUploadType)
+ {
+ return this->HandleCDashUploadFile(cdashUploadFile, cdashUploadType);
+ }
std::string iscdash = this->CTest->GetCTestConfiguration("IsCDash");
// cdash does not need to trigger so just return true
if(!iscdash.empty())
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index accabd1..f9cd894 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -41,6 +41,11 @@ public:
/** Specify a set of files to submit. */
void SelectFiles(cmCTest::SetOfStrings const& files);
+ // handle the cdash file upload protocol
+ int HandleCDashUploadFile(std::string const& file, std::string const& type);
+
+ void ConstructCDashURL(std::string& dropMethod, std::string& url);
+
private:
void SetLogFile(std::ostream* ost) { this->LogFile = ost; }