extracted downloaded archive
This commit is contained in:
parent
76bd9a0497
commit
5ee7ae7f73
@ -24,6 +24,7 @@ endif()
|
|||||||
|
|
||||||
find_package(nlohmann_json REQUIRED)
|
find_package(nlohmann_json REQUIRED)
|
||||||
find_package(CURL REQUIRED)
|
find_package(CURL REQUIRED)
|
||||||
|
find_package(LibArchive REQUIRED)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME})
|
add_executable(${PROJECT_NAME})
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ add_subdirectory(test)
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
|
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl)
|
target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE LibArchive::LibArchive)
|
||||||
|
|
||||||
install(TARGETS ${PROJECT_NAME}
|
install(TARGETS ${PROJECT_NAME}
|
||||||
EXPORT ${PROJECT_NAME}Targets
|
EXPORT ${PROJECT_NAME}Targets
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
|
||||||
|
constexpr std::string_view downloads("downloads");
|
||||||
|
constexpr std::string_view build("build");
|
||||||
|
|
||||||
constexpr std::string_view acceptJson("accept: application/json");
|
constexpr std::string_view acceptJson("accept: application/json");
|
||||||
const std::regex http("^https?:\\/\\/");
|
const std::regex http("^https?:\\/\\/");
|
||||||
const std::regex repo("(^https?):\\/\\/([\\w\\d\\.\\-\\_]+)\\/([\\w\\d\\-\\_]+)\\/([\\w\\d\\-\\_]+)");
|
const std::regex repo("(^https?):\\/\\/([\\w\\d\\.\\-\\_]+)\\/([\\w\\d\\-\\_]+)\\/([\\w\\d\\-\\_]+)");
|
||||||
@ -74,9 +77,16 @@ bool Dependency::downloadRepo(
|
|||||||
|
|
||||||
std::string fileName = branchName + ".tar.gz";
|
std::string fileName = branchName + ".tar.gz";
|
||||||
std::string url = protocol + "://" + host + "/api/v1/repos/" + owner + "/" + repo + "/archive/" + fileName;
|
std::string url = protocol + "://" + host + "/api/v1/repos/" + owner + "/" + repo + "/archive/" + fileName;
|
||||||
res = download(url, destination / "downloads" / fileName);
|
std::filesystem::path archivePath = destination/downloads/fileName;
|
||||||
if (res)
|
res = download(url, archivePath);
|
||||||
Project::info("Successfully downloaded " + fileName);
|
if (res) {
|
||||||
|
Project::info("Successfully downloaded " + archivePath.string());
|
||||||
|
|
||||||
|
res = extract(archivePath, destination/build);
|
||||||
|
if (!res) {
|
||||||
|
Project::error("Couldn't extract archive " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
@ -139,9 +149,13 @@ CURLcode Dependency::httpGet(const std::string& url, std::string& result, const
|
|||||||
|
|
||||||
bool Dependency::download(const std::string& url, const std::filesystem::path& destination) {
|
bool Dependency::download(const std::string& url, const std::filesystem::path& destination) {
|
||||||
std::filesystem::create_directories(destination.parent_path());
|
std::filesystem::create_directories(destination.parent_path());
|
||||||
if (std::filesystem::exists(destination))
|
if (std::filesystem::exists(destination)) {
|
||||||
Project::minor("File " + destination.string() + " already exists, will be overwritten");
|
Project::minor("File " + destination.string() + " already exists, will be overwritten");
|
||||||
|
|
||||||
|
if (std::filesystem::is_directory(destination))
|
||||||
|
std::filesystem::remove_all(destination);
|
||||||
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
CURL* curl = curl_easy_init();
|
CURL* curl = curl_easy_init();
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||||
@ -169,14 +183,14 @@ bool Dependency::download(const std::string& url, const std::filesystem::path& d
|
|||||||
Project::warn("Couldn't download file " + url + ": response code " + std::to_string(code));
|
Project::warn("Couldn't download file " + url + ": response code " + std::to_string(code));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Project::error(std::string("couldn't open output file ") + destination.c_str());
|
Project::error(std::string("Couldn't open output file ") + destination.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
Project::minor("Removing " + destination.string() + " since the donwload failed");
|
Project::minor("Removing " + destination.string() + " since the donwload failed");
|
||||||
std::filesystem::remove(destination);
|
std::filesystem::remove_all(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -211,3 +225,99 @@ int Dependency::trace(CURL* handle, curl_infotype type, char* data, size_t size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Dependency::extract(const std::filesystem::path& source, const std::filesystem::path& destination) const {
|
||||||
|
int flags = ARCHIVE_EXTRACT_TIME;
|
||||||
|
flags |= ARCHIVE_EXTRACT_PERM;
|
||||||
|
flags |= ARCHIVE_EXTRACT_ACL;
|
||||||
|
flags |= ARCHIVE_EXTRACT_FFLAGS;
|
||||||
|
|
||||||
|
struct archive* a = archive_read_new();
|
||||||
|
struct archive* ext = archive_write_disk_new();
|
||||||
|
struct archive_entry *entry;
|
||||||
|
archive_read_support_format_all(a);
|
||||||
|
archive_read_support_filter_all(a);
|
||||||
|
archive_write_disk_set_options(ext, flags);
|
||||||
|
archive_write_disk_set_standard_lookup(ext);
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
|
bool readOpen = false;
|
||||||
|
bool writeOpen = false;
|
||||||
|
int r = archive_read_open_filename(a, source.c_str(), 10240);
|
||||||
|
if (r) {
|
||||||
|
Project::major("Couldn't open file " + source.string());
|
||||||
|
result = false;
|
||||||
|
} else {
|
||||||
|
readOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result) {
|
||||||
|
r = archive_read_next_header(a, &entry);
|
||||||
|
if (r == ARCHIVE_EOF)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (r < ARCHIVE_OK)
|
||||||
|
Project::major(archive_error_string(a));
|
||||||
|
|
||||||
|
if (r < ARCHIVE_WARN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
std::string fileName(archive_entry_pathname(entry));
|
||||||
|
std::filesystem::path filePath = destination/fileName;
|
||||||
|
Project::debug("Extracting " + filePath.string());
|
||||||
|
archive_entry_set_pathname_utf8(entry, filePath.c_str());
|
||||||
|
|
||||||
|
r = archive_write_header(ext, entry);
|
||||||
|
if (r < ARCHIVE_OK) {
|
||||||
|
Project::major(archive_error_string(ext));
|
||||||
|
} else if (archive_entry_size(entry) > 0) {
|
||||||
|
writeOpen = true;
|
||||||
|
r = copy(a, ext);
|
||||||
|
if (r < ARCHIVE_OK)
|
||||||
|
Project::major(archive_error_string(ext));
|
||||||
|
|
||||||
|
if (r < ARCHIVE_WARN)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r = archive_write_finish_entry(ext);
|
||||||
|
if (r < ARCHIVE_OK)
|
||||||
|
Project::major(archive_error_string(ext));
|
||||||
|
|
||||||
|
if (r < ARCHIVE_WARN)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readOpen)
|
||||||
|
archive_read_close(a);
|
||||||
|
|
||||||
|
if (writeOpen)
|
||||||
|
archive_write_close(ext);
|
||||||
|
|
||||||
|
archive_read_free(a);
|
||||||
|
archive_write_free(ext);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Dependency::copy(struct archive* ar, struct archive* aw) const {
|
||||||
|
int r;
|
||||||
|
const void *buff;
|
||||||
|
size_t size;
|
||||||
|
la_int64_t offset;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
r = archive_read_data_block(ar, &buff, &size, &offset);
|
||||||
|
if (r == ARCHIVE_EOF)
|
||||||
|
return ARCHIVE_OK;
|
||||||
|
|
||||||
|
if (r < ARCHIVE_OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = archive_write_data_block(aw, buff, size, offset);
|
||||||
|
if (r < ARCHIVE_OK) {
|
||||||
|
Project::major(archive_error_string(aw));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <archive.h>
|
||||||
|
#include <archive_entry.h>
|
||||||
|
|
||||||
class Dependency {
|
class Dependency {
|
||||||
public:
|
public:
|
||||||
@ -54,6 +56,9 @@ private:
|
|||||||
);
|
);
|
||||||
CURLcode httpGet(const std::string& url, std::string& result, const std::list<std::string_view>& headers = {});
|
CURLcode httpGet(const std::string& url, std::string& result, const std::list<std::string_view>& headers = {});
|
||||||
|
|
||||||
|
bool extract(const std::filesystem::path& source, const std::filesystem::path& destination) const;
|
||||||
|
int copy(struct archive *ar, struct archive *aw) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type;
|
Type type;
|
||||||
std::optional<std::string> name;
|
std::optional<std::string> name;
|
||||||
|
Loading…
Reference in New Issue
Block a user