aboutsummaryrefslogtreecommitdiff
path: root/src/Package.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Package.cpp')
-rw-r--r--src/Package.cpp114
1 files changed, 114 insertions, 0 deletions
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<Document*> Package::getPackageList(const char *url)
+ {
+ if(packageList)
+ return Result<Document*>::Ok(packageList);
+
+ HttpResult httpResult = curl::get(url);
+ if(!httpResult.success)
+ return Result<Document*>::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<Document*>::Err(errMsg);
+ }
+
+ packageList = doc;
+ return Result<Document*>::Ok(packageList);
+ }
+
+ Result<string> Package::getPackageUrl(const char *packageName, const char *packageVersion)
+ {
+ Result<Document*> packageList = Package::getPackageList("https://raw.githubusercontent.com/DEC05EBA/sibs_packages/master/packages.json");
+ if(!packageList)
+ return Result<string>::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<string>::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<string>::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<string>::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<string>::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<string>::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<string>::Err(errMsg);
+ }
+
+ return Result<std::string>::Ok(string(packageUrlValue.GetString(), packageUrlValue.GetStringLength()));
+ }
+}