ENH: add DOWNLOAD option to FILE command
This commit is contained in:
parent
0c3607eafc
commit
7dfcc3fc12
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue