Merge pull request #595 from kotisoff/main
Проверка версий зависимостей
This commit is contained in:
@@ -132,7 +132,44 @@ ContentPack ContentPack::read(const io::path& folder) {
|
||||
level = DependencyLevel::weak;
|
||||
break;
|
||||
}
|
||||
pack.dependencies.push_back({level, depName});
|
||||
|
||||
std::string depVer = "*";
|
||||
std::string depVerOperator = "=";
|
||||
|
||||
size_t versionPos = depName.rfind("@");
|
||||
if (versionPos != std::string::npos) {
|
||||
depVer = depName.substr(versionPos + 1);
|
||||
depName = depName.substr(0, versionPos);
|
||||
|
||||
if (depVer.size() >= 2) {
|
||||
std::string op = depVer.substr(0, 2);
|
||||
std::uint8_t op_size = 0;
|
||||
|
||||
// Two symbol operators
|
||||
if (op == ">=" || op == "=>" || op == "<=" || op == "=<") {
|
||||
op_size = 2;
|
||||
depVerOperator = op;
|
||||
}
|
||||
|
||||
// One symbol operators
|
||||
else {
|
||||
op = depVer.substr(0, 1);
|
||||
|
||||
if (op == ">" || op == "<") {
|
||||
op_size = 1;
|
||||
depVerOperator = op;
|
||||
}
|
||||
}
|
||||
|
||||
depVer = depVer.substr(op_size);
|
||||
} else {
|
||||
if (depVer == ">" || depVer == "<"){
|
||||
depVer = "*";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pack.dependencies.push_back({level, depName, depVer, depVerOperator});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,16 @@ public:
|
||||
io::path folder,
|
||||
const std::string& message
|
||||
);
|
||||
|
||||
|
||||
std::string getPackId() const;
|
||||
io::path getFolder() const;
|
||||
};
|
||||
|
||||
enum class DependencyVersionOperator {
|
||||
equal, more, less,
|
||||
more_or_equal, less_or_equal
|
||||
};
|
||||
|
||||
enum class DependencyLevel {
|
||||
required, // dependency must be installed
|
||||
optional, // dependency will be installed if found
|
||||
@@ -35,6 +40,8 @@ enum class DependencyLevel {
|
||||
struct DependencyPack {
|
||||
DependencyLevel level;
|
||||
std::string id;
|
||||
std::string version;
|
||||
std::string op;
|
||||
};
|
||||
|
||||
struct ContentPackStats {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "ContentPackVersion.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "coders/commons.hpp"
|
||||
|
||||
Version::Version(const std::string& version) {
|
||||
major = 0;
|
||||
minor = 0;
|
||||
patch = 0;
|
||||
|
||||
std::vector<int> parts;
|
||||
|
||||
std::stringstream ss(version);
|
||||
std::string part;
|
||||
while (std::getline(ss, part, '.')) {
|
||||
if (!part.empty()) {
|
||||
parts.push_back(std::stoi(part));
|
||||
}
|
||||
}
|
||||
|
||||
if (parts.size() > 0) major = parts[0];
|
||||
if (parts.size() > 1) minor = parts[1];
|
||||
if (parts.size() > 2) patch = parts[2];
|
||||
}
|
||||
|
||||
DependencyVersionOperator Version::string_to_operator(const std::string& op) {
|
||||
if (op == "=")
|
||||
return DependencyVersionOperator::equal;
|
||||
else if (op == ">")
|
||||
return DependencyVersionOperator::more;
|
||||
else if (op == "<")
|
||||
return DependencyVersionOperator::less;
|
||||
else if (op == ">=" || op == "=>")
|
||||
return DependencyVersionOperator::more_or_equal;
|
||||
else if (op == "<=" || op == "=<")
|
||||
return DependencyVersionOperator::less_or_equal;
|
||||
else return DependencyVersionOperator::equal;
|
||||
}
|
||||
|
||||
bool isNumber(const std::string& s) {
|
||||
return !s.empty() && std::all_of(s.begin(), s.end(), ::is_digit);
|
||||
}
|
||||
|
||||
bool Version::matches_pattern(const std::string& version) {
|
||||
for (char c : version) {
|
||||
if (!isdigit(c) && c != '.') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream ss(version);
|
||||
|
||||
std::vector<std::string> parts;
|
||||
std::string part;
|
||||
while (std::getline(ss, part, '.')) {
|
||||
if (part.empty()) return false;
|
||||
if (!isNumber(part)) return false;
|
||||
|
||||
parts.push_back(part);
|
||||
}
|
||||
|
||||
return parts.size() == 2 || parts.size() == 3;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#include <string>
|
||||
|
||||
#include "content/ContentPack.hpp"
|
||||
|
||||
class Version {
|
||||
public:
|
||||
int major;
|
||||
int minor;
|
||||
int patch;
|
||||
|
||||
Version(const std::string& version);
|
||||
|
||||
bool operator==(const Version& other) const {
|
||||
return major == other.major && minor == other.minor && patch == other.patch;
|
||||
}
|
||||
|
||||
bool operator<(const Version& other) const {
|
||||
if (major != other.major) return major < other.major;
|
||||
if (minor != other.minor) return minor < other.minor;
|
||||
return patch < other.patch;
|
||||
}
|
||||
|
||||
|
||||
bool operator>(const Version& other) const {
|
||||
return other < *this;
|
||||
}
|
||||
|
||||
bool operator>=(const Version& other) const {
|
||||
return !(*this < other);
|
||||
}
|
||||
|
||||
bool operator<=(const Version& other) const {
|
||||
return !(*this > other);
|
||||
}
|
||||
|
||||
bool process_operator(const std::string& op, const Version& other) const {
|
||||
auto dep_op = Version::string_to_operator(op);
|
||||
|
||||
switch(dep_op) {
|
||||
case DependencyVersionOperator::equal: return *this == other;
|
||||
case DependencyVersionOperator::more: return *this > other;
|
||||
case DependencyVersionOperator::less: return *this < other;
|
||||
case DependencyVersionOperator::less_or_equal: return *this <= other;
|
||||
case DependencyVersionOperator::more_or_equal: return *this >= other;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
static DependencyVersionOperator string_to_operator(const std::string& op);
|
||||
static bool matches_pattern(const std::string& version);
|
||||
};
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
|
||||
#include "ContentPackVersion.hpp"
|
||||
#include "util/listutil.hpp"
|
||||
|
||||
PacksManager::PacksManager() = default;
|
||||
@@ -106,6 +107,23 @@ static bool resolve_dependencies(
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dep_pack = found -> second;
|
||||
|
||||
if (Version::matches_pattern(dep.version) && Version::matches_pattern(dep_pack.version)
|
||||
&& Version(dep_pack.version)
|
||||
.process_operator(dep.op, Version(dep.version))
|
||||
) {
|
||||
// dependency pack version meets the required one
|
||||
continue;
|
||||
} else if (dep.version == "*" || dep.version == dep_pack.version){
|
||||
// fallback: dependency pack version also meets required one
|
||||
continue;
|
||||
} else {
|
||||
throw contentpack_error(
|
||||
dep.id, io::path(), "does not meet required version '" + dep.op + dep.version +"' of '" + pack->id + "'"
|
||||
);
|
||||
}
|
||||
|
||||
if (!util::contains(allNames, dep.id) &&
|
||||
dep.level != DependencyLevel::weak) {
|
||||
allNames.push_back(dep.id);
|
||||
|
||||
@@ -114,7 +114,8 @@ static int l_pack_get_info(
|
||||
default:
|
||||
throw std::runtime_error("");
|
||||
}
|
||||
lua::pushfstring(L, "%s%s", prefix.c_str(), dpack.id.c_str());
|
||||
|
||||
lua::pushfstring(L, "%s%s@%s%s", prefix.c_str(), dpack.id.c_str(), dpack.op.c_str(), dpack.version.c_str());
|
||||
lua::rawseti(L, i + 1);
|
||||
}
|
||||
lua::setfield(L, "dependencies");
|
||||
|
||||
Reference in New Issue
Block a user