summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Hoffman <bill.hoffman@kitware.com>2008-02-06 14:35:02 (GMT)
committerBill Hoffman <bill.hoffman@kitware.com>2008-02-06 14:35:02 (GMT)
commit7dfcc3fc12435d372e7142898c633504de064579 (patch)
treec6000ef79fdae70770d6165f0fdf5b9fdbb686f6
parent0c3607eafccfa2b040774c7572508df507e8c10a (diff)
downloadCMake-7dfcc3fc12435d372e7142898c633504de064579.zip
CMake-7dfcc3fc12435d372e7142898c633504de064579.tar.gz
CMake-7dfcc3fc12435d372e7142898c633504de064579.tar.bz2
ENH: add DOWNLOAD option to FILE command
-rw-r--r--Source/CMakeLists.txt3
-rw-r--r--Source/cmFileCommand.cxx172
-rw-r--r--Source/cmFileCommand.h9
3 files changed, 182 insertions, 2 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index dc83ca3..55dc3a1 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -267,7 +267,8 @@ ENDIF (WIN32)
ADD_LIBRARY(CMakeLib ${SRCS})
TARGET_LINK_LIBRARIES(CMakeLib cmsys
${CMAKE_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES}
- ${CMAKE_TAR_LIBRARIES} ${CMAKE_COMPRESS_LIBRARIES})
+ ${CMAKE_TAR_LIBRARIES} ${CMAKE_COMPRESS_LIBRARIES}
+ ${CMAKE_CURL_LIBRARIES})
# On Apple we need Carbon
IF(APPLE)
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 4ab73db..d1c5117 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -19,6 +19,11 @@
#include "cmHexFileConverter.h"
#include "cmFileTimeComparison.h"
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cm_curl.h"
+#endif
+
+#undef GetCurrentDirectory
#include <sys/types.h>
#include <sys/stat.h>
@@ -71,6 +76,10 @@ bool cmFileCommand
{
return this->HandleWriteCommand(args, true);
}
+ else if ( subCommand == "DOWNLOAD" )
+ {
+ return this->HandleDownloadCommand(args);
+ }
else if ( subCommand == "READ" )
{
return this->HandleReadCommand(args);
@@ -1869,5 +1878,168 @@ bool cmFileCommand::HandleCMakePathCommand(std::vector<std::string>
this->Makefile->AddDefinition(var, value.c_str());
return true;
}
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+
+// Stuff for curl download
+typedef std::vector<char> cmFileCommandVectorOfChar;
+namespace{
+ size_t
+ cmFileCommandWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
+ void *data)
+ {
+ register int realsize = (int)(size * nmemb);
+ std::ofstream* fout = static_cast<std::ofstream*>(data);
+ const char* chPtr = static_cast<char*>(ptr);
+ fout->write(chPtr, realsize);
+ return realsize;
+ }
+
+ static size_t
+ cmFileCommandCurlDebugCallback(CURL *, curl_infotype, char *chPtr,
+ size_t size, void *data)
+ {
+ cmFileCommandVectorOfChar *vec
+ = static_cast<cmFileCommandVectorOfChar*>(data);
+ vec->insert(vec->end(), chPtr, chPtr + size);
+
+ return size;
+ }
+
+
+}
+
+#endif
+
+bool
+cmFileCommand::HandleDownloadCommand(std::vector<std::string>
+ const& args)
+{
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ std::vector<std::string>::const_iterator i = args.begin();
+ if(args.size() < 3)
+ {
+ std::cout << args.size() << "\n";
+ this->SetError("FILE(DOWNLOAD url file) must be called with "
+ "at least three arguments.");
+ return false;
+ }
+ i++; // Get rid of subcommand
+ std::string url = *i;
+ i++;
+ std::string file = *i;
+ i++;
+ double timeout = 0;
+ std::string verboseLog;
+ std::string statusVar;
+ while(i != args.end())
+ {
+ if(*i == "TIMEOUT")
+ {
+ i++;
+ if(i != args.end())
+ {
+ timeout = atof(i->c_str());
+ }
+ else
+ {
+ this->SetError("FILE(DOWNLOAD url file TIMEOUT time) missing "
+ "time for TIMEOUT.");
+ return false;
+ }
+ }
+ else if(*i == "LOG")
+ {
+ i++;
+ if( i == args.end())
+ {
+ this->SetError("FILE(DOWNLOAD url file LOG VAR) missing "
+ "VAR for LOG.");
+ return false;
+ }
+ verboseLog = *i;
+ }
+ else if(*i == "STATUS")
+ {
+ i++;
+ if( i == args.end())
+ {
+ this->SetError("FILE(DOWNLOAD url file STATUS VAR) missing "
+ "VAR for STATUS.");
+ return false;
+ }
+ statusVar = *i;
+ }
+ i++;
+ }
+ std::cout << "log var: [" << verboseLog << "]\n";
+ std::cout << "Url: [" << url << "]\n";
+ std::cout << "file: [" << file << "]\n";
+ std::cout << "timeout: [" << timeout << "]\n";
+ std::ofstream fout(file.c_str());
+ if(!fout)
+ {
+ this->SetError("FILE(DOWNLOAD url file TIMEOUT time) can not open "
+ "file for write.");
+ return false;
+ }
+ CURL *curl;
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ curl = curl_easy_init();
+ if(!curl)
+ {
+ this->SetError("FILE(DOWNLOAD ) error "
+ "initializing curl.");
+ return false;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+ cmFileCommandWriteMemoryCallback);
+ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
+ cmFileCommandCurlDebugCallback);
+ cmFileCommandVectorOfChar chunkDebug;
+ ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&fout);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
+ if(verboseLog.size())
+ {
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+ }
+ if(timeout > 0)
+ {
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout );
+ }
+ CURLcode res = curl_easy_perform(curl);
+ std::cout << "res = " << res << "\n";
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ if(statusVar.size())
+ {
+ this->Makefile->AddDefinition(statusVar.c_str(),
+ curl_easy_strerror(res));
+ }
+ curl_global_cleanup();
+ if(chunkDebug.size())
+ {
+ chunkDebug.push_back(0);
+ if(CURLE_OPERATION_TIMEOUTED == res)
+ {
+ std::string output = &*chunkDebug.begin();
+
+ if(verboseLog.size())
+ {
+ this->Makefile->AddDefinition(verboseLog.c_str(),
+ &*chunkDebug.begin());
+ }
+ }
+ this->Makefile->AddDefinition(verboseLog.c_str(),
+ &*chunkDebug.begin());
+ }
+ return true;
+#else
+ this->SetError("FILE(DOWNLOAD ) "
+ "not supported in bootstrap cmake ");
+ return false;
+#endif
+}
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index a69844a..2631021 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -84,6 +84,7 @@ public:
" file(RELATIVE_PATH variable directory file)\n"
" file(TO_CMAKE_PATH path result)\n"
" file(TO_NATIVE_PATH path result)\n"
+ " file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log])\n"
"WRITE will write a message into a file called 'filename'. It "
"overwrites the file if it already exists, and creates the file "
"if it does not exist.\n"
@@ -145,7 +146,12 @@ public:
" one argument.\n"
"TO_NATIVE_PATH works just like TO_CMAKE_PATH, but will convert from "
" a cmake style path into the native path style \\ for windows and / "
- "for UNIX.";
+ "for UNIX.\n"
+ "DOWNLOAD will download the givin URL to the given file. "
+ "If LOG var is specified a log of the download will be put in var. "
+ "If STATUS var is specified the status of the operation will"
+ " be put in var. If TIMEOUT time is specified, the operation will "
+ "timeout after time seconds, time can be specified as a float.\n";
}
cmTypeMacro(cmFileCommand, cmCommand);
@@ -180,6 +186,7 @@ protected:
const std::vector<std::string>& files,
const bool optional
);
+ bool HandleDownloadCommand(std::vector<std::string> const& args);
void GetTargetTypeFromString(const std::string& stype, int& itype) const;
bool HandleInstallDestination(cmFileInstaller& installer,
std::string& destination);