From 85ae710d407eb31527183d5f8bec0399eb209f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 11 Nov 2017 01:38:31 +0100 Subject: GH-2026 implement changes necessary to support 1.13 snapshots --- api/logic/meta/BaseEntity.cpp | 4 +-- api/logic/meta/BaseEntity.h | 3 +- api/logic/meta/JsonFormat.cpp | 66 ++++++++++++++++++++++++++++++++++-------- api/logic/meta/JsonFormat.h | 33 +++++++++++++++++++++ api/logic/meta/Version.cpp | 19 ++++++++++-- api/logic/meta/Version.h | 15 ++++++++-- api/logic/meta/VersionList.cpp | 31 +++++++++++++++----- 7 files changed, 144 insertions(+), 27 deletions(-) (limited to 'api/logic/meta') diff --git a/api/logic/meta/BaseEntity.cpp b/api/logic/meta/BaseEntity.cpp index 6bac71ee..7cf327be 100644 --- a/api/logic/meta/BaseEntity.cpp +++ b/api/logic/meta/BaseEntity.cpp @@ -99,7 +99,7 @@ bool Meta::BaseEntity::loadLocalFile() } } -void Meta::BaseEntity::load() +void Meta::BaseEntity::load(Net::Mode loadType) { // load local file if nothing is loaded yet if(!isLoaded()) @@ -110,7 +110,7 @@ void Meta::BaseEntity::load() } } // if we need remote update, run the update task - if(!shouldStartRemoteUpdate()) + if(loadType == Net::Mode::Offline || !shouldStartRemoteUpdate()) { return; } diff --git a/api/logic/meta/BaseEntity.h b/api/logic/meta/BaseEntity.h index 4483beab..4c74b1a7 100644 --- a/api/logic/meta/BaseEntity.h +++ b/api/logic/meta/BaseEntity.h @@ -20,6 +20,7 @@ #include "QObjectPtr.h" #include "multimc_logic_export.h" +#include "net/Mode.h" class Task; namespace Meta @@ -54,7 +55,7 @@ public: bool isLoaded() const; bool shouldStartRemoteUpdate() const; - void load(); + void load(Net::Mode loadType); shared_qobject_ptr getCurrentTask(); protected: /* methods */ diff --git a/api/logic/meta/JsonFormat.cpp b/api/logic/meta/JsonFormat.cpp index d13c89df..2c313478 100644 --- a/api/logic/meta/JsonFormat.cpp +++ b/api/logic/meta/JsonFormat.cpp @@ -51,18 +51,11 @@ static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj) version->setType(ensureString(obj, "type", QString())); version->setParentUid(ensureString(obj, "parentUid", QString())); version->setRecommended(ensureBoolean(obj, QString("recommended"), false)); - if(obj.contains("requires")) - { - QHash requires; - auto reqobj = requireObject(obj, "requires"); - auto iter = reqobj.begin(); - while(iter != reqobj.end()) - { - requires[iter.key()] = requireString(iter.value()); - iter++; - } - version->setRequires(requires); - } + version->setVolatile(ensureBoolean(obj, QString("volatile"), false)); + RequireSet requires, conflicts; + parseRequires(obj, &requires, "requires"); + parseRequires(obj, &conflicts, "conflicts"); + version->setRequires(requires, conflicts); return version; } @@ -145,4 +138,53 @@ void parseVersion(const QJsonObject &obj, Version *ptr) throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version)); } } + +/* +[ +{"uid":"foo", "equals":"version"} +] +*/ +void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char * keyName) +{ + if(obj.contains(keyName)) + { + QSet requires; + auto reqArray = requireArray(obj, keyName); + auto iter = reqArray.begin(); + while(iter != reqArray.end()) + { + auto reqObject = requireObject(*iter); + auto uid = requireString(reqObject, "uid"); + auto equals = ensureString(reqObject, "equals", QString()); + auto suggests = ensureString(reqObject, "suggests", QString()); + ptr->insert({uid, equals, suggests}); + iter++; + } + } } +void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char * keyName) +{ + if(!ptr || ptr->empty()) + { + return; + } + QJsonArray arrOut; + for(auto &iter: *ptr) + { + QJsonObject reqOut; + reqOut.insert("uid", iter.uid); + if(!iter.equalsVersion.isEmpty()) + { + reqOut.insert("equals", iter.equalsVersion); + } + if(!iter.suggests.isEmpty()) + { + reqOut.insert("suggests", iter.suggests); + } + arrOut.append(reqOut); + } + obj.insert(keyName, arrOut); +} + +} + diff --git a/api/logic/meta/JsonFormat.h b/api/logic/meta/JsonFormat.h index aaed07fc..9b9dcd91 100644 --- a/api/logic/meta/JsonFormat.h +++ b/api/logic/meta/JsonFormat.h @@ -20,6 +20,7 @@ #include "Exception.h" #include "meta/BaseEntity.h" +#include namespace Meta { @@ -32,9 +33,41 @@ class ParseException : public Exception public: using Exception::Exception; }; +struct Require +{ + bool operator==(const Require & rhs) const + { + return uid == rhs.uid; + } + bool operator<(const Require & rhs) const + { + return uid < rhs.uid; + } + bool deepEquals(const Require & rhs) const + { + return uid == rhs.uid + && equalsVersion == rhs.equalsVersion + && suggests == rhs.suggests; + } + QString uid; + QString equalsVersion; + QString suggests; +}; + +inline Q_DECL_PURE_FUNCTION uint qHash(const Require &key, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(key.uid, seed); +} + +using RequireSet = std::set; void parseIndex(const QJsonObject &obj, Index *ptr); void parseVersion(const QJsonObject &obj, Version *ptr); void parseVersionList(const QJsonObject &obj, VersionList *ptr); +// FIXME: this has a different shape than the others...FIX IT!? +void parseRequires(const QJsonObject &obj, RequireSet * ptr, const char * keyName = "requires"); +void serializeRequires(QJsonObject & objOut, RequireSet* ptr, const char * keyName = "requires"); } + +Q_DECLARE_METATYPE(std::set); \ No newline at end of file diff --git a/api/logic/meta/Version.cpp b/api/logic/meta/Version.cpp index bf739157..d82878a1 100644 --- a/api/logic/meta/Version.cpp +++ b/api/logic/meta/Version.cpp @@ -74,12 +74,20 @@ void Meta::Version::merge(const std::shared_ptr &other) } if (m_requires != version->m_requires) { - setRequires(version->m_requires); + m_requires = version->m_requires; + } + if (m_conflicts != version->m_conflicts) + { + m_conflicts = version->m_conflicts; } if (m_parentUid != version->m_parentUid) { setParentUid(version->m_parentUid); } + if(m_volatile != version->m_volatile) + { + setVolatile(version->m_volatile); + } if(version->m_data) { setData(version->m_data); @@ -109,12 +117,19 @@ void Meta::Version::setTime(const qint64 time) emit timeChanged(); } -void Meta::Version::setRequires(const QHash &requires) +void Meta::Version::setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts) { m_requires = requires; + m_conflicts = conflicts; emit requiresChanged(); } +void Meta::Version::setVolatile(bool volatile_) +{ + m_volatile = volatile_; +} + + void Meta::Version::setData(const VersionFilePtr &data) { m_data = data; diff --git a/api/logic/meta/Version.h b/api/logic/meta/Version.h index 2f92ee9f..61f253c6 100644 --- a/api/logic/meta/Version.h +++ b/api/logic/meta/Version.h @@ -28,6 +28,8 @@ #include "multimc_logic_export.h" +#include "JsonFormat.h" + namespace Meta { using VersionPtr = std::shared_ptr; @@ -65,7 +67,7 @@ public: /* con/des */ { return m_time; } - const QHash &requires() const + const Meta::RequireSet &requires() const { return m_requires; } @@ -77,6 +79,10 @@ public: /* con/des */ { return m_recommended; } + bool isLoaded() const + { + return m_data != nullptr; + } void merge(const std::shared_ptr &other) override; void parse(const QJsonObject &obj) override; @@ -87,7 +93,8 @@ public: // for usage by format parsers only void setParentUid(const QString &parentUid); void setType(const QString &type); void setTime(const qint64 time); - void setRequires(const QHash &requires); + void setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts); + void setVolatile(bool volatile_); void setRecommended(bool recommended); void setProvidesRecommendations(); void setData(const VersionFilePtr &data); @@ -106,7 +113,9 @@ private: QString m_version; QString m_type; qint64 m_time = 0; - QHash m_requires; + Meta::RequireSet m_requires; + Meta::RequireSet m_conflicts; + bool m_volatile = false; VersionFilePtr m_data; }; } diff --git a/api/logic/meta/VersionList.cpp b/api/logic/meta/VersionList.cpp index 4da0fb76..8910c4d7 100644 --- a/api/logic/meta/VersionList.cpp +++ b/api/logic/meta/VersionList.cpp @@ -30,7 +30,7 @@ VersionList::VersionList(const QString &uid, QObject *parent) shared_qobject_ptr VersionList::getLoadTask() { - load(); + load(Net::Mode::Online); return getCurrentTask(); } @@ -81,10 +81,13 @@ QVariant VersionList::data(const QModelIndex &index, int role) const return QVariant(); } auto & reqs = version->requires(); - auto iter = reqs.find(parentUid); + auto iter = std::find_if(reqs.begin(), reqs.end(), [&parentUid](const Require & req) + { + return req.uid == parentUid; + }); if (iter != reqs.end()) { - return iter.value(); + return (*iter).equalsVersion; } } case TypeRole: return version->type(); @@ -159,6 +162,7 @@ void VersionList::setVersions(const QVector &versions) setupAddedVersion(i, m_versions.at(i)); } + // FIXME: this is dumb, we have 'recommended' as part of the metadata already... auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; }); m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt; endResetModel(); @@ -169,6 +173,22 @@ void VersionList::parse(const QJsonObject& obj) parseVersionList(obj, this); } +// FIXME: this is dumb, we have 'recommended' as part of the metadata already... +static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b) +{ + if(!a) + return b; + if(!b) + return a; + if(a->type() == b->type()) + { + // newer of same type wins + return (a->rawTime() > b->rawTime() ? a : b); + } + // 'release' type wins + return (a->type() == "release" ? a : b); +} + void VersionList::merge(const BaseEntity::Ptr &other) { const VersionListPtr list = std::dynamic_pointer_cast(other); @@ -199,10 +219,7 @@ void VersionList::merge(const BaseEntity::Ptr &other) // connect it. setupAddedVersion(m_versions.size(), version); m_versions.append(version); - if (!m_recommended || (version->type() == "release" && version->rawTime() > m_recommended->rawTime())) - { - m_recommended = version; - } + m_recommended = getBetterVersion(m_recommended, version); } endResetModel(); } -- cgit v1.2.3