sources as different names, explicit targets

This commit is contained in:
Blue 2023-10-02 14:19:24 -03:00
parent cc4d8d1fc3
commit 1d9a6ec3f8
Signed by: blue
GPG Key ID: 9B203B252A63EE38
10 changed files with 252 additions and 62 deletions

View File

@ -7,6 +7,7 @@ set(SOURCES
taskmanager.cpp
download.cpp
atomicmutex.cpp
source.cpp
)
set(HEADERS
@ -17,6 +18,7 @@ set(HEADERS
taskmanager.h
download.h
atomicmutex.h
source.h
)
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})

View File

@ -43,7 +43,7 @@ Collection::Collection(
librariesPath = root->getLibrariesPath();
std::lock_guard lock(mutex);
while (pendingSources.size() > 0) {
std::string source = pendingSources.front();
Source source = pendingSources.front();
pendingSources.pop();
processSource(source);
}
@ -54,15 +54,15 @@ Collection::Collection(
);
}
void Collection::addSource(const std::string& source) {
void Collection::addSource(const Source& source) {
std::lock_guard lock(mutex);
std::pair<Sources::const_iterator, bool> result = knownSources.emplace(source);
if (!result.second) {
major("Source " + source + " is already present, skipping as duplicate");
major("Source " + source.print() + " is already present, skipping as duplicate");
return;
}
debug("Adding source " + source);
debug("Adding source " + source.print());
switch (root->getState()) {
case Component::initial:
case Component::reading:
@ -78,69 +78,74 @@ void Collection::addSource(const std::string& source) {
}
}
void Collection::processSource(const std::string& source) {
if (isRemote(source))
void Collection::processSource(const Source& source) {
std::string path = source.getPath();
if (isRemote(path))
queueDownload(source);
else
queueRead(source, source);
queueRead(source, path);
}
void Collection::sourceDownaloded(const std::string& source, TaskManager::Error err) {
void Collection::sourceDownaloded(const Source& source, TaskManager::Error err) {
std::lock_guard lock(mutex);
Downloads::const_iterator itr = downloadingSources.find(source);
std::optional<std::filesystem::path> location = itr->second->getLocation();
downloadingSources.erase(itr);
if (err.has_value() || !location.has_value()) {
error("Coundn't download " + source + ": " + err.value()->what());
error("Coundn't download " + source.print() + ": " + err.value()->what());
return;
}
queueRead(source, location.value());
}
void Collection::sourceRead(const std::string& source, TaskManager::Error err) {
void Collection::sourceRead(const Source& source, TaskManager::Error err) {
std::lock_guard lock(mutex);
Components::iterator itr = readingSources.find(source);
if (err.has_value()) {
error("Coundn't read " + source + ": " + err.value()->what());
error("Coundn't read " + source.print() + ": " + err.value()->what());
readingSources.erase(itr);
return;
}
if (!itr->second->successfullyRead()) {
error("Source " + source + " had an error during read process, canceling build of this component");
error("Source " + source.print() + " had an error during read process, canceling build of this component");
readingSources.erase(itr);
return;
}
debug("Source " + source + " has been read, scheduling build");
debug("Source " + source.print() + " has been read, scheduling build");
std::pair<Components::iterator, bool> res = buildingSources.emplace(source, std::move(itr->second));
readingSources.erase(itr);
std::string tgt = target;
if (source.hasExplicitTarget())
tgt = source.getTarget();
taskManager->queue(
std::bind(&Component::build, res.first->second.get(), destination/librariesPath, target, true),
std::bind(&Component::build, res.first->second.get(), destination/librariesPath, tgt, true),
std::bind(&Collection::sourceBuilt, this, source, std::placeholders::_1)
);
}
void Collection::sourceBuilt(const std::string& source, TaskManager::Error err) {
void Collection::sourceBuilt(const Source& source, TaskManager::Error err) {
std::lock_guard lock(mutex);
Components::iterator itr = buildingSources.find(source);
bool success = itr->second->successfullyBuilt();
buildingSources.erase(itr);
if (err.has_value()) {
error("Coundn't read " + source + ": " + err.value()->what());
error("Coundn't read " + source.print() + ": " + err.value()->what());
return;
}
if (!success) {
error("Source " + source + " had an error during build process");
error("Source " + source.print() + " had an error during build process");
return;
}
debug("Source " + source + " has been built");
debug("Source " + source.print() + " has been built");
successSources.emplace(source);
}
@ -161,12 +166,12 @@ bool Collection::isRemote(const std::string& source) {
return std::regex_search(source, remote);
}
void Collection::queueDownload(const std::string& source) {
debug("Scheduling download of " + source);
void Collection::queueDownload(const Source& source) {
debug("Scheduling download of " + source.print());
std::pair<Downloads::iterator, bool> res = downloadingSources.emplace(std::piecewise_construct,
std::forward_as_tuple(source),
std::forward_as_tuple(
std::make_unique<Download>(source, destination/downloads, logger)
std::make_unique<Download>(source.getPath(), destination/downloads, logger)
)
);
@ -176,12 +181,12 @@ void Collection::queueDownload(const std::string& source) {
);
}
void Collection::queueRead(const std::string& source, const std::filesystem::path& location) {
debug("Scheduling read of " + source);
void Collection::queueRead(const Source& source, const std::filesystem::path& location) {
debug("Scheduling read of " + source.print());
std::pair<Components::iterator, bool> res = readingSources.emplace(std::piecewise_construct,
std::forward_as_tuple(source),
std::forward_as_tuple(
std::make_unique<Component>(location, this, logger)
std::make_unique<Component>(location, this, logger, source.getOptionalName())
)
);
@ -191,7 +196,7 @@ void Collection::queueRead(const std::string& source, const std::filesystem::pat
);
}
bool Collection::hasSource(const std::string& source) const {
bool Collection::hasSource(const Source& source) const {
std::lock_guard lock(mutex);
return _hasSource(source);
}
@ -221,7 +226,7 @@ bool Collection::success() const {
return _sourcesTotal() == _sourcesSuccess() && root->successfullyBuilt();
}
bool Collection::_hasSource(const std::string& source) const {
bool Collection::_hasSource(const Source& source) const {
return knownSources.count(source) > 0;
}

View File

@ -14,12 +14,13 @@
#include "component.h"
#include "download.h"
#include "taskmanager.h"
#include "source.h"
class Collection : protected Loggable {
using Sources = std::set<std::string>;
using SourcesQueue = std::queue<std::string>;
using Downloads = std::map<std::string, std::unique_ptr<Download>>;
using Components = std::map<std::string, std::unique_ptr<Component>>;
using Sources = std::set<Source>;
using SourcesQueue = std::queue<Source>;
using Downloads = std::map<Source, std::unique_ptr<Download>>;
using Components = std::map<Source, std::unique_ptr<Component>>;
public:
Collection(
@ -37,22 +38,22 @@ public:
unsigned int sourcesError() const;
unsigned int sourcesSuccess() const;
bool hasSource(const std::string& source) const;
void addSource(const std::string& source);
bool hasSource(const Source& source) const;
void addSource(const Source& source);
private:
void sourceDownaloded(const std::string& source, TaskManager::Error err);
void sourceRead(const std::string& source, TaskManager::Error err);
void sourceBuilt(const std::string& source, TaskManager::Error err);
void sourceDownaloded(const Source& source, TaskManager::Error err);
void sourceRead(const Source& source, TaskManager::Error err);
void sourceBuilt(const Source& source, TaskManager::Error err);
void rootBuilt(TaskManager::Error err);
static bool isRemote(const std::string& source);
void processSource(const std::string& source);
void queueDownload(const std::string& source);
void queueRead(const std::string& source, const std::filesystem::path& location);
void processSource(const Source& source);
void queueDownload(const Source& source);
void queueRead(const Source& source, const std::filesystem::path& location);
bool _hasSource(const std::string& source) const;
bool _hasSource(const Source& source) const;
unsigned int _sourcesTotal() const;
unsigned int _sourcesPending() const;
unsigned int _sourcesError() const;

View File

@ -42,7 +42,7 @@ Component::Component(
const std::filesystem::path& path,
Collection* collection,
const std::shared_ptr<Logger>& logger,
const std::string& name
const std::optional<std::string>& name
):
Loggable(logger),
state(initial),
@ -64,14 +64,14 @@ void Component::read() {
case std::filesystem::file_type::directory:
type = directory;
state = ready;
if (!tryReadingBuildScenarios() && name.empty())
if (!tryReadingBuildScenarios() && !name.has_value())
name = location.filename();
break;
case std::filesystem::file_type::regular:
type = file;
state = ready;
if (name.empty())
if (!name.has_value())
name = location.filename();
break;
@ -115,12 +115,12 @@ bool Component::readAsMason() {
return false;
}
if (name.empty()) {
if (!name.has_value()) {
std::optional<std::string> manifestName = tryStringValue(mnfst, "name");
if (manifestName.has_value())
name = manifestName.value();
if (name.empty()) {
if (!name.has_value()) {
major("Couldn't define name of the project at " + location.string() + ", using directory name as project name");
name = location.filename();
}
@ -141,18 +141,14 @@ bool Component::readMasonDependencies(const nlohmann::json& deps, const std::str
for (const nlohmann::json& dep : deps) {
switch (dep.type()) {
case nlohmann::json::value_t::string:
collection->addSource(dep);
collection->addSource({dep});
break;
case nlohmann::json::value_t::object: {
nlohmann::json::const_iterator ditr = dep.find("path");
if (ditr == dep.end())
std::optional<std::string> path = tryStringValue(dep, "path");
if (!path.has_value())
return errorScenario(manifestPath + " object of unexpected format in dependecies");
nlohmann::json path = *ditr;
if (!path.is_string())
return errorScenario(manifestPath + " object of unexpected format in dependecies");
collection->addSource(path);
collection->addSource({path.value(), tryStringValue(dep, "target"), tryStringValue(dep, "name")});
}
break;
default:
@ -181,20 +177,20 @@ void Component::build(const std::filesystem::path& destination, const std::strin
switch (type) {
case file:
if (useName)
buildAsFile(destination/name);
buildAsFile(destination/name.value());
else
buildAsFile(destination);
break;
case directory:
if (useName)
buildAsDirectory(destination/name);
buildAsDirectory(destination/name.value());
else
buildAsDirectory(destination);
break;
case mason:
if (useName)
buildAsMason(destination/name, target);
buildAsMason(destination/name.value(), target);
else
buildAsMason(destination, target);
break;

View File

@ -41,7 +41,7 @@ public:
const std::filesystem::path& path,
Collection* collection,
const std::shared_ptr<Logger>& logger,
const std::string& name = ""
const std::optional<std::string>& name = std::nullopt
);
Type getType() const;
@ -84,7 +84,7 @@ private:
Collection* collection;
std::filesystem::path location;
std::optional<nlohmann::json> manifest;
std::string name;
std::optional<std::string> name;
};
class Component::WrongState : public std::runtime_error {

View File

@ -7,6 +7,7 @@
int main(int argc, char *argv[]) {
std::string firstArg;
std::string secondArg;
std::string thirdArg;
if (argc > 1)
firstArg = argv[1];
else
@ -17,13 +18,18 @@ int main(int argc, char *argv[]) {
else
secondArg = "./";
if (argc > 3)
thirdArg = argv[3];
else
thirdArg = "";
std::shared_ptr<Logger> logger = std::make_shared<Logger>(Logger::Severity::debug);
std::shared_ptr<Logger> logger = std::make_shared<Logger>(Logger::Severity::info);
std::shared_ptr<TaskManager> taskManager = std::make_shared<TaskManager>(logger);
std::shared_ptr<Collection> collection = std::make_shared<Collection>(
firstArg,
secondArg,
"",
thirdArg,
logger,
taskManager
);

129
src/source.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "source.h"
Source::Source(const std::string& path) :
path(path),
target(std::nullopt),
name(std::nullopt)
{}
Source::Source(const std::string& path, const std::string& target) :
path(path),
target(target),
name(std::nullopt)
{}
Source::Source(const std::string& path, const std::string& target, const std::string& name) :
path(path),
target(target),
name(name)
{}
Source::Source(const std::string& path, const std::optional<std::string>& target, const std::optional<std::string>& name) :
path(path),
target(target),
name(name)
{}
void Source::clearName() {
name = std::nullopt;
}
void Source::clearTarget() {
target = std::nullopt;
}
std::string Source::getPath() const {
return path;
}
std::string Source::getTarget() const {
if (target.has_value())
return target.value();
else
return "";
}
std::string Source::getName() const {
if (name.has_value())
return name.value();
else
return "";
}
std::optional<std::string> Source::getOptionalTarget() const {
return target;
}
std::optional<std::string> Source::getOptionalName() const {
return name;
}
bool Source::hasExplicitTarget() const {
return target.has_value();
}
bool Source::hasExplicitName() const {
return name.has_value();
}
void Source::setPath(const std::string& path) {
Source::path = path;
}
void Source::setTarget(const std::string& target) {
Source::target = target;
}
void Source::setName(const std::string& name) {
Source::name = name;
}
bool Source::operator < (const Source& other) const {
if (path < other.path)
return true;
else if (path > other.path)
return false;
else {
if (hasExplicitTarget()) {
if (other.hasExplicitTarget()) {
if (target.value() < other.target.value())
return true;
else if (target.value() > other.target.value()) {
return false;
} else {
if (hasExplicitName()) {
if (other.hasExplicitName()) {
return name.value() < other.name.value();
} else
return false;
} else
return other.hasExplicitName();
}
} else
return false;
} else {
if (other.hasExplicitTarget())
return true;
else {
if (hasExplicitName()) {
if (other.hasExplicitName()) {
return name.value() < other.name.value();
} else
return false;
} else
return other.hasExplicitName();
}
}
}
}
std::string Source::print() const {
std::string result = path;
if (hasExplicitTarget())
result += " -> " + target.value();
if (hasExplicitName())
result += " (as " + name.value() + ")";
return result;
}

37
src/source.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <optional>
#include <string>
class Source {
public:
Source(const std::string& path);
Source(const std::string& path, const std::string& target);
Source(const std::string& path, const std::string& target, const std::string& name);
Source(const std::string& path, const std::optional<std::string>& target, const std::optional<std::string>& name);
std::string getPath() const;
std::string getTarget() const;
std::string getName() const;
std::optional<std::string> getOptionalTarget() const;
std::optional<std::string> getOptionalName() const;
void setPath(const std::string& path);
void setTarget(const std::string& target);
void setName(const std::string& name);
std::string print() const;
void clearTarget();
void clearName();
bool hasExplicitTarget() const;
bool hasExplicitName() const;
bool operator < (const Source& other) const;
private:
std::string path;
std::optional<std::string> target;
std::optional<std::string> name;
};

View File

@ -95,8 +95,13 @@ void TaskManager::executeTask(const Task& task) const {
try {
task.first();
} catch (const std::exception& e) {
if (task.second.has_value())
task.second.value()(&e);
if (task.second.has_value()) {
try {
task.second.value()(&e);
} catch (const std::exception& e) {
error(std::string("Uncaught exception: ") + e.what());
}
}
return;
}

View File

@ -10,7 +10,16 @@
"path" : "https://nowhere/to/get.from"
},
"https://git.macaw.me/blue/mason/archive/main.tar.gz",
"https://git.macaw.me/blue/mason/raw/branch/main/src2/atomicmutex.h"
"https://git.macaw.me/blue/mason/raw/branch/main/src2/atomicmutex.h",
{
"path" : "https://git.macaw.me/blue/mason/raw/branch/main/src2/atomicmutex.h",
"name" : "changed.h"
},
{
"path" : "https://git.macaw.me/blue/mimicry.git",
"name" : "mimicryNode",
"target" : "node"
}
],
"build": [
"mason.json",