some progress over building
This commit is contained in:
parent
0fa8ba6918
commit
4843fcc77f
@ -12,12 +12,11 @@ Collection::Collection(
|
||||
const std::shared_ptr<TaskManager>& taskManager
|
||||
):
|
||||
Loggable(logger),
|
||||
std::enable_shared_from_this<Collection>(),
|
||||
mutex(),
|
||||
destination(destination),
|
||||
target(target),
|
||||
taskManager(taskManager),
|
||||
root(std::make_unique<Component>(location, shared_from_this(), logger)),
|
||||
root(std::make_unique<Component>(location, this, logger)),
|
||||
librariesPath(),
|
||||
knownSources(),
|
||||
successSources(),
|
||||
@ -35,7 +34,7 @@ Collection::Collection(
|
||||
}
|
||||
|
||||
root->read();
|
||||
if (root->successfullyRead())
|
||||
if (!root->successfullyRead())
|
||||
throw std::runtime_error("Error reading project in " + location.string());
|
||||
|
||||
if (root->getType() != Component::mason)
|
||||
@ -73,6 +72,7 @@ void Collection::addSource(const std::string& source) {
|
||||
case Component::building:
|
||||
case Component::done:
|
||||
processSource(source);
|
||||
break;
|
||||
case Component::error:
|
||||
throw std::runtime_error("Project in " + root->getLocation().string() + " doesn't seem to be a valid mason project");
|
||||
}
|
||||
@ -109,7 +109,7 @@ void Collection::sourceRead(const std::string& source, TaskManager::Error err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (itr->second->successfullyRead()) {
|
||||
if (!itr->second->successfullyRead()) {
|
||||
error("Source " + source + " had an error during read process, canceling build of this component");
|
||||
readingSources.erase(itr);
|
||||
return;
|
||||
@ -127,19 +127,34 @@ void Collection::sourceRead(const std::string& source, TaskManager::Error err) {
|
||||
|
||||
void Collection::sourceBuilt(const std::string& source, TaskManager::Error err) {
|
||||
std::lock_guard lock(mutex);
|
||||
debug("Source " + source + " has been built");
|
||||
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());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
error("Source " + source + " had an error during build process");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Source " + source + " has been built");
|
||||
successSources.emplace(source);
|
||||
}
|
||||
|
||||
void Collection::rootBuilt(TaskManager::Error err) {
|
||||
std::string loc = root->getLocation();
|
||||
if (err.has_value()) {
|
||||
error("Coundn't build project at" + loc + ": " + err.value()->what());
|
||||
return;
|
||||
}
|
||||
|
||||
if (root->successfullyBuilt())
|
||||
info("Project at " + loc + " was successfully built");
|
||||
else
|
||||
error("Project at " + loc + " had some errors during build process");
|
||||
}
|
||||
|
||||
bool Collection::isRemote(const std::string& source) {
|
||||
@ -166,7 +181,7 @@ void Collection::queueRead(const std::string& source, const std::filesystem::pat
|
||||
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, shared_from_this(), logger)
|
||||
std::make_unique<Component>(location, this, logger)
|
||||
)
|
||||
);
|
||||
|
||||
@ -201,6 +216,11 @@ unsigned int Collection::sourcesError() const {
|
||||
return _sourcesError();
|
||||
}
|
||||
|
||||
bool Collection::success() const {
|
||||
std::lock_guard lock(mutex);
|
||||
return _sourcesTotal() == _sourcesSuccess() && root->successfullyBuilt();
|
||||
}
|
||||
|
||||
bool Collection::_hasSource(const std::string& source) const {
|
||||
return knownSources.count(source) > 0;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "download.h"
|
||||
#include "taskmanager.h"
|
||||
|
||||
class Collection : protected Loggable, public std::enable_shared_from_this<Collection> {
|
||||
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>>;
|
||||
@ -30,6 +30,8 @@ public:
|
||||
const std::shared_ptr<TaskManager>& taskManager
|
||||
);
|
||||
|
||||
bool success() const;
|
||||
|
||||
unsigned int sourcesTotal() const;
|
||||
unsigned int sourcesPending() const;
|
||||
unsigned int sourcesError() const;
|
||||
|
@ -3,7 +3,25 @@
|
||||
#include "collection.h"
|
||||
|
||||
constexpr std::string_view masonJSON("mason.json");
|
||||
|
||||
constexpr std::string_view dependencies("dependencies");
|
||||
|
||||
constexpr std::array<std::string_view, 5> sourceVariants({
|
||||
"source",
|
||||
"src",
|
||||
"from",
|
||||
"in",
|
||||
"file"
|
||||
});
|
||||
|
||||
constexpr std::array<std::string_view, 5> targetVariants({
|
||||
"target",
|
||||
"dst",
|
||||
"to",
|
||||
"out",
|
||||
"destination"
|
||||
});
|
||||
|
||||
constexpr std::array<std::string_view, Component::done + 1> stringStates {
|
||||
"initial",
|
||||
"reading",
|
||||
@ -22,7 +40,7 @@ constexpr std::array<std::string_view, Component::unknown + 1> stringTypes {
|
||||
|
||||
Component::Component(
|
||||
const std::filesystem::path& path,
|
||||
const std::weak_ptr<Collection>& collection,
|
||||
Collection* collection,
|
||||
const std::shared_ptr<Logger>& logger
|
||||
):
|
||||
Loggable(logger),
|
||||
@ -101,10 +119,9 @@ bool Component::readMasonDependencies(const nlohmann::json& deps, const std::str
|
||||
return errorScenario(manifestPath + " dependencies are not organized as an array");
|
||||
|
||||
for (const nlohmann::json& dep : deps) {
|
||||
std::shared_ptr<Collection> col = collection.lock();
|
||||
switch (dep.type()) {
|
||||
case nlohmann::json::value_t::string:
|
||||
col->addSource(dep);
|
||||
collection->addSource(dep);
|
||||
break;
|
||||
case nlohmann::json::value_t::object: {
|
||||
nlohmann::json::const_iterator ditr = dep.find("path");
|
||||
@ -115,7 +132,7 @@ bool Component::readMasonDependencies(const nlohmann::json& deps, const std::str
|
||||
if (!path.is_string())
|
||||
return errorScenario(manifestPath + " object of unexpected format in dependecies");
|
||||
|
||||
col->addSource(path);
|
||||
collection->addSource(path);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -146,7 +163,7 @@ void Component::build(const std::filesystem::path& destination, const std::strin
|
||||
buildAsFile(destination);
|
||||
break;
|
||||
case directory:
|
||||
buildAsDiractory(destination);
|
||||
buildAsDirectory(destination);
|
||||
break;
|
||||
case mason:
|
||||
buildAsMason(destination, target);
|
||||
@ -154,19 +171,21 @@ void Component::build(const std::filesystem::path& destination, const std::strin
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Component::buildAsFile(const std::filesystem::path& destination) {
|
||||
copyFile(location, destination/location.filename());
|
||||
|
||||
state = done;
|
||||
}
|
||||
|
||||
void Component::buildAsFile(const std::filesystem::path& destination) {
|
||||
std::filesystem::copy(location, destination/location.filename());
|
||||
}
|
||||
|
||||
void Component::buildAsDiractory(const std::filesystem::path& destination) {
|
||||
void Component::buildAsDirectory(const std::filesystem::path& destination) {
|
||||
std::filesystem::copy(location, destination/location.filename(),
|
||||
std::filesystem::copy_options::recursive |
|
||||
std::filesystem::copy_options::overwrite_existing
|
||||
);
|
||||
|
||||
state = done;
|
||||
}
|
||||
|
||||
std::string Component::getLibrariesPath() const {
|
||||
@ -196,8 +215,160 @@ bool Component::successfullyRead() const {
|
||||
return state > reading && state != error;
|
||||
}
|
||||
|
||||
bool Component::successfullyBuilt() const {
|
||||
return state == done;
|
||||
}
|
||||
|
||||
void Component::buildAsMason(const std::filesystem::path& destination, const std::string& target) {
|
||||
warn("mason build is not implemented yet");
|
||||
const nlohmann::json& mnfst = manifest.value();
|
||||
nlohmann::json::const_iterator itr = mnfst.find("build");
|
||||
if (itr == mnfst.end()) {
|
||||
warn("Mason project at " + location.string() + " has no \"build\" section in its manifest");
|
||||
state = done;
|
||||
return;
|
||||
}
|
||||
|
||||
const nlohmann::json& build = *itr;
|
||||
if (!build.is_array()) {
|
||||
warn("Mason project at " + location.string() + " has unexpected \"build\" section in its manifest");
|
||||
state = done;
|
||||
return;
|
||||
}
|
||||
|
||||
for (const nlohmann::json& entry : build) {
|
||||
switch (entry.type()) {
|
||||
case nlohmann::json::value_t::string:
|
||||
copyFile(location/entry, destination/entry);
|
||||
break;
|
||||
case nlohmann::json::value_t::array:
|
||||
masonFilesArray(entry, destination);
|
||||
break;
|
||||
case nlohmann::json::value_t::object:
|
||||
if (allowedForTarget(entry, target)) {
|
||||
nlohmann::json::const_iterator fitr = entry.find("files");
|
||||
if (fitr != entry.end()) {
|
||||
const nlohmann::json& files = *fitr;
|
||||
if (files.is_array())
|
||||
masonFilesArray(files, destination);
|
||||
else
|
||||
warn(std::string("Unexpected ") + entry.type_name()
|
||||
+ " of files subsection of build section of its manifest in "
|
||||
+ location.string() + ", ignoring");
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warn(std::string("Unexpected ") + entry.type_name() + " in build section of manifest in " + location.string() + ", ignoring");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state = done;
|
||||
}
|
||||
|
||||
void Component::copyFile(const std::filesystem::path& from, const std::filesystem::path& to) const {
|
||||
std::filesystem::create_directories(to.parent_path());
|
||||
|
||||
if (std::filesystem::exists(to))
|
||||
minor("File " + to.string() + " already exists, overwriting from " + from.string());
|
||||
else
|
||||
debug("Copying " + from.string() + " to " + to.string());
|
||||
|
||||
std::filesystem::copy(from, to, std::filesystem::copy_options::overwrite_existing);
|
||||
}
|
||||
|
||||
void Component::masonFilesArray(const nlohmann::json& files, const std::filesystem::path& destination) {
|
||||
for (const nlohmann::json& entry : files) {
|
||||
switch (entry.type()) {
|
||||
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");
|
||||
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 "
|
||||
+ location.string() + ", ignoring");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Component::allowedForTarget(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;
|
||||
if (tg.is_string())
|
||||
return tg == target;
|
||||
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()) {
|
||||
if (entry == target)
|
||||
return true;
|
||||
} else {
|
||||
warn("one of the targets in \"targets\" in build section has unexpected type, ignoring it");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
warn("\"targets\" in build section has unexpected type, ignoring");
|
||||
}
|
||||
}
|
||||
|
||||
//TODO may be notTarget and notTargets?
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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());
|
||||
if (value.has_value())
|
||||
return value;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Component::getFileTarget(const nlohmann::json& object) const {
|
||||
for (const std::string_view& key : targetVariants) {
|
||||
std::optional<std::string> value = tryStringValue(object, key.data());
|
||||
if (value.has_value())
|
||||
return value;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> Component::tryStringValue(const nlohmann::json& object, const std::string& key) {
|
||||
nlohmann::json::const_iterator itr = object.find(key);
|
||||
if (itr != object.end()) {
|
||||
const nlohmann::json& value = *itr;
|
||||
if (value.is_string())
|
||||
return value;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Component::State Component::getState() const {
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
|
||||
Component(
|
||||
const std::filesystem::path& path,
|
||||
const std::weak_ptr<Collection>& collection,
|
||||
Collection* collection,
|
||||
const std::shared_ptr<Logger>& logger
|
||||
);
|
||||
|
||||
@ -47,6 +47,7 @@ public:
|
||||
std::filesystem::path getLocation() const;
|
||||
std::string getLibrariesPath() const;
|
||||
bool successfullyRead() const;
|
||||
bool successfullyBuilt() const;
|
||||
|
||||
void read();
|
||||
void build(const std::filesystem::path& destination, const std::string& target);
|
||||
@ -57,15 +58,24 @@ private:
|
||||
bool errorScenario(const std::string& message);
|
||||
|
||||
void buildAsFile(const std::filesystem::path& destination);
|
||||
void buildAsDiractory(const std::filesystem::path& destination);
|
||||
void buildAsDirectory(const std::filesystem::path& destination);
|
||||
void buildAsMason(const std::filesystem::path& destination, const 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;
|
||||
|
||||
void masonFilesArray(const nlohmann::json& files, const std::filesystem::path& destination);
|
||||
bool allowedForTarget(const nlohmann::json& object, const std::string& target) const;
|
||||
|
||||
std::optional<std::string> getFileSource(const nlohmann::json& object) const;
|
||||
std::optional<std::string> getFileTarget(const nlohmann::json& object) const;
|
||||
|
||||
static std::optional<std::string> tryStringValue (const nlohmann::json& object, const std::string& key);
|
||||
|
||||
private:
|
||||
State state;
|
||||
Type type;
|
||||
std::weak_ptr<Collection> collection;
|
||||
Collection* collection;
|
||||
std::filesystem::path location;
|
||||
std::optional<nlohmann::json> manifest;
|
||||
};
|
||||
|
@ -71,7 +71,6 @@ void Download::proceed() {
|
||||
const FileInfo& fl = file.value();
|
||||
std::optional<std::filesystem::path> path = downloadAsFile(fl);
|
||||
if (path.has_value()) {
|
||||
info("Successfully downloaded " + url);
|
||||
if (fl.archive) {
|
||||
info(url + " appears to be an archive, extracting");
|
||||
bool success = extract(path.value(), destination/fl.name);
|
||||
|
@ -32,17 +32,15 @@ int main(int argc, char *argv[]) {
|
||||
taskManager->wait();
|
||||
taskManager->stop();
|
||||
|
||||
unsigned int success = collection->sourcesSuccess();
|
||||
unsigned int total = collection->sourcesTotal();
|
||||
if (total == success) {
|
||||
if (collection->success()) {
|
||||
logger->log(Logger::Severity::info, "Successfully built " + firstArg);
|
||||
return 0;
|
||||
} else {
|
||||
logger->log(Logger::Severity::error, "Failed to build " + firstArg);
|
||||
logger->log(Logger::Severity::info, "Success: " + std::to_string(success));
|
||||
logger->log(Logger::Severity::info, "Success: " + std::to_string(collection->sourcesSuccess()));
|
||||
logger->log(Logger::Severity::info, "Failed: " + std::to_string(collection->sourcesError()));
|
||||
logger->log(Logger::Severity::info, "Unfinished: " + std::to_string(collection->sourcesPending()));
|
||||
logger->log(Logger::Severity::info, "Total: " + std::to_string(total));
|
||||
logger->log(Logger::Severity::info, "Total: " + std::to_string(collection->sourcesTotal()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
"dependencies" : [
|
||||
"somePath",
|
||||
"https://git.macaw.me/blue/mason.git",
|
||||
"https://git.macaw.me/blue/mimicry.git",
|
||||
{
|
||||
"name" : "aProject",
|
||||
"path" : "https://nowhere/to/get.from"
|
||||
|
Loading…
Reference in New Issue
Block a user