targets and names

This commit is contained in:
Blue 2023-10-01 12:47:17 -03:00
parent 4843fcc77f
commit cc4d8d1fc3
Signed by: blue
GPG Key ID: 9B203B252A63EE38
4 changed files with 160 additions and 36 deletions

View File

@ -49,7 +49,7 @@ Collection::Collection(
}
taskManager->queue(
std::bind(&Component::build, root.get(), destination, target),
std::bind(&Component::build, root.get(), destination, target, false),
std::bind(&Collection::rootBuilt, this, std::placeholders::_1)
);
}
@ -120,7 +120,7 @@ void Collection::sourceRead(const std::string& source, TaskManager::Error err) {
readingSources.erase(itr);
taskManager->queue(
std::bind(&Component::build, res.first->second.get(), destination/librariesPath, target),
std::bind(&Component::build, res.first->second.get(), destination/librariesPath, target, true),
std::bind(&Collection::sourceBuilt, this, source, std::placeholders::_1)
);
}

View File

@ -41,14 +41,16 @@ constexpr std::array<std::string_view, Component::unknown + 1> stringTypes {
Component::Component(
const std::filesystem::path& path,
Collection* collection,
const std::shared_ptr<Logger>& logger
const std::shared_ptr<Logger>& logger,
const std::string& name
):
Loggable(logger),
state(initial),
type(unknown),
collection(collection),
location(path),
manifest(std::nullopt)
manifest(std::nullopt),
name(name)
{}
void Component::read() {
@ -62,11 +64,16 @@ void Component::read() {
case std::filesystem::file_type::directory:
type = directory;
state = ready;
tryReadingBuildScenarios();
if (!tryReadingBuildScenarios() && name.empty())
name = location.filename();
break;
case std::filesystem::file_type::regular:
type = file;
state = ready;
if (name.empty())
name = location.filename();
break;
default:
warn(location.string() + " doesn't appear to be a file nor a directory");
@ -75,9 +82,11 @@ void Component::read() {
}
}
void Component::tryReadingBuildScenarios() {
bool Component::tryReadingBuildScenarios() {
if (readAsMason())
return;
return true;
return false;
}
bool Component::readAsMason() {
@ -106,6 +115,17 @@ bool Component::readAsMason() {
return false;
}
if (name.empty()) {
std::optional<std::string> manifestName = tryStringValue(mnfst, "name");
if (manifestName.has_value())
name = manifestName.value();
if (name.empty()) {
major("Couldn't define name of the project at " + location.string() + ", using directory name as project name");
name = location.filename();
}
}
type = mason;
info(location.string() + " seems to be a valid mason project");
return true;
@ -151,7 +171,7 @@ bool Component::errorScenario(const std::string& message) {
return false;
}
void Component::build(const std::filesystem::path& destination, const std::string& target) {
void Component::build(const std::filesystem::path& destination, const std::string& target, bool useName) {
if (state != ready)
throw WrongState(state, "build");
@ -160,12 +180,22 @@ void Component::build(const std::filesystem::path& destination, const std::strin
switch (type) {
case file:
if (useName)
buildAsFile(destination/name);
else
buildAsFile(destination);
break;
case directory:
if (useName)
buildAsDirectory(destination/name);
else
buildAsDirectory(destination);
break;
case mason:
if (useName)
buildAsMason(destination/name, target);
else
buildAsMason(destination, target);
break;
default:
@ -174,13 +204,13 @@ void Component::build(const std::filesystem::path& destination, const std::strin
}
void Component::buildAsFile(const std::filesystem::path& destination) {
copyFile(location, destination/location.filename());
copyFile(location, destination);
state = done;
}
void Component::buildAsDirectory(const std::filesystem::path& destination) {
std::filesystem::copy(location, destination/location.filename(),
std::filesystem::copy(location, destination,
std::filesystem::copy_options::recursive |
std::filesystem::copy_options::overwrite_existing
);
@ -219,7 +249,7 @@ bool Component::successfullyBuilt() const {
return state == done;
}
void Component::buildAsMason(const std::filesystem::path& destination, const std::string& target) {
void Component::buildAsMason(const std::filesystem::path& destination, std::string target) {
const nlohmann::json& mnfst = manifest.value();
nlohmann::json::const_iterator itr = mnfst.find("build");
if (itr == mnfst.end()) {
@ -230,11 +260,13 @@ void Component::buildAsMason(const std::filesystem::path& destination, const std
const nlohmann::json& build = *itr;
if (!build.is_array()) {
warn("Mason project at " + location.string() + " has unexpected \"build\" section in its manifest");
warn("Mason project at " + location.string() + " has unexpected type \"build\" section in its manifest");
state = done;
return;
}
target = validateMasonTarget(target);
for (const nlohmann::json& entry : build) {
switch (entry.type()) {
case nlohmann::json::value_t::string:
@ -244,7 +276,7 @@ void Component::buildAsMason(const std::filesystem::path& destination, const std
masonFilesArray(entry, destination);
break;
case nlohmann::json::value_t::object:
if (allowedForTarget(entry, target)) {
if (allowedForMasonTarget(entry, target)) {
nlohmann::json::const_iterator fitr = entry.find("files");
if (fitr != entry.end()) {
const nlohmann::json& files = *fitr;
@ -254,6 +286,8 @@ void Component::buildAsMason(const std::filesystem::path& destination, const std
warn(std::string("Unexpected ") + entry.type_name()
+ " of files subsection of build section of its manifest in "
+ location.string() + ", ignoring");
} else {
masonFileObject(entry, destination);
}
}
@ -284,20 +318,9 @@ void Component::masonFilesArray(const nlohmann::json& files, const std::filesyst
case nlohmann::json::value_t::string:
copyFile(location/entry, destination/entry);
break;
case nlohmann::json::value_t::object: {
std::optional<std::string> src = getFileSource(entry);
if (!src.has_value()) {
warn("Couldn't understand file source processing file array in " + location.string() + ", ignoring");
case nlohmann::json::value_t::object:
masonFileObject(entry, destination);
break;
}
std::optional<std::string> dst = getFileTarget(entry);
if (!src.has_value()) {
warn("Couldn't understand file destination processing file array in " + location.string() + ", ignoring");
break;
}
copyFile(location/src.value(), destination/src.value());
} break;
default:
warn(std::string("Unexpected ") + entry.type_name()
+ " in files subsection of build section of manifest in "
@ -306,7 +329,65 @@ void Component::masonFilesArray(const nlohmann::json& files, const std::filesyst
}
}
bool Component::allowedForTarget(const nlohmann::json& object, const std::string& target) const {
bool Component::masonFileObject(const nlohmann::json& object, const std::filesystem::path& destination) {
std::optional<std::string> src = getFileSource(object);
if (!src.has_value()) {
warn("Couldn't understand file source processing file array in " + location.string() + ", ignoring");
return false;
}
std::optional<std::string> dst = getFileTarget(object);
if (!src.has_value()) {
warn("Couldn't understand file destination processing file array in " + location.string() + ", ignoring");
return false;
}
copyFile(location/src.value(), destination/dst.value());
return true;
}
std::string Component::validateMasonTarget(std::string target) const {
const nlohmann::json& mnfst = manifest.value();
std::set<std::string> allowedTarges;
nlohmann::json::const_iterator itr = mnfst.find("targets");
if (itr != mnfst.end()) {
const nlohmann::json& targets = *itr;
if (targets.is_array()) {
for (const nlohmann::json& entry : targets) {
if (entry.is_string())
allowedTarges.emplace(entry);
}
} else {
warn("Mason project at " + location.string() + " has unexpected type \"targets\" section in its manifest, ignoring");
}
} else {
minor("Mason project at " + location.string() + " has no \"targets\" section, trying to figure out utilized targets from \"build\" section");
const nlohmann::json& build = mnfst.at("build");
for (const nlohmann::json& entry : build) {
if (entry.is_object())
getMasonTargets(entry, allowedTarges);
}
}
if (allowedTarges.count(target) > 0)
return target;
minor("Mason project at " + location.string() + " doesn't seem to support target \"" + target + "\"");
std::optional<std::string> defaultTarget = tryStringValue(mnfst, "defaultTarget");
if (defaultTarget.has_value()) {
target = defaultTarget.value();
minor("Mason project at " + location.string() + " will use project default target \"" + target + "\" instead of specified");
} else {
target = "default";
warn("Mason project at " + location.string() + " will use hardcoded default target \""
+ target + "\" because field \"defaultTarget\" is either abscent or invalid");
}
return target;
}
//this method could utilize Component::getMasonTargets but it doesn't because this way has less overhead
bool Component::allowedForMasonTarget(const nlohmann::json& object, const std::string& target) const {
nlohmann::json::const_iterator itr = object.find("target");
if (itr != object.end()) {
const nlohmann::json& tg = *itr;
@ -340,6 +421,35 @@ bool Component::allowedForTarget(const nlohmann::json& object, const std::string
return true;
}
void Component::getMasonTargets(const nlohmann::json& object, std::set<std::string>& out) const {
nlohmann::json::const_iterator itr = object.find("target");
if (itr != object.end()) {
const nlohmann::json& tg = *itr;
if (tg.is_string())
out.emplace(tg);
else
warn("\"target\" in build section has unexpected type, ignoring");
}
itr = object.find("targets");
if (itr != object.end()) {
const nlohmann::json& targets = *itr;
if (targets.is_array()) {
for (const nlohmann::json& entry : targets) {
if (entry.is_string())
out.emplace(entry);
else
warn("one of the targets in \"targets\" in build section has unexpected type, ignoring it");
}
} else {
warn("\"targets\" in build section has unexpected type, ignoring");
}
}
//TODO may be notTarget and notTargets?
}
std::optional<std::string> Component::getFileSource(const nlohmann::json& object) const {
for (const std::string_view& key : sourceVariants) {
std::optional<std::string> value = tryStringValue(object, key.data());

View File

@ -9,6 +9,7 @@
#include <functional>
#include <array>
#include <string_view>
#include <set>
#include <nlohmann/json.hpp>
#include "loggable.h"
@ -39,33 +40,38 @@ public:
Component(
const std::filesystem::path& path,
Collection* collection,
const std::shared_ptr<Logger>& logger
const std::shared_ptr<Logger>& logger,
const std::string& name = ""
);
Type getType() const;
State getState() const;
std::filesystem::path getLocation() const;
std::string getLibrariesPath() const;
std::string getName() const;
bool successfullyRead() const;
bool successfullyBuilt() const;
void read();
void build(const std::filesystem::path& destination, const std::string& target);
void build(const std::filesystem::path& destination, const std::string& target, bool useName = true);
private:
void tryReadingBuildScenarios();
bool tryReadingBuildScenarios();
bool readAsMason();
bool errorScenario(const std::string& message);
void buildAsFile(const std::filesystem::path& destination);
void buildAsDirectory(const std::filesystem::path& destination);
void buildAsMason(const std::filesystem::path& destination, const std::string& target);
void buildAsMason(const std::filesystem::path& destination, std::string target);
bool readMasonDependencies(const nlohmann::json& deps, const std::string& manifestPath);
void copyFile(const std::filesystem::path& from, const std::filesystem::path& to) const;
std::string validateMasonTarget(std::string target) const;
void masonFilesArray(const nlohmann::json& files, const std::filesystem::path& destination);
bool allowedForTarget(const nlohmann::json& object, const std::string& target) const;
bool masonFileObject(const nlohmann::json& object, const std::filesystem::path& destination);
bool allowedForMasonTarget(const nlohmann::json& object, const std::string& target) const;
void getMasonTargets(const nlohmann::json& object, std::set<std::string>& out) const;
std::optional<std::string> getFileSource(const nlohmann::json& object) const;
std::optional<std::string> getFileTarget(const nlohmann::json& object) const;
@ -78,6 +84,7 @@ private:
Collection* collection;
std::filesystem::path location;
std::optional<nlohmann::json> manifest;
std::string name;
};
class Component::WrongState : public std::runtime_error {

View File

@ -12,5 +12,12 @@
"https://git.macaw.me/blue/mason/archive/main.tar.gz",
"https://git.macaw.me/blue/mason/raw/branch/main/src2/atomicmutex.h"
],
"build": [
"mason.json",
{
"src" : "mason.json",
"dst" : "another/mason.json"
}
],
"libraries": "lib"
}