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()
|
||||
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
find_package(CURL REQUIRED)
|
||||
|
||||
add_executable(${PROJECT_NAME})
|
||||
|
||||
@ -42,6 +43,7 @@ add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
|
@ -1,10 +1,12 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
loggger.cpp
|
||||
project.cpp
|
||||
dependency.cpp
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
logger.h
|
||||
project.h
|
||||
dependency.cpp
|
||||
)
|
||||
|
@ -1,5 +1,11 @@
|
||||
#include "dependency.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include "project.h"
|
||||
|
||||
const std::regex http("^https?://");
|
||||
|
||||
Dependency::Dependency(
|
||||
const std::string& path,
|
||||
Type type,
|
||||
@ -23,3 +29,69 @@ std::optional<std::string> Dependency::getName() const {
|
||||
std::optional<std::string> Dependency::getVersion() const {
|
||||
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 <optional>
|
||||
#include <filesystem>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class Dependency {
|
||||
public:
|
||||
@ -22,8 +26,14 @@ public:
|
||||
std::optional<std::string> getName() const;
|
||||
std::optional<std::string> getVersion() const;
|
||||
|
||||
bool prepare(const std::filesystem::path& source, const std::filesystem::path& destination);
|
||||
|
||||
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:
|
||||
Type type;
|
||||
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 "project.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::string firstArg;
|
||||
std::string secondArg;
|
||||
if (argc > 1)
|
||||
firstArg = argv[1];
|
||||
else
|
||||
firstArg = "./";
|
||||
|
||||
Project root(firstArg);
|
||||
if (argc > 2)
|
||||
secondArg = argv[2];
|
||||
else
|
||||
secondArg = "./";
|
||||
|
||||
Project root(firstArg, secondArg);
|
||||
bool success = root.read();
|
||||
|
||||
if (!success) {
|
||||
Project::Log log(root.getLog());
|
||||
for (const Project::LogMessage& msg : log)
|
||||
std::cout << msg << std::endl;
|
||||
int result = -1;
|
||||
if (success) {
|
||||
root.info("successfully parsed project " + root.getName());
|
||||
root.info("dependencies count is " + std::to_string(root.dependenciesCount()));
|
||||
|
||||
return -1;
|
||||
} else {
|
||||
std::cout << "successfully parsed project " << root.getName() << std::endl;
|
||||
std::cout << "dependencies count is " << root.dependenciesCount() << std::endl;
|
||||
root.discover();
|
||||
result = 0;
|
||||
}
|
||||
|
||||
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}
|
||||
});
|
||||
|
||||
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),
|
||||
status(Status::unknown),
|
||||
destination(destination),
|
||||
state(State::unknown),
|
||||
name(),
|
||||
logStorage(),
|
||||
dependencies()
|
||||
{}
|
||||
dependencies(),
|
||||
root(logger == nullptr)
|
||||
{
|
||||
if (root)
|
||||
logger = new Logger();
|
||||
}
|
||||
|
||||
Project::~Project() {
|
||||
if (root) {
|
||||
delete logger;
|
||||
logger = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Project::read() {
|
||||
if (status == Status::read)
|
||||
if (state == State::read)
|
||||
return true;
|
||||
|
||||
std::filesystem::path entryPointPath;
|
||||
try {
|
||||
entryPointPath = std::filesystem::canonical(location) / entry;
|
||||
location = std::filesystem::canonical(location);
|
||||
entryPointPath = location / entry;
|
||||
} catch (const std::exception& e) {
|
||||
log(e.what());
|
||||
status = Status::error;
|
||||
fatal(e.what());
|
||||
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;
|
||||
}
|
||||
|
||||
std::ifstream file(entryPointPath);
|
||||
if (!file.is_open()) {
|
||||
log("couldn't open " + std::string(entryPointPath));
|
||||
status = Status::error;
|
||||
fatal("couldn't open " + entryPointPath.string());
|
||||
state = State::error;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -47,16 +70,16 @@ bool Project::read() {
|
||||
try {
|
||||
data = json::parse(file);
|
||||
} catch (const json::exception& e) {
|
||||
log(e.what());
|
||||
status = Status::error;
|
||||
fatal(e.what());
|
||||
state = State::error;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
parse(data);
|
||||
} catch (const std::exception& e) {
|
||||
log(e.what());
|
||||
status = Status::error;
|
||||
fatal(e.what());
|
||||
state = State::error;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -126,21 +149,54 @@ void Project::createDepencencyFromObject(const nlohmann::json& entry) {
|
||||
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 {
|
||||
return dependencies.size();
|
||||
}
|
||||
|
||||
|
||||
void Project::log(const std::string& message) const {
|
||||
logStorage.emplace_back(message);
|
||||
void Project::log(Logger::Severity severity, const std::string& message) {
|
||||
if (logger != nullptr)
|
||||
logger->log(severity, message);
|
||||
}
|
||||
|
||||
Project::Log Project::getLog() const {
|
||||
return logStorage;
|
||||
void Project::info(const std::string& message) {
|
||||
log(Logger::Severity::info, message);
|
||||
}
|
||||
|
||||
Project::Status Project::getStatus() const {
|
||||
return status;
|
||||
void Project::debug(const std::string& message) {
|
||||
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 {
|
||||
|
@ -10,35 +10,47 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "dependency.h"
|
||||
#include "loggger.h"
|
||||
|
||||
class Project {
|
||||
public:
|
||||
typedef std::string LogMessage;
|
||||
typedef std::list<LogMessage> Log;
|
||||
enum class Status {
|
||||
enum class State {
|
||||
unknown,
|
||||
read,
|
||||
discovering,
|
||||
error
|
||||
};
|
||||
|
||||
Project(const std::filesystem::path& location);
|
||||
Project(const std::filesystem::path& location, const std::filesystem::path& destination);
|
||||
~Project();
|
||||
|
||||
bool read();
|
||||
Status getStatus() const;
|
||||
Log getLog() const;
|
||||
void discover();
|
||||
State getStatus() const;
|
||||
std::string getName() 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:
|
||||
void log(const std::string& message) const;
|
||||
void parse(const nlohmann::json& json);
|
||||
void createDepencencyFromString(const std::string& entry);
|
||||
void createDepencencyFromObject(const nlohmann::json& entry);
|
||||
|
||||
private:
|
||||
std::filesystem::path location;
|
||||
Status status;
|
||||
std::filesystem::path destination;
|
||||
State state;
|
||||
std::string name;
|
||||
mutable Log logStorage;
|
||||
std::map<std::string, Dependency> dependencies;
|
||||
const bool root;
|
||||
|
||||
static Logger* logger;
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user