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( 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) 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); readingSources.erase(itr);
taskManager->queue( 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) 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( Component::Component(
const std::filesystem::path& path, const std::filesystem::path& path,
Collection* collection, Collection* collection,
const std::shared_ptr<Logger>& logger const std::shared_ptr<Logger>& logger,
const std::string& name
): ):
Loggable(logger), Loggable(logger),
state(initial), state(initial),
type(unknown), type(unknown),
collection(collection), collection(collection),
location(path), location(path),
manifest(std::nullopt) manifest(std::nullopt),
name(name)
{} {}
void Component::read() { void Component::read() {
@ -62,11 +64,16 @@ void Component::read() {
case std::filesystem::file_type::directory: case std::filesystem::file_type::directory:
type = directory; type = directory;
state = ready; state = ready;
tryReadingBuildScenarios(); if (!tryReadingBuildScenarios() && name.empty())
name = location.filename();
break; break;
case std::filesystem::file_type::regular: case std::filesystem::file_type::regular:
type = file; type = file;
state = ready; state = ready;
if (name.empty())
name = location.filename();
break; break;
default: default:
warn(location.string() + " doesn't appear to be a file nor a directory"); 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()) if (readAsMason())
return; return true;
return false;
} }
bool Component::readAsMason() { bool Component::readAsMason() {
@ -106,6 +115,17 @@ bool Component::readAsMason() {
return false; 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; type = mason;
info(location.string() + " seems to be a valid mason project"); info(location.string() + " seems to be a valid mason project");
return true; return true;
@ -151,7 +171,7 @@ bool Component::errorScenario(const std::string& message) {
return false; 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) if (state != ready)
throw WrongState(state, "build"); throw WrongState(state, "build");
@ -160,13 +180,23 @@ void Component::build(const std::filesystem::path& destination, const std::strin
switch (type) { switch (type) {
case file: case file:
buildAsFile(destination); if (useName)
buildAsFile(destination/name);
else
buildAsFile(destination);
break; break;
case directory: case directory:
buildAsDirectory(destination); if (useName)
buildAsDirectory(destination/name);
else
buildAsDirectory(destination);
break; break;
case mason: case mason:
buildAsMason(destination, target); if (useName)
buildAsMason(destination/name, target);
else
buildAsMason(destination, target);
break; break;
default: default:
break; break;
@ -174,13 +204,13 @@ void Component::build(const std::filesystem::path& destination, const std::strin
} }
void Component::buildAsFile(const std::filesystem::path& destination) { void Component::buildAsFile(const std::filesystem::path& destination) {
copyFile(location, destination/location.filename()); copyFile(location, destination);
state = done; state = done;
} }
void Component::buildAsDirectory(const std::filesystem::path& destination) { 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::recursive |
std::filesystem::copy_options::overwrite_existing std::filesystem::copy_options::overwrite_existing
); );
@ -219,7 +249,7 @@ bool Component::successfullyBuilt() const {
return state == done; 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(); const nlohmann::json& mnfst = manifest.value();
nlohmann::json::const_iterator itr = mnfst.find("build"); nlohmann::json::const_iterator itr = mnfst.find("build");
if (itr == mnfst.end()) { if (itr == mnfst.end()) {
@ -230,11 +260,13 @@ void Component::buildAsMason(const std::filesystem::path& destination, const std
const nlohmann::json& build = *itr; const nlohmann::json& build = *itr;
if (!build.is_array()) { 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; state = done;
return; return;
} }
target = validateMasonTarget(target);
for (const nlohmann::json& entry : build) { for (const nlohmann::json& entry : build) {
switch (entry.type()) { switch (entry.type()) {
case nlohmann::json::value_t::string: case nlohmann::json::value_t::string:
@ -244,7 +276,7 @@ void Component::buildAsMason(const std::filesystem::path& destination, const std
masonFilesArray(entry, destination); masonFilesArray(entry, destination);
break; break;
case nlohmann::json::value_t::object: case nlohmann::json::value_t::object:
if (allowedForTarget(entry, target)) { if (allowedForMasonTarget(entry, target)) {
nlohmann::json::const_iterator fitr = entry.find("files"); nlohmann::json::const_iterator fitr = entry.find("files");
if (fitr != entry.end()) { if (fitr != entry.end()) {
const nlohmann::json& files = *fitr; 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() warn(std::string("Unexpected ") + entry.type_name()
+ " of files subsection of build section of its manifest in " + " of files subsection of build section of its manifest in "
+ location.string() + ", ignoring"); + 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: case nlohmann::json::value_t::string:
copyFile(location/entry, destination/entry); copyFile(location/entry, destination/entry);
break; break;
case nlohmann::json::value_t::object: { case nlohmann::json::value_t::object:
std::optional<std::string> src = getFileSource(entry); masonFileObject(entry, destination);
if (!src.has_value()) { break;
warn("Couldn't understand file source processing file array in " + location.string() + ", ignoring");
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: default:
warn(std::string("Unexpected ") + entry.type_name() warn(std::string("Unexpected ") + entry.type_name()
+ " in files subsection of build section of manifest in " + " 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"); nlohmann::json::const_iterator itr = object.find("target");
if (itr != object.end()) { if (itr != object.end()) {
const nlohmann::json& tg = *itr; const nlohmann::json& tg = *itr;
@ -340,6 +421,35 @@ bool Component::allowedForTarget(const nlohmann::json& object, const std::string
return true; 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 { std::optional<std::string> Component::getFileSource(const nlohmann::json& object) const {
for (const std::string_view& key : sourceVariants) { for (const std::string_view& key : sourceVariants) {
std::optional<std::string> value = tryStringValue(object, key.data()); std::optional<std::string> value = tryStringValue(object, key.data());

View File

@ -9,6 +9,7 @@
#include <functional> #include <functional>
#include <array> #include <array>
#include <string_view> #include <string_view>
#include <set>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "loggable.h" #include "loggable.h"
@ -39,33 +40,38 @@ public:
Component( Component(
const std::filesystem::path& path, const std::filesystem::path& path,
Collection* collection, Collection* collection,
const std::shared_ptr<Logger>& logger const std::shared_ptr<Logger>& logger,
const std::string& name = ""
); );
Type getType() const; Type getType() const;
State getState() const; State getState() const;
std::filesystem::path getLocation() const; std::filesystem::path getLocation() const;
std::string getLibrariesPath() const; std::string getLibrariesPath() const;
std::string getName() const;
bool successfullyRead() const; bool successfullyRead() const;
bool successfullyBuilt() const; bool successfullyBuilt() const;
void read(); 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: private:
void tryReadingBuildScenarios(); bool tryReadingBuildScenarios();
bool readAsMason(); bool readAsMason();
bool errorScenario(const std::string& message); bool errorScenario(const std::string& message);
void buildAsFile(const std::filesystem::path& destination); void buildAsFile(const std::filesystem::path& destination);
void buildAsDirectory(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); bool readMasonDependencies(const nlohmann::json& deps, const std::string& manifestPath);
void copyFile(const std::filesystem::path& from, const std::filesystem::path& to) const; 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); 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> getFileSource(const nlohmann::json& object) const;
std::optional<std::string> getFileTarget(const nlohmann::json& object) const; std::optional<std::string> getFileTarget(const nlohmann::json& object) const;
@ -78,6 +84,7 @@ private:
Collection* collection; Collection* collection;
std::filesystem::path location; std::filesystem::path location;
std::optional<nlohmann::json> manifest; std::optional<nlohmann::json> manifest;
std::string name;
}; };
class Component::WrongState : public std::runtime_error { 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/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"
], ],
"build": [
"mason.json",
{
"src" : "mason.json",
"dst" : "another/mason.json"
}
],
"libraries": "lib" "libraries": "lib"
} }