From a548abb5a6a83c9318e9db3cf71170a7610e2758 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 4 Jan 2018 01:01:35 +0100 Subject: Use packages list to find packages --- src/Package.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/Package.cpp (limited to 'src/Package.cpp') diff --git a/src/Package.cpp b/src/Package.cpp new file mode 100644 index 0000000..c1c00be --- /dev/null +++ b/src/Package.cpp @@ -0,0 +1,114 @@ +#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())); + } +} -- cgit v1.2.3