#include "../include/Package.hpp" #include "../include/curl.hpp" #include "../external/rapidjson/error/en.h" using namespace std; using namespace rapidjson; static Document *packageList = nullptr; namespace sibs { // TODO: Always downloading is fine right now because the package list is small. This should later be modified to use local cache. // The package file should be stored locally (at ~/.sibs/packages.json) and the version file should also be stored. // First we check if the version is incorrect and if it, we download the new packages.json file. // We should only check if the package list is up to date once every 10 minute or so (make it configurable in a config file?) // to improve build performance and reduce server load. // Or maybe we dont have to do that at all.... Result Package::getPackageList(const char *url) { if(packageList) return Result::Ok(packageList); HttpResult httpResult = curl::get(url); if(!httpResult.success) return Result::Err(httpResult.str, httpResult.httpCode); Document *doc = new Document(); ParseResult parseResult = doc->Parse(httpResult.str.c_str()); if(!parseResult) { string errMsg = "Failed to parse package list json file: "; errMsg += GetParseError_En(parseResult.Code()); errMsg += " ("; errMsg += to_string(parseResult.Offset()); errMsg += ")"; return Result::Err(errMsg); } packageList = doc; return Result::Ok(packageList); } Result Package::getPackageUrl(const char *packageName, const char *packageVersion) { Result packageList = Package::getPackageList("https://raw.githubusercontent.com/DEC05EBA/sibs_packages/master/packages.json"); if(!packageList) return Result::Err(packageList); const Document &packageDoc = *packageList.unwrap(); const Value &packageMetaData = packageDoc[packageName]; if(!packageMetaData.IsObject()) { string errMsg = "No package with the name \""; errMsg += packageName; errMsg += "\" was found"; return Result::Err(errMsg); } const Value &packageVersions = packageMetaData["versions"]; if(!packageVersions.IsObject()) { string errMsg = "Package file is corrupt. "; errMsg += packageName; errMsg += ".versions is not a json object"; return Result::Err("errMsg"); } const Value &package = packageVersions[packageVersion]; if(!package.IsObject()) { string errMsg = "Package file is corrupt. "; errMsg += packageName; errMsg += ".versions."; errMsg += packageVersion; errMsg += " is not a json object"; return Result::Err(errMsg); } const Value &packageUrlsValue = package["urls"]; if(!packageUrlsValue.IsArray()) { string errMsg = "Package file is corrupt. "; errMsg += packageName; errMsg += ".versions."; errMsg += packageVersion; errMsg += ".urls is not a json array"; return Result::Err(errMsg); } auto packageUrls = packageUrlsValue.GetArray(); if(packageUrls.Empty()) { string errMsg = "Package file is corrupt. "; errMsg += packageName; errMsg += ".versions."; errMsg += packageVersion; errMsg += ".urls is an empty json array"; return Result::Err(errMsg); } const Value &packageUrlValue = packageUrls[0]; if(!packageUrlValue.IsString()) { string errMsg = "Package file is corrupt. "; errMsg += packageName; errMsg += ".versions."; errMsg += packageVersion; errMsg += ".urls[0] is not a string"; return Result::Err(errMsg); } return Result::Ok(string(packageUrlValue.GetString(), packageUrlValue.GetStringLength())); } }