NOISSUE add versioning to component metadata format and use it
This commit is contained in:
parent
50ca6cbb4d
commit
719f3e863a
@ -28,6 +28,11 @@ using namespace Json;
|
||||
namespace Meta
|
||||
{
|
||||
|
||||
MetadataVersion currentFormatVersion()
|
||||
{
|
||||
return MetadataVersion::InitialRelease;
|
||||
}
|
||||
|
||||
// Index
|
||||
static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj)
|
||||
{
|
||||
@ -49,7 +54,6 @@ static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj)
|
||||
VersionPtr version = std::make_shared<Version>(uid, requireString(obj, "version"));
|
||||
version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000);
|
||||
version->setType(ensureString(obj, "type", QString()));
|
||||
version->setParentUid(ensureString(obj, "parentUid", QString()));
|
||||
version->setRecommended(ensureBoolean(obj, QString("recommended"), false));
|
||||
version->setVolatile(ensureBoolean(obj, QString("volatile"), false));
|
||||
RequireSet requires, conflicts;
|
||||
@ -86,56 +90,79 @@ static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject &
|
||||
|
||||
VersionListPtr list = std::make_shared<VersionList>(uid);
|
||||
list->setName(ensureString(obj, "name", QString()));
|
||||
list->setParentUid(ensureString(obj, "parentUid", QString()));
|
||||
list->setVersions(versions);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
static int formatVersion(const QJsonObject &obj)
|
||||
MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required)
|
||||
{
|
||||
if (!obj.contains("formatVersion")) {
|
||||
throw ParseException(QObject::tr("Missing required field: 'formatVersion'"));
|
||||
if (!obj.contains("formatVersion"))
|
||||
{
|
||||
if(required)
|
||||
{
|
||||
return MetadataVersion::Invalid;
|
||||
}
|
||||
return MetadataVersion::InitialRelease;
|
||||
}
|
||||
if (!obj.value("formatVersion").isDouble()) {
|
||||
throw ParseException(QObject::tr("Required field has invalid type: 'formatVersion'"));
|
||||
if (!obj.value("formatVersion").isDouble())
|
||||
{
|
||||
return MetadataVersion::Invalid;
|
||||
}
|
||||
return obj.value("formatVersion").toInt();
|
||||
switch(obj.value("formatVersion").toInt())
|
||||
{
|
||||
case 0:
|
||||
return MetadataVersion::InitialRelease;
|
||||
default:
|
||||
return MetadataVersion::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
void serializeFormatVersion(QJsonObject& obj, Meta::MetadataVersion version)
|
||||
{
|
||||
if(version == MetadataVersion::Invalid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
obj.insert("formatVersion", int(version));
|
||||
}
|
||||
|
||||
void parseIndex(const QJsonObject &obj, Index *ptr)
|
||||
{
|
||||
const int version = formatVersion(obj);
|
||||
switch (version) {
|
||||
case 0:
|
||||
const MetadataVersion version = parseFormatVersion(obj);
|
||||
switch (version)
|
||||
{
|
||||
case MetadataVersion::InitialRelease:
|
||||
ptr->merge(parseIndexInternal(obj));
|
||||
break;
|
||||
default:
|
||||
throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version));
|
||||
case MetadataVersion::Invalid:
|
||||
throw ParseException(QObject::tr("Unknown format version!"));
|
||||
}
|
||||
}
|
||||
|
||||
void parseVersionList(const QJsonObject &obj, VersionList *ptr)
|
||||
{
|
||||
const int version = formatVersion(obj);
|
||||
switch (version) {
|
||||
case 0:
|
||||
const MetadataVersion version = parseFormatVersion(obj);
|
||||
switch (version)
|
||||
{
|
||||
case MetadataVersion::InitialRelease:
|
||||
ptr->merge(parseVersionListInternal(obj));
|
||||
break;
|
||||
default:
|
||||
throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version));
|
||||
case MetadataVersion::Invalid:
|
||||
throw ParseException(QObject::tr("Unknown format version!"));
|
||||
}
|
||||
}
|
||||
|
||||
void parseVersion(const QJsonObject &obj, Version *ptr)
|
||||
{
|
||||
const int version = formatVersion(obj);
|
||||
switch (version) {
|
||||
case 0:
|
||||
const MetadataVersion version = parseFormatVersion(obj);
|
||||
switch (version)
|
||||
{
|
||||
case MetadataVersion::InitialRelease:
|
||||
ptr->merge(parseVersionInternal(obj));
|
||||
break;
|
||||
default:
|
||||
throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version));
|
||||
case MetadataVersion::Invalid:
|
||||
throw ParseException(QObject::tr("Unknown format version!"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,12 @@ class Index;
|
||||
class Version;
|
||||
class VersionList;
|
||||
|
||||
enum class MetadataVersion
|
||||
{
|
||||
Invalid = -1,
|
||||
InitialRelease = 0
|
||||
};
|
||||
|
||||
class ParseException : public Exception
|
||||
{
|
||||
public:
|
||||
@ -65,9 +71,13 @@ void parseIndex(const QJsonObject &obj, Index *ptr);
|
||||
void parseVersion(const QJsonObject &obj, Version *ptr);
|
||||
void parseVersionList(const QJsonObject &obj, VersionList *ptr);
|
||||
|
||||
MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required = true);
|
||||
void serializeFormatVersion(QJsonObject &obj, MetadataVersion version);
|
||||
|
||||
// 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");
|
||||
MetadataVersion currentFormatVersion();
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::set<Meta::Require>);
|
@ -79,10 +79,6 @@ void Meta::Version::mergeFromList(const Meta::VersionPtr& other)
|
||||
{
|
||||
m_conflicts = other->m_conflicts;
|
||||
}
|
||||
if (m_parentUid != other->m_parentUid)
|
||||
{
|
||||
setParentUid(other->m_parentUid);
|
||||
}
|
||||
if(m_volatile != other->m_volatile)
|
||||
{
|
||||
setVolatile(other->m_volatile);
|
||||
@ -103,12 +99,6 @@ QString Meta::Version::localFilename() const
|
||||
return m_uid + '/' + m_version + ".json";
|
||||
}
|
||||
|
||||
void Meta::Version::setParentUid(const QString& parentUid)
|
||||
{
|
||||
m_parentUid = parentUid;
|
||||
emit requiresChanged();
|
||||
}
|
||||
|
||||
void Meta::Version::setType(const QString &type)
|
||||
{
|
||||
m_type = type;
|
||||
|
@ -50,10 +50,6 @@ public: /* con/des */
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
QString parentUid() const
|
||||
{
|
||||
return m_parentUid;
|
||||
}
|
||||
QString version() const
|
||||
{
|
||||
return m_version;
|
||||
@ -91,7 +87,6 @@ public: /* con/des */
|
||||
QString localFilename() const override;
|
||||
|
||||
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 Meta::RequireSet &requires, const Meta::RequireSet &conflicts);
|
||||
@ -110,7 +105,6 @@ private:
|
||||
bool m_recommended = false;
|
||||
QString m_name;
|
||||
QString m_uid;
|
||||
QString m_parentUid;
|
||||
QString m_version;
|
||||
QString m_type;
|
||||
qint64 m_time = 0;
|
||||
|
@ -76,20 +76,17 @@ QVariant VersionList::data(const QModelIndex &index, int role) const
|
||||
return version->version();
|
||||
case ParentVersionRole:
|
||||
{
|
||||
auto parentUid = this->parentUid();
|
||||
if(parentUid.isEmpty())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
// FIXME: HACK: this should be generic and be replaced by something else. Anything that is a hard 'equals' dep is a 'parent uid'.
|
||||
auto & reqs = version->requires();
|
||||
auto iter = std::find_if(reqs.begin(), reqs.end(), [&parentUid](const Require & req)
|
||||
auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Require & req)
|
||||
{
|
||||
return req.uid == parentUid;
|
||||
return req.uid == "net.minecraft";
|
||||
});
|
||||
if (iter != reqs.end())
|
||||
{
|
||||
return (*iter).equalsVersion;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
case TypeRole: return version->type();
|
||||
|
||||
@ -196,11 +193,6 @@ void VersionList::mergeFromIndex(const VersionListPtr &other)
|
||||
{
|
||||
setName(other->m_name);
|
||||
}
|
||||
|
||||
if(m_parentUid != other->m_parentUid)
|
||||
{
|
||||
setParentUid(other->m_parentUid);
|
||||
}
|
||||
}
|
||||
|
||||
void VersionList::merge(const VersionListPtr &other)
|
||||
@ -210,11 +202,6 @@ void VersionList::merge(const VersionListPtr &other)
|
||||
setName(other->m_name);
|
||||
}
|
||||
|
||||
if(m_parentUid != other->m_parentUid)
|
||||
{
|
||||
setParentUid(other->m_parentUid);
|
||||
}
|
||||
|
||||
// TODO: do not reset the whole model. maybe?
|
||||
beginResetModel();
|
||||
m_versions.clear();
|
||||
@ -256,8 +243,3 @@ BaseVersionPtr VersionList::getRecommended() const
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Meta::VersionList::setParentUid(const QString& parentUid)
|
||||
{
|
||||
m_parentUid = parentUid;
|
||||
}
|
||||
|
@ -55,10 +55,6 @@ public:
|
||||
|
||||
QString localFilename() const override;
|
||||
|
||||
QString parentUid() const
|
||||
{
|
||||
return m_parentUid;
|
||||
}
|
||||
QString uid() const
|
||||
{
|
||||
return m_uid;
|
||||
@ -78,7 +74,6 @@ public:
|
||||
|
||||
public: // for usage only by parsers
|
||||
void setName(const QString &name);
|
||||
void setParentUid(const QString &parentUid);
|
||||
void setVersions(const QVector<VersionPtr> &versions);
|
||||
void merge(const VersionListPtr &other);
|
||||
void mergeFromIndex(const VersionListPtr &other);
|
||||
@ -96,7 +91,6 @@ private:
|
||||
QVector<VersionPtr> m_versions;
|
||||
QHash<QString, VersionPtr> m_lookup;
|
||||
QString m_uid;
|
||||
QString m_parentUid;
|
||||
QString m_name;
|
||||
|
||||
VersionPtr m_recommended;
|
||||
|
@ -450,42 +450,30 @@ bool ComponentList::migratePreComponentConfig()
|
||||
intendedVersion = emptyVersion;
|
||||
}
|
||||
auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false);
|
||||
bool fileChanged = false;
|
||||
// if uid is missing or incorrect, fix it
|
||||
if(file->uid != uid)
|
||||
{
|
||||
file->uid = uid;
|
||||
fileChanged = true;
|
||||
}
|
||||
// fix uid
|
||||
file->uid = uid;
|
||||
// if version is missing, add it from the outside.
|
||||
if(file->version.isEmpty())
|
||||
{
|
||||
file->version = intendedVersion;
|
||||
fileChanged = true;
|
||||
}
|
||||
// if this is a dependency (LWJGL), mark it also as volatile
|
||||
if(asDependency)
|
||||
{
|
||||
file->m_volatile = true;
|
||||
fileChanged = true;
|
||||
}
|
||||
// insert requirements if needed
|
||||
if(!req.uid.isEmpty())
|
||||
{
|
||||
file->requires.insert(req);
|
||||
fileChanged = true;
|
||||
}
|
||||
// insert conflicts if needed
|
||||
if(!conflict.uid.isEmpty())
|
||||
{
|
||||
file->conflicts.insert(conflict);
|
||||
fileChanged = true;
|
||||
}
|
||||
if(fileChanged)
|
||||
{
|
||||
// FIXME: @QUALITY do not ignore return value
|
||||
ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), jsonFilePath);
|
||||
}
|
||||
// FIXME: @QUALITY do not ignore return value
|
||||
ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), jsonFilePath);
|
||||
component = new Component(this, uid, file);
|
||||
component->m_version = intendedVersion;
|
||||
}
|
||||
@ -538,17 +526,9 @@ bool ComponentList::migratePreComponentConfig()
|
||||
QFile::remove(info.absoluteFilePath());
|
||||
continue;
|
||||
}
|
||||
bool fileChanged = false;
|
||||
if(file->uid != uid)
|
||||
{
|
||||
file->uid = uid;
|
||||
fileChanged = true;
|
||||
}
|
||||
if(fileChanged)
|
||||
{
|
||||
// FIXME: @QUALITY do not ignore return value
|
||||
ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), info.absoluteFilePath());
|
||||
}
|
||||
file->uid = uid;
|
||||
// FIXME: @QUALITY do not ignore return value
|
||||
ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), info.absoluteFilePath());
|
||||
|
||||
auto component = new Component(this, file->uid, file);
|
||||
auto version = d->getOldConfigVersion(file->uid);
|
||||
|
@ -52,6 +52,15 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
|
||||
QJsonObject root = doc.object();
|
||||
|
||||
Meta::MetadataVersion formatVersion = Meta::parseFormatVersion(root, false);
|
||||
switch(formatVersion)
|
||||
{
|
||||
case Meta::MetadataVersion::InitialRelease:
|
||||
break;
|
||||
case Meta::MetadataVersion::Invalid:
|
||||
throw JSONValidationError(filename + " does not contain a recognizable version of the metadata format.");
|
||||
}
|
||||
|
||||
if (requireOrder)
|
||||
{
|
||||
if (root.contains("order"))
|
||||
@ -77,8 +86,6 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
}
|
||||
|
||||
out->version = root.value("version").toString();
|
||||
out->dependsOnMinecraftVersion = root.value("mcVersion").toString();
|
||||
// out->filename = filename;
|
||||
|
||||
MojangVersionFormat::readVersionProperties(root, out.get());
|
||||
|
||||
@ -196,6 +203,17 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
{
|
||||
Meta::parseRequires(root, &out->requires);
|
||||
}
|
||||
QString dependsOnMinecraftVersion = root.value("mcVersion").toString();
|
||||
if(!dependsOnMinecraftVersion.isEmpty())
|
||||
{
|
||||
Meta::Require mcReq;
|
||||
mcReq.uid = "net.minecraft";
|
||||
mcReq.equalsVersion = dependsOnMinecraftVersion;
|
||||
if (out->requires.count(mcReq) == 0)
|
||||
{
|
||||
out->requires.insert(mcReq);
|
||||
}
|
||||
}
|
||||
if (root.contains("conflicts"))
|
||||
{
|
||||
Meta::parseRequires(root, &out->conflicts);
|
||||
@ -237,7 +255,8 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
|
||||
writeString(root, "uid", patch->uid);
|
||||
|
||||
writeString(root, "version", patch->version);
|
||||
writeString(root, "mcVersion", patch->dependsOnMinecraftVersion);
|
||||
|
||||
Meta::serializeFormatVersion(root, Meta::MetadataVersion::InitialRelease);
|
||||
|
||||
MojangVersionFormat::writeVersionProperties(patch.get(), root);
|
||||
|
||||
|
@ -18,7 +18,7 @@ class LaunchProfile;
|
||||
struct MojangDownloadInfo;
|
||||
struct MojangAssetIndexInfo;
|
||||
|
||||
typedef std::shared_ptr<VersionFile> VersionFilePtr;
|
||||
using VersionFilePtr = std::shared_ptr<VersionFile>;
|
||||
class VersionFile : public ProblemContainer
|
||||
{
|
||||
friend class MojangVersionFormat;
|
||||
|
@ -402,44 +402,6 @@ void VersionPage::on_forgeBtn_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use something like this... except the final decision of what to show has to be deferred until the lists are known
|
||||
/*
|
||||
void VersionPage::on_liteloaderBtn_clicked()
|
||||
{
|
||||
QString uid = "com.mumfrey.liteloader";
|
||||
auto vlist = ENV.metadataIndex()->get(uid);
|
||||
if(!vlist)
|
||||
{
|
||||
return;
|
||||
}
|
||||
VersionSelectDialog vselect(vlist.get(), tr("Select %1 version").arg(vlist->name()), this);
|
||||
auto parentUid = vlist->parentUid();
|
||||
if(!parentUid.isEmpty())
|
||||
{
|
||||
auto parentvlist = ENV.metadataIndex()->get(parentUid);
|
||||
vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion(parentUid));
|
||||
vselect.setEmptyString(
|
||||
tr("No %1 versions are currently available for %2 %3")
|
||||
.arg(vlist->name())
|
||||
.arg(parentvlist->name())
|
||||
.arg(m_profile->getComponentVersion(parentUid)));
|
||||
}
|
||||
else
|
||||
{
|
||||
vselect.setEmptyString(tr("No %1 versions are currently available"));
|
||||
}
|
||||
vselect.setEmptyErrorString(tr("Couldn't load or download the %1 version lists!").arg(vlist->name()));
|
||||
if (vselect.exec() && vselect.selectedVersion())
|
||||
{
|
||||
auto vsn = vselect.selectedVersion();
|
||||
m_profile->setComponentVersion(uid, vsn->descriptor());
|
||||
m_profile->resolve();
|
||||
preselect(m_profile->rowCount(QModelIndex())-1);
|
||||
m_container->refreshContainer();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void VersionPage::on_liteloaderBtn_clicked()
|
||||
{
|
||||
auto vlist = ENV.metadataIndex()->get("com.mumfrey.liteloader");
|
||||
|
Loading…
Reference in New Issue
Block a user