diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/GlobalLib.cpp | 2 | ||||
-rw-r--r-- | src/Package.cpp | 168 | ||||
-rw-r--r-- | src/main.cpp | 12 |
3 files changed, 129 insertions, 53 deletions
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<bool> GlobalLib::downloadDependency(const Dependency &dependency) { - Result<string> packageUrlResult = Package::getPackageUrl(dependency.name.c_str(), dependency.version.c_str()); + Result<string> packageUrlResult = Package::getPackageUrl(dependency.name.c_str(), dependency.version.c_str(), SYSTEM_PLATFORM_NAME); if(!packageUrlResult) return Result<bool>::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<string> &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<PackageMetadata> getPackageMetadata(Value::ConstObject jsonObj) + { + const auto &description = jsonObj["description"]; + if(!description.IsString()) return Result<PackageMetadata>::Err("Expected description to be a string"); + const auto &version = jsonObj["version"]; + if(!version.IsString()) return Result<PackageMetadata>::Err("Expected version to be a string"); + const auto &platforms = jsonObj["platforms"]; + if(!platforms.IsArray() || platforms.GetArray().Empty()) return Result<PackageMetadata>::Err("Expected platforms to be an array of strings"); + const auto &urls = jsonObj["urls"]; + if(!urls.IsArray() || urls.GetArray().Empty()) return Result<PackageMetadata>::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<PackageMetadata>::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<PackageMetadata>::Err("Expected urls to only contain strings"); + packageMetadata.urls.push_back(urlElement.GetString()); + } + + return Result<PackageMetadata>::Ok(packageMetadata); + } + + Result<string> 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<string>::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<string>::Err(errMsg); + } + + return Result<string>::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<Document*>::Ok(packageList); } - Result<string> Package::getPackageUrl(const char *packageName, const char *packageVersion) + Result<string> Package::getPackageUrl(const char *packageName, const char *packageVersion, const char *platform) { 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()) + 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<string>::Err(errMsg); + Result<PackageMetadata> packageMetadataResult = getPackageMetadata(packageMetaDataJson.GetObject()); + if(!packageMetadataResult) return Result<string>::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<string>::Err(errMsg); + } + + Result<PackageMetadata> packageMetadataResult = getPackageMetadata(packageMetaDataJson.GetObject()); + if(packageMetadataResult) + { + Result<string> 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<string>::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<string>::Err(errMsg); } - - return Result<std::string>::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 |