From ea17671d7fe9ece8a33bdbc2f1d7bdf68bbccb69 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 6 Jan 2018 08:33:49 +0100 Subject: Change package list format --- include/Conf.hpp | 4 ++ include/Package.hpp | 11 +++- src/GlobalLib.cpp | 2 +- src/Package.cpp | 168 ++++++++++++++++++++++++++++++++++++---------------- src/main.cpp | 12 ++++ 5 files changed, 143 insertions(+), 54 deletions(-) diff --git a/include/Conf.hpp b/include/Conf.hpp index de63eae..c661ca4 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -133,11 +133,13 @@ namespace sibs #if OS_TYPE == OS_TYPE_WINDOWS #ifdef SIBS_ENV_32BIT #define SYSTEM_PLATFORM Platform::PLATFORM_WIN32 + #define SYSTEM_PLATFORM_NAME "win32" #define CONFIG_SYSTEM_PLATFORM 0 #define CONFIG_STATIC_DEBUG_PLATFORM 1 #define CONFIG_STATIC_RELEASE_PLATFORM 2 #else #define SYSTEM_PLATFORM Platform::PLATFORM_WIN64 + #define SYSTEM_PLATFORM_NAME "win64" #define CONFIG_SYSTEM_PLATFORM 3 #define CONFIG_STATIC_DEBUG_PLATFORM 4 #define CONFIG_STATIC_RELEASE_PLATFORM 5 @@ -147,11 +149,13 @@ namespace sibs #elif OS_TYPE == OS_TYPE_LINUX #ifdef SIBS_ENV_32BIT #define SYSTEM_PLATFORM Platform::PLATFORM_LINUX32 + #define SYSTEM_PLATFORM_NAME "linux32" #define CONFIG_SYSTEM_PLATFORM 6 #define CONFIG_STATIC_DEBUG_PLATFORM 7 #define CONFIG_STATIC_RELEASE_PLATFORM 8 #else #define SYSTEM_PLATFORM Platform::PLATFORM_LINUX64 + #define SYSTEM_PLATFORM_NAME "linux64" #define CONFIG_SYSTEM_PLATFORM 9 #define CONFIG_STATIC_DEBUG_PLATFORM 10 #define CONFIG_STATIC_RELEASE_PLATFORM 11 diff --git a/include/Package.hpp b/include/Package.hpp index 475e11b..131e87f 100644 --- a/include/Package.hpp +++ b/include/Package.hpp @@ -4,6 +4,7 @@ #include "../external/rapidjson/document.h" #include "Result.hpp" #include +#include namespace sibs { @@ -25,6 +26,14 @@ namespace sibs LIBRARY }; + struct PackageMetadata + { + std::string description; + std::string version; + std::vector platforms; + std::vector urls; + }; + class Package { public: @@ -39,7 +48,7 @@ namespace sibs * TODO: If we fail to fetch package from first url, try other other ones in the list (or if the first url is too slow / takes too long to respond). * TODO: Add version matching with wildcard etc. If we specify "1.2.*", then it should get the latest version that matches; etc... */ - static Result getPackageUrl(const char *packageName, const char *packageVersion); + static Result getPackageUrl(const char *packageName, const char *packageVersion, const char *platform); }; } diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp index 0256685..3842388 100644 --- a/src/GlobalLib.cpp +++ b/src/GlobalLib.cpp @@ -318,7 +318,7 @@ namespace sibs Result GlobalLib::downloadDependency(const Dependency &dependency) { - Result packageUrlResult = Package::getPackageUrl(dependency.name.c_str(), dependency.version.c_str()); + Result packageUrlResult = Package::getPackageUrl(dependency.name.c_str(), dependency.version.c_str(), SYSTEM_PLATFORM_NAME); if(!packageUrlResult) return Result::Err(packageUrlResult); diff --git a/src/Package.cpp b/src/Package.cpp index c1c00be..a2aaf52 100644 --- a/src/Package.cpp +++ b/src/Package.cpp @@ -9,6 +9,83 @@ static Document *packageList = nullptr; namespace sibs { + // TODO: Use containsPlatform in Conf.hpp instead? dont need a vector of string when we can use vector of enum + bool containsPlatform(const vector &supportedPlatforms, const char *platform) + { + for(const string &supportedPlatform : supportedPlatforms) + { + if(strcmp(supportedPlatform.c_str(), platform) == 0 || strcmp(supportedPlatform.c_str(), "any") == 0) + return true; + } + + return false; + } + + Result getPackageMetadata(Value::ConstObject jsonObj) + { + const auto &description = jsonObj["description"]; + if(!description.IsString()) return Result::Err("Expected description to be a string"); + const auto &version = jsonObj["version"]; + if(!version.IsString()) return Result::Err("Expected version to be a string"); + const auto &platforms = jsonObj["platforms"]; + if(!platforms.IsArray() || platforms.GetArray().Empty()) return Result::Err("Expected platforms to be an array of strings"); + const auto &urls = jsonObj["urls"]; + if(!urls.IsArray() || urls.GetArray().Empty()) return Result::Err("Expected urls to be an array of string"); + + PackageMetadata packageMetadata; + packageMetadata.description.assign(description.GetString(), description.GetStringLength()); + packageMetadata.version.assign(version.GetString(), version.GetStringLength()); + + const auto &platformsArray = platforms.GetArray(); + packageMetadata.platforms.reserve(platformsArray.Size()); + for(int i = 0; i < platformsArray.Size(); ++i) + { + const auto &platformElement = platformsArray[i]; + if(!platformElement.IsString()) + return Result::Err("Expected platforms to only contain strings"); + packageMetadata.platforms.push_back(platformElement.GetString()); + } + + const auto &urlsArray = urls.GetArray(); + packageMetadata.urls.reserve(urlsArray.Size()); + for(int i = 0; i < urlsArray.Size(); ++i) + { + const auto &urlElement = urlsArray[i]; + if(!urlElement.IsString()) + return Result::Err("Expected urls to only contain strings"); + packageMetadata.urls.push_back(urlElement.GetString()); + } + + return Result::Ok(packageMetadata); + } + + Result getPackageUrl(const PackageMetadata &packageMetadata, const char *packageName, const char *packageVersion, const char *platform) + { + if(strcmp(packageMetadata.version.c_str(), packageVersion) != 0) + { + string errMsg = "Package \""; + errMsg += packageName; + errMsg += "\" does not exist for version \""; + errMsg += packageVersion; + errMsg += "\""; + return Result::Err(errMsg); + } + + if(!containsPlatform(packageMetadata.platforms, platform)) + { + string errMsg = "Package \""; + errMsg += packageName; + errMsg += "\" with version \""; + errMsg += packageVersion; + errMsg += "\" does not support platform \""; + errMsg += platform; + errMsg += "\""; + return Result::Err(errMsg); + } + + return Result::Ok(packageMetadata.urls[0]); + } + // 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. @@ -40,75 +117,62 @@ namespace sibs return Result::Ok(packageList); } - Result Package::getPackageUrl(const char *packageName, const char *packageVersion) + Result Package::getPackageUrl(const char *packageName, const char *packageVersion, const char *platform) { 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()) + const Value &packageMetaDataJson = packageDoc[packageName]; + if(packageMetaDataJson.IsObject()) { - string errMsg = "Package file is corrupt. "; - errMsg += packageName; - errMsg += ".versions."; - errMsg += packageVersion; - errMsg += ".urls is not a json array"; - return Result::Err(errMsg); + Result packageMetadataResult = getPackageMetadata(packageMetaDataJson.GetObject()); + if(!packageMetadataResult) return Result::Err(packageMetadataResult); + return ::sibs::getPackageUrl(packageMetadataResult.unwrap(), packageName, packageVersion, platform); } - - auto packageUrls = packageUrlsValue.GetArray(); - if(packageUrls.Empty()) + else if(packageMetaDataJson.IsArray()) { - string errMsg = "Package file is corrupt. "; + int i = 0; + for(const auto &packageData : packageMetaDataJson.GetArray()) + { + if(!packageData.IsObject()) + { + string errMsg = "Package file is corrupt. "; + errMsg += packageName; + errMsg += "["; + errMsg += to_string(i); + errMsg += "] is not an object"; + return Result::Err(errMsg); + } + + Result packageMetadataResult = getPackageMetadata(packageMetaDataJson.GetObject()); + if(packageMetadataResult) + { + Result packageUrlResult = ::sibs::getPackageUrl(packageMetadataResult.unwrap(), packageName, packageVersion, platform); + if(packageUrlResult) + return packageUrlResult; + } + + ++i; + } + + string errMsg = "Package \""; errMsg += packageName; - errMsg += ".versions."; + errMsg += "\" with version \""; errMsg += packageVersion; - errMsg += ".urls is an empty json array"; + errMsg += "\" does not exist or does not exist for platform \""; + errMsg += platform; + errMsg += "\""; return Result::Err(errMsg); } - - const Value &packageUrlValue = packageUrls[0]; - if(!packageUrlValue.IsString()) + else { - string errMsg = "Package file is corrupt. "; + string errMsg = "No package with the name \""; errMsg += packageName; - errMsg += ".versions."; - errMsg += packageVersion; - errMsg += ".urls[0] is not a string"; + errMsg += "\" was found"; return Result::Err(errMsg); } - - return Result::Ok(string(packageUrlValue.GetString(), packageUrlValue.GetStringLength())); } } diff --git a/src/main.cpp b/src/main.cpp index d4de6e0..c626f11 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,6 +43,18 @@ using namespace std::chrono; // TODO: Set c++ standard to c++11 and c standard to c98 - for consistency across different compilers and compiler version. // It should be possible to override language version in project.conf +// TODO: If file extension is common c extension (.c, ...) then remove cast checking (for example using malloc without casting result to result type) + +// TODO: When building a sibs project, add a hardlink in ~/.sibs/lib to it. This allows us to have dependency to a project that we can modify +// without having to commit & push to remote + +// TODO: Check compiler flags generated by cmake and visual studio in debug and release mode and use the same ones when building sibs project. +// There are certain compiler flags we do not currently have, for example _ITERATOR_DEBUG_LEVEL in debug mode which enables runtime checks. +// You should be able to specify runtime checks as an option to `sibs build` and project specific config in .conf file. +// Also add stack protection option. If it's enabled, shouldn't sibs prefer to compile dependencies from source? +// and should this force static compilation so dependencies can also be built with protection and if dependencies dont exist +// as static library/source, then fail build? + #if OS_FAMILY == OS_FAMILY_POSIX #define ferr std::cerr #else -- cgit v1.2.3