#include "component.h" #include "collection.h" constexpr std::string_view masonJSON("mason.json"); constexpr std::string_view dependencies("dependencies"); constexpr std::array stringStates { "initial", "reading", "ready", "building", "error", "done" }; Component::Component( const std::filesystem::path& path, const std::weak_ptr& collection, const std::shared_ptr& logger ): Loggable(logger), state(initial), type(unknown), collection(collection), location(path), scenario(std::nullopt) {} void Component::read() { if (state != initial) throw WrongState(state, "read"); state = reading; std::filesystem::file_status status = std::filesystem::status(location); switch (status.type()) { case std::filesystem::file_type::directory: type = directory; state = ready; tryReadingBuildScenarios(); break; case std::filesystem::file_type::regular: type = file; state = ready; break; default: warn(location.string() + " doesn't appear to be a file nor a directory"); state = error; break; } } void Component::tryReadingBuildScenarios() { if (readAsMason()) return; } bool Component::readAsMason() { std::filesystem::path masonScenarion = location/masonJSON; try { std::ifstream file(masonScenarion); if (file.is_open()) scenario = nlohmann::json::parse(file); else minor("Couldn't open " + masonScenarion.string()); } catch (const nlohmann::json::exception& e) { major("Couldn't parse " + masonScenarion.string()); } if (scenario.has_value()) { const nlohmann::json& sc = scenario.value(); if (!sc.is_object()) return errorScenario(masonScenarion.string() + " is unexpected root type"); nlohmann::json::const_iterator itr = sc.find(dependencies); if (itr == sc.end()) { info(masonScenarion.string() + " doesn't have dependencies"); } else { const nlohmann::json& deps = *itr; if (!deps.is_array()) return errorScenario(masonScenarion.string() + " dependencies are not organized as an array"); for (const nlohmann::json& dep : deps) { std::shared_ptr col = collection.lock(); switch (dep.type()) { case nlohmann::json::value_t::string: col->addSource(dep); break; case nlohmann::json::value_t::object: { nlohmann::json::const_iterator ditr = dep.find("path"); if (ditr == dep.end()) return errorScenario(masonScenarion.string() + " object of unexpected format in dependecies"); nlohmann::json path = *ditr; if (!path.is_string()) return errorScenario(masonScenarion.string() + " object of unexpected format in dependecies"); col->addSource(path); } break; default: return errorScenario(masonScenarion.string() + " has unexpected entries in dependecies"); } } } type = mason; info(location.string() + " seems to be a mason project"); return true; } return false; } bool Component::errorScenario(const std::string& message) { major(message); scenario = std::nullopt; return false; return false; } void Component::build(const std::filesystem::path& destination, const std::string& target) { if (state != ready) throw WrongState(state, "build"); state = building; info("Building " + location.string() + " to " + destination.string()); state = done; } Component::State Component::getState() const { return state; } Component::Type Component::getType() const { return type; } Component::WrongState::WrongState(State state, const std::string& action): std::runtime_error("An attempt to perform action \"" + action + "\" on a wrong state \"" + stringStates[state].data() + '\"') {}