first attempt to download something
This commit is contained in:
parent
60b2220b97
commit
7ac697f111
@ -23,6 +23,7 @@ elseif (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(nlohmann_json REQUIRED)
|
find_package(nlohmann_json REQUIRED)
|
||||||
|
find_package(CURL REQUIRED)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME})
|
add_executable(${PROJECT_NAME})
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ add_subdirectory(src)
|
|||||||
add_subdirectory(test)
|
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)
|
||||||
|
|
||||||
install(TARGETS ${PROJECT_NAME}
|
install(TARGETS ${PROJECT_NAME}
|
||||||
EXPORT ${PROJECT_NAME}Targets
|
EXPORT ${PROJECT_NAME}Targets
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
set(SOURCES
|
set(SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
|
loggger.cpp
|
||||||
project.cpp
|
project.cpp
|
||||||
dependency.cpp
|
dependency.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
logger.h
|
||||||
project.h
|
project.h
|
||||||
dependency.cpp
|
dependency.cpp
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
#include "dependency.h"
|
#include "dependency.h"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "project.h"
|
||||||
|
|
||||||
|
const std::regex http("^https?://");
|
||||||
|
|
||||||
Dependency::Dependency(
|
Dependency::Dependency(
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
Type type,
|
Type type,
|
||||||
@ -23,3 +29,69 @@ std::optional<std::string> Dependency::getName() const {
|
|||||||
std::optional<std::string> Dependency::getVersion() const {
|
std::optional<std::string> Dependency::getVersion() const {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
return download(destination);
|
||||||
|
} else {
|
||||||
|
Project::info("checking project at path " + path);
|
||||||
|
std::filesystem::directory_entry srcDir(source / path);
|
||||||
|
if (!srcDir.exists()) {
|
||||||
|
Project::error("Project at " + path + " doesn't exist");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
CURL *curl_handle;
|
||||||
|
std::filesystem::path out = dwn / ("out" + std::to_string(std::rand()));
|
||||||
|
FILE *pagefile;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup curl stuff */
|
||||||
|
curl_easy_cleanup(curl_handle);
|
||||||
|
curl_global_cleanup();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t Dependency::write(void* file, size_t size, size_t nmemb, void* stream) {
|
||||||
|
size_t written = fwrite(file, size, nmemb, (FILE *)stream);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
class Dependency {
|
class Dependency {
|
||||||
public:
|
public:
|
||||||
@ -22,8 +26,14 @@ public:
|
|||||||
std::optional<std::string> getName() const;
|
std::optional<std::string> getName() const;
|
||||||
std::optional<std::string> getVersion() const;
|
std::optional<std::string> getVersion() const;
|
||||||
|
|
||||||
|
bool prepare(const std::filesystem::path& source, const std::filesystem::path& destination);
|
||||||
|
|
||||||
const std::string path;
|
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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type;
|
Type type;
|
||||||
std::optional<std::string> name;
|
std::optional<std::string> name;
|
||||||
|
59
src/loggger.cpp
Normal file
59
src/loggger.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "loggger.h"
|
||||||
|
|
||||||
|
constexpr const std::array<std::string_view, static_cast<int>(Logger::Severity::fatal) + 1> logSettings({
|
||||||
|
/*debug*/ "\e[90m",
|
||||||
|
/*info*/ "\e[32m",
|
||||||
|
/*minor*/ "\e[34m",
|
||||||
|
/*major*/ "\e[94m",
|
||||||
|
/*warning*/ "\e[33m",
|
||||||
|
/*error*/ "\e[31m",
|
||||||
|
/*fatal*/ "\e[91m"
|
||||||
|
});
|
||||||
|
|
||||||
|
constexpr const std::array<std::string_view, static_cast<int>(Logger::Severity::fatal) + 1> logHeaders({
|
||||||
|
/*debug*/ "DEBUG: ",
|
||||||
|
/*info*/ "INFO: ",
|
||||||
|
/*minor*/ "MINOR: ",
|
||||||
|
/*major*/ "MAJOR: ",
|
||||||
|
/*warning*/ "WARNING: ",
|
||||||
|
/*error*/ "ERROR: ",
|
||||||
|
/*fatal*/ "FATAL: "
|
||||||
|
});
|
||||||
|
|
||||||
|
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):
|
||||||
|
currentSeverity(severity),
|
||||||
|
history(),
|
||||||
|
readMutex(),
|
||||||
|
writeMutex()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Logger::~Logger()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Logger::printLog(bool colored) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
history.emplace_back(severity, comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::pair<Logger::Severity, std::string>> Logger::getLog() const {
|
||||||
|
std::scoped_lock lock(readMutex);
|
||||||
|
return history;
|
||||||
|
}
|
36
src/loggger.h
Normal file
36
src/loggger.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
#include <array>
|
||||||
|
#include <string_view>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
public:
|
||||||
|
enum class Severity {
|
||||||
|
debug,
|
||||||
|
info,
|
||||||
|
minor,
|
||||||
|
major,
|
||||||
|
warning,
|
||||||
|
error,
|
||||||
|
fatal
|
||||||
|
};
|
||||||
|
typedef std::pair<Severity, std::string> Message;
|
||||||
|
|
||||||
|
Logger(Severity severity = Severity::info);
|
||||||
|
~Logger();
|
||||||
|
|
||||||
|
void log (Severity severity, const std::string& comment) const;
|
||||||
|
std::list<Message> getLog() const;
|
||||||
|
void printLog(bool colored = true);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Severity currentSeverity;
|
||||||
|
mutable std::list<Message> history;
|
||||||
|
mutable std::mutex readMutex;
|
||||||
|
mutable std::mutex writeMutex;
|
||||||
|
|
||||||
|
};
|
27
src/main.cpp
27
src/main.cpp
@ -1,29 +1,34 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
std::string firstArg;
|
std::string firstArg;
|
||||||
|
std::string secondArg;
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
firstArg = argv[1];
|
firstArg = argv[1];
|
||||||
else
|
else
|
||||||
firstArg = "./";
|
firstArg = "./";
|
||||||
|
|
||||||
Project root(firstArg);
|
if (argc > 2)
|
||||||
|
secondArg = argv[2];
|
||||||
|
else
|
||||||
|
secondArg = "./";
|
||||||
|
|
||||||
|
Project root(firstArg, secondArg);
|
||||||
bool success = root.read();
|
bool success = root.read();
|
||||||
|
|
||||||
if (!success) {
|
int result = -1;
|
||||||
Project::Log log(root.getLog());
|
if (success) {
|
||||||
for (const Project::LogMessage& msg : log)
|
root.info("successfully parsed project " + root.getName());
|
||||||
std::cout << msg << std::endl;
|
root.info("dependencies count is " + std::to_string(root.dependenciesCount()));
|
||||||
|
|
||||||
return -1;
|
root.discover();
|
||||||
} else {
|
result = 0;
|
||||||
std::cout << "successfully parsed project " << root.getName() << std::endl;
|
|
||||||
std::cout << "dependencies count is " << root.dependenciesCount() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root.printLog();
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
100
src/project.cpp
100
src/project.cpp
@ -15,31 +15,54 @@ std::map<std::string, Dependency::Type> types({
|
|||||||
{"automatic", Dependency::Type::automatic}
|
{"automatic", Dependency::Type::automatic}
|
||||||
});
|
});
|
||||||
|
|
||||||
Project::Project(const std::filesystem::path& location):
|
Logger* Project::logger = nullptr;
|
||||||
|
|
||||||
|
Project::Project(const std::filesystem::path& location, const std::filesystem::path& destination):
|
||||||
location(location),
|
location(location),
|
||||||
status(Status::unknown),
|
destination(destination),
|
||||||
|
state(State::unknown),
|
||||||
name(),
|
name(),
|
||||||
logStorage(),
|
dependencies(),
|
||||||
dependencies()
|
root(logger == nullptr)
|
||||||
{}
|
{
|
||||||
|
if (root)
|
||||||
|
logger = new Logger();
|
||||||
|
}
|
||||||
|
|
||||||
|
Project::~Project() {
|
||||||
|
if (root) {
|
||||||
|
delete logger;
|
||||||
|
logger = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Project::read() {
|
bool Project::read() {
|
||||||
if (status == Status::read)
|
if (state == State::read)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
std::filesystem::path entryPointPath;
|
std::filesystem::path entryPointPath;
|
||||||
try {
|
try {
|
||||||
entryPointPath = std::filesystem::canonical(location) / entry;
|
location = std::filesystem::canonical(location);
|
||||||
|
entryPointPath = location / entry;
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
log(e.what());
|
fatal(e.what());
|
||||||
status = Status::error;
|
state = State::error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::filesystem::create_directories(destination);
|
||||||
|
destination = std::filesystem::canonical(destination);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
fatal(e.what());
|
||||||
|
state = State::error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream file(entryPointPath);
|
std::ifstream file(entryPointPath);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
log("couldn't open " + std::string(entryPointPath));
|
fatal("couldn't open " + entryPointPath.string());
|
||||||
status = Status::error;
|
state = State::error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,16 +70,16 @@ bool Project::read() {
|
|||||||
try {
|
try {
|
||||||
data = json::parse(file);
|
data = json::parse(file);
|
||||||
} catch (const json::exception& e) {
|
} catch (const json::exception& e) {
|
||||||
log(e.what());
|
fatal(e.what());
|
||||||
status = Status::error;
|
state = State::error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
parse(data);
|
parse(data);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
log(e.what());
|
fatal(e.what());
|
||||||
status = Status::error;
|
state = State::error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,21 +149,54 @@ void Project::createDepencencyFromObject(const nlohmann::json& entry) {
|
|||||||
dependencies.emplace(url, Dependency{url, type, name, version});
|
dependencies.emplace(url, Dependency{url, type, name, version});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Project::discover() {
|
||||||
|
int fine = 0;
|
||||||
|
for (std::pair<const std::string, Dependency>& pair : dependencies) {
|
||||||
|
bool success = pair.second.prepare(location, destination);
|
||||||
|
if (success)
|
||||||
|
fine++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t Project::dependenciesCount() const {
|
uint32_t Project::dependenciesCount() const {
|
||||||
return dependencies.size();
|
return dependencies.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Project::log(Logger::Severity severity, const std::string& message) {
|
||||||
void Project::log(const std::string& message) const {
|
if (logger != nullptr)
|
||||||
logStorage.emplace_back(message);
|
logger->log(severity, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::Log Project::getLog() const {
|
void Project::info(const std::string& message) {
|
||||||
return logStorage;
|
log(Logger::Severity::info, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::Status Project::getStatus() const {
|
void Project::debug(const std::string& message) {
|
||||||
return status;
|
log(Logger::Severity::debug, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Project::error(const std::string& message) {
|
||||||
|
log(Logger::Severity::error, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Project::warn(const std::string& message) {
|
||||||
|
log(Logger::Severity::warning, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Project::fatal(const std::string& message) {
|
||||||
|
log(Logger::Severity::fatal, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Project::printLog() {
|
||||||
|
if (logger != nullptr)
|
||||||
|
logger->printLog();
|
||||||
|
}
|
||||||
|
|
||||||
|
Project::State Project::getStatus() const {
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Project::getName() const {
|
std::string Project::getName() const {
|
||||||
|
@ -10,35 +10,47 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "dependency.h"
|
#include "dependency.h"
|
||||||
|
#include "loggger.h"
|
||||||
|
|
||||||
class Project {
|
class Project {
|
||||||
public:
|
public:
|
||||||
typedef std::string LogMessage;
|
enum class State {
|
||||||
typedef std::list<LogMessage> Log;
|
|
||||||
enum class Status {
|
|
||||||
unknown,
|
unknown,
|
||||||
read,
|
read,
|
||||||
|
discovering,
|
||||||
error
|
error
|
||||||
};
|
};
|
||||||
|
|
||||||
Project(const std::filesystem::path& location);
|
Project(const std::filesystem::path& location, const std::filesystem::path& destination);
|
||||||
|
~Project();
|
||||||
|
|
||||||
bool read();
|
bool read();
|
||||||
Status getStatus() const;
|
void discover();
|
||||||
Log getLog() const;
|
State getStatus() const;
|
||||||
std::string getName() const;
|
std::string getName() const;
|
||||||
uint32_t dependenciesCount() const;
|
uint32_t dependenciesCount() const;
|
||||||
|
|
||||||
|
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 warn(const std::string& message);
|
||||||
|
static void error(const std::string& message);
|
||||||
|
static void fatal(const std::string& message);
|
||||||
|
static void printLog();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void log(const std::string& message) const;
|
|
||||||
void parse(const nlohmann::json& json);
|
void parse(const nlohmann::json& json);
|
||||||
void createDepencencyFromString(const std::string& entry);
|
void createDepencencyFromString(const std::string& entry);
|
||||||
void createDepencencyFromObject(const nlohmann::json& entry);
|
void createDepencencyFromObject(const nlohmann::json& entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path location;
|
std::filesystem::path location;
|
||||||
Status status;
|
std::filesystem::path destination;
|
||||||
|
State state;
|
||||||
std::string name;
|
std::string name;
|
||||||
mutable Log logStorage;
|
|
||||||
std::map<std::string, Dependency> dependencies;
|
std::map<std::string, Dependency> dependencies;
|
||||||
|
const bool root;
|
||||||
|
|
||||||
|
static Logger* logger;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user