managed to download a tarball
This commit is contained in:
parent
7ac697f111
commit
76bd9a0497
@ -4,7 +4,9 @@
|
||||
|
||||
#include "project.h"
|
||||
|
||||
const std::regex http("^https?://");
|
||||
constexpr std::string_view acceptJson("accept: application/json");
|
||||
const std::regex http("^https?:\\/\\/");
|
||||
const std::regex repo("(^https?):\\/\\/([\\w\\d\\.\\-\\_]+)\\/([\\w\\d\\-\\_]+)\\/([\\w\\d\\-\\_]+)");
|
||||
|
||||
Dependency::Dependency(
|
||||
const std::string& path,
|
||||
@ -31,11 +33,15 @@ std::optional<std::string> Dependency::getVersion() const {
|
||||
}
|
||||
|
||||
bool Dependency::prepare(const std::filesystem::path& source, const std::filesystem::path& destination) {
|
||||
if (std::regex_search(path, http)) {
|
||||
Project::info("downloading project from " + path);
|
||||
std::filesystem::create_directories(destination / "downloads");
|
||||
std::smatch results;
|
||||
if (std::regex_search(path, results, repo)) {
|
||||
Project::info(path + " appears to be a git repository");
|
||||
const std::string& protocol = results[1];
|
||||
const std::string& host = results[2];
|
||||
const std::string& owner = results[3];
|
||||
const std::string& repo = results[4];
|
||||
|
||||
return download(destination);
|
||||
return downloadRepo(destination, protocol, host, owner, repo);
|
||||
} else {
|
||||
Project::info("checking project at path " + path);
|
||||
std::filesystem::directory_entry srcDir(source / path);
|
||||
@ -48,50 +54,160 @@ bool Dependency::prepare(const std::filesystem::path& source, const std::filesys
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dependency::download(const std::filesystem::path& destination) {
|
||||
std::filesystem::path dwn = destination / "downloads";
|
||||
bool result = std::filesystem::create_directories(dwn);
|
||||
// if (!result) {
|
||||
// Project::error("couldn't create " + dwn.string());
|
||||
// return result;
|
||||
// }
|
||||
bool Dependency::downloadRepo(
|
||||
const std::filesystem::path& destination,
|
||||
const std::string& protocol,
|
||||
const std::string& host,
|
||||
const std::string& owner,
|
||||
const std::string& repo
|
||||
) {
|
||||
nlohmann::json info;
|
||||
Project::info("Trying Gitea v1 API");
|
||||
bool res = repoGiteaApi1(protocol, host, owner, repo, info);
|
||||
|
||||
CURL *curl_handle;
|
||||
std::filesystem::path out = dwn / ("out" + std::to_string(std::rand()));
|
||||
FILE *pagefile;
|
||||
if (res) {
|
||||
nlohmann::json::const_iterator itr = info.find("default_branch");
|
||||
if (itr != info.end() && itr->is_string()) {
|
||||
std::string branchName = *itr;
|
||||
Project::info("Gitea v1 API seem to have worked");
|
||||
Project::info("Default branch is " + branchName);
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
/* init the curl session */
|
||||
curl_handle = curl_easy_init();
|
||||
/* set URL to get here */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, path.c_str());
|
||||
/* disable progress meter, set to 0L to enable it */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
|
||||
/* send all data to this function */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write);
|
||||
|
||||
/* open the file */
|
||||
pagefile = fopen(out.c_str(), "wb");
|
||||
if (pagefile) {
|
||||
/* write the page body to this file handle */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, pagefile);
|
||||
/* get it! */
|
||||
curl_easy_perform(curl_handle);
|
||||
/* close the header file */
|
||||
fclose(pagefile);
|
||||
} else {
|
||||
Project::error(std::string("couldn't open output file ") + out.c_str());
|
||||
std::string fileName = branchName + ".tar.gz";
|
||||
std::string url = protocol + "://" + host + "/api/v1/repos/" + owner + "/" + repo + "/archive/" + fileName;
|
||||
res = download(url, destination / "downloads" / fileName);
|
||||
if (res)
|
||||
Project::info("Successfully downloaded " + fileName);
|
||||
} else {
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup curl stuff */
|
||||
curl_easy_cleanup(curl_handle);
|
||||
curl_global_cleanup();
|
||||
if (!res) {
|
||||
Project::warn("Gitea v1 API didn't work");
|
||||
}
|
||||
|
||||
return true;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Dependency::repoGiteaApi1(
|
||||
const std::string& protocol,
|
||||
const std::string& host,
|
||||
const std::string& owner,
|
||||
const std::string& repo,
|
||||
nlohmann::json& json
|
||||
) {
|
||||
bool result = false;
|
||||
std::string url = protocol + "://" + host + "/api/v1/repos/" + owner + "/" + repo;
|
||||
std::string data;
|
||||
CURLcode code = httpGet(url, data, {acceptJson});
|
||||
if (code == CURLE_OK) {
|
||||
try {
|
||||
json = nlohmann::json::parse(data);
|
||||
result = true;
|
||||
} catch (const nlohmann::json::exception& e) {
|
||||
Project::warn(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Dependency::httpGet(const std::string& url, std::string& result, const std::list<std::string_view>& headers) {
|
||||
CURL* curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
|
||||
|
||||
struct curl_slist* curlHeaders = nullptr;
|
||||
for (const std::string_view& header : headers)
|
||||
curlHeaders = curl_slist_append(curlHeaders, header.data());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curlHeaders);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeString);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, trace);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, this);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
size_t Dependency::write(void* file, size_t size, size_t nmemb, void* stream) {
|
||||
size_t written = fwrite(file, size, nmemb, (FILE *)stream);
|
||||
bool Dependency::download(const std::string& url, const std::filesystem::path& destination) {
|
||||
std::filesystem::create_directories(destination.parent_path());
|
||||
if (std::filesystem::exists(destination))
|
||||
Project::minor("File " + destination.string() + " already exists, will be overwritten");
|
||||
|
||||
bool result = false;
|
||||
CURL* curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFile);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, trace);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, this);
|
||||
|
||||
FILE* pagefile = fopen(destination.c_str(), "wb");
|
||||
if (pagefile) {
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, pagefile);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
fclose(pagefile);
|
||||
if (res != CURLE_OK) {
|
||||
Project::warn("Couldn't download file " + url + ": " + curl_easy_strerror(res));
|
||||
} else {
|
||||
uint32_t code;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
if (code == 200)
|
||||
result = true;
|
||||
else
|
||||
Project::warn("Couldn't download file " + url + ": response code " + std::to_string(code));
|
||||
}
|
||||
} else {
|
||||
Project::error(std::string("couldn't open output file ") + destination.c_str());
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (!result) {
|
||||
Project::minor("Removing " + destination.string() + " since the donwload failed");
|
||||
std::filesystem::remove(destination);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t Dependency::writeString(void* data, size_t size, size_t nmemb, void* pointer) {
|
||||
size_t finalSize = size * nmemb;
|
||||
std::string* string = static_cast<std::string*>(pointer);
|
||||
string->append(static_cast<char*>(data), finalSize);
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
size_t Dependency::writeFile(void* data, size_t size, size_t nmemb, void* file) {
|
||||
size_t written = fwrite(data, size, nmemb, (FILE *)file);
|
||||
return written;
|
||||
}
|
||||
|
||||
int Dependency::trace(CURL* handle, curl_infotype type, char* data, size_t size, void* clientp) {
|
||||
switch (type) {
|
||||
case CURLINFO_TEXT: {
|
||||
std::string message(data, size);
|
||||
if (message[size - 1] == '\n')
|
||||
message = message.substr(0, size - 1);
|
||||
|
||||
Project::debug(message);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,12 @@
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <filesystem>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <list>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <curl/curl.h>
|
||||
|
||||
class Dependency {
|
||||
public:
|
||||
enum class Type {
|
||||
@ -31,8 +33,26 @@ public:
|
||||
const std::string path;
|
||||
|
||||
private:
|
||||
static size_t write(void *file, size_t size, size_t nmemb, void *stream);
|
||||
bool download(const std::filesystem::path& destination);
|
||||
static size_t writeFile(void* data, size_t size, size_t nmemb, void* file);
|
||||
static size_t writeString(void* data, size_t size, size_t nmemb, void* mem);
|
||||
static int trace(CURL *handle, curl_infotype type, char *data, size_t size, void *clientp);
|
||||
bool download(const std::string& url, const std::filesystem::path& destination);
|
||||
|
||||
bool downloadRepo(
|
||||
const std::filesystem::path& destination,
|
||||
const std::string& protocol,
|
||||
const std::string& host,
|
||||
const std::string& owner,
|
||||
const std::string& repo
|
||||
);
|
||||
bool repoGiteaApi1(
|
||||
const std::string& protocol,
|
||||
const std::string& host,
|
||||
const std::string& owner,
|
||||
const std::string& repo,
|
||||
nlohmann::json& json
|
||||
);
|
||||
CURLcode httpGet(const std::string& url, std::string& result, const std::list<std::string_view>& headers = {});
|
||||
|
||||
private:
|
||||
Type type;
|
||||
|
@ -24,7 +24,8 @@ constexpr const std::string_view bold("\e[1m");
|
||||
constexpr const std::string_view regular("\e[22m");
|
||||
constexpr const std::string_view clearStyle("\e[0m");
|
||||
|
||||
Logger::Logger(Logger::Severity severity):
|
||||
Logger::Logger(Logger::Severity severity, bool accumulate):
|
||||
accumulate(accumulate),
|
||||
currentSeverity(severity),
|
||||
history(),
|
||||
readMutex(),
|
||||
@ -34,26 +35,41 @@ Logger::Logger(Logger::Severity severity):
|
||||
Logger::~Logger()
|
||||
{}
|
||||
|
||||
void Logger::printLog(bool colored) {
|
||||
void Logger::printLog(bool colored) const {
|
||||
std::cout << std::endl;
|
||||
for (const Message& message : history) {
|
||||
if (colored) {
|
||||
int severity = static_cast<int>(message.first);
|
||||
std::cout << logSettings[severity] << bold << logHeaders[severity] << regular;
|
||||
}
|
||||
std::cout << message.second << std::endl;
|
||||
}
|
||||
std::scoped_lock lock(readMutex);
|
||||
for (const Message& message : history)
|
||||
printMessage(message, colored);
|
||||
|
||||
if (colored)
|
||||
std::cout << clearStyle << std::flush;
|
||||
}
|
||||
|
||||
void Logger::log(Logger::Severity severity, const std::string& comment) const {
|
||||
std::scoped_lock lock(readMutex, writeMutex);
|
||||
if (severity >= currentSeverity)
|
||||
void Logger::log(Logger::Severity severity, const std::string& comment, bool colored) const {
|
||||
if (severity < currentSeverity)
|
||||
return;
|
||||
|
||||
if (accumulate) {
|
||||
std::scoped_lock lock(readMutex, writeMutex);
|
||||
history.emplace_back(severity, comment);
|
||||
} else {
|
||||
std::scoped_lock lock(writeMutex);
|
||||
printMessage({severity, comment}, colored);
|
||||
|
||||
if (colored)
|
||||
std::cout << clearStyle << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<std::pair<Logger::Severity, std::string>> Logger::getLog() const {
|
||||
std::scoped_lock lock(readMutex);
|
||||
return history;
|
||||
}
|
||||
|
||||
void Logger::printMessage(const Message& message, bool colored) const {
|
||||
if (colored) {
|
||||
int severity = static_cast<int>(message.first);
|
||||
std::cout << logSettings[severity] << bold << logHeaders[severity] << regular;
|
||||
}
|
||||
std::cout << message.second << std::endl;
|
||||
}
|
||||
|
@ -20,14 +20,18 @@ public:
|
||||
};
|
||||
typedef std::pair<Severity, std::string> Message;
|
||||
|
||||
Logger(Severity severity = Severity::info);
|
||||
Logger(Severity severity = Severity::info, bool accumulate = false);
|
||||
~Logger();
|
||||
|
||||
void log (Severity severity, const std::string& comment) const;
|
||||
void log (Severity severity, const std::string& comment, bool colored = true) const;
|
||||
std::list<Message> getLog() const;
|
||||
void printLog(bool colored = true);
|
||||
void printLog(bool colored = true) const;
|
||||
|
||||
private:
|
||||
void printMessage(const Message& message, bool colored = false) const;
|
||||
|
||||
private:
|
||||
bool accumulate;
|
||||
const Severity currentSeverity;
|
||||
mutable std::list<Message> history;
|
||||
mutable std::mutex readMutex;
|
||||
|
@ -25,12 +25,16 @@ Project::Project(const std::filesystem::path& location, const std::filesystem::p
|
||||
dependencies(),
|
||||
root(logger == nullptr)
|
||||
{
|
||||
if (root)
|
||||
logger = new Logger();
|
||||
if (root) {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
logger = new Logger(Logger::Severity::debug);
|
||||
}
|
||||
}
|
||||
|
||||
Project::~Project() {
|
||||
if (root) {
|
||||
curl_global_cleanup();
|
||||
|
||||
delete logger;
|
||||
logger = nullptr;
|
||||
}
|
||||
@ -178,6 +182,14 @@ void Project::debug(const std::string& message) {
|
||||
log(Logger::Severity::debug, message);
|
||||
}
|
||||
|
||||
void Project::minor(const std::string& message) {
|
||||
log(Logger::Severity::minor, message);
|
||||
}
|
||||
|
||||
void Project::major(const std::string& message) {
|
||||
log(Logger::Severity::major, message);
|
||||
}
|
||||
|
||||
void Project::error(const std::string& message) {
|
||||
log(Logger::Severity::error, message);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "dependency.h"
|
||||
#include "loggger.h"
|
||||
@ -33,6 +34,8 @@ public:
|
||||
static void log(Logger::Severity severity, const std::string& message);
|
||||
static void debug(const std::string& message);
|
||||
static void info(const std::string& message);
|
||||
static void minor(const std::string& message);
|
||||
static void major(const std::string& message);
|
||||
static void warn(const std::string& message);
|
||||
static void error(const std::string& message);
|
||||
static void fatal(const std::string& message);
|
||||
|
Loading…
Reference in New Issue
Block a user