fix segfaults consistently set component problems
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
a85d6cb1f2
commit
4ed92a95c2
@ -45,6 +45,7 @@
|
|||||||
#include "OneSixVersionFormat.h"
|
#include "OneSixVersionFormat.h"
|
||||||
#include "VersionFile.h"
|
#include "VersionFile.h"
|
||||||
#include "meta/Version.h"
|
#include "meta/Version.h"
|
||||||
|
#include "minecraft/Component.h"
|
||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/PackProfile.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -438,14 +439,14 @@ void Component::setUpdateAction(UpdateAction action)
|
|||||||
m_updateAction = action;
|
m_updateAction = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<UpdateAction> Component::getUpdateAction()
|
UpdateAction Component::getUpdateAction()
|
||||||
{
|
{
|
||||||
return m_updateAction;
|
return m_updateAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Component::clearUpdateAction()
|
void Component::clearUpdateAction()
|
||||||
{
|
{
|
||||||
m_updateAction.reset();
|
m_updateAction = UpdateAction{ UpdateActionNone{} };
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug d, const Component& comp)
|
QDebug operator<<(QDebug d, const Component& comp)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <variant>
|
||||||
#include "ProblemProvider.h"
|
#include "ProblemProvider.h"
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
#include "meta/JsonFormat.h"
|
#include "meta/JsonFormat.h"
|
||||||
@ -17,7 +18,7 @@ class VersionList;
|
|||||||
} // namespace Meta
|
} // namespace Meta
|
||||||
class VersionFile;
|
class VersionFile;
|
||||||
|
|
||||||
struct UpdateActionChangeVerison {
|
struct UpdateActionChangeVersion {
|
||||||
/// version to change to
|
/// version to change to
|
||||||
QString targetVersion;
|
QString targetVersion;
|
||||||
};
|
};
|
||||||
@ -34,8 +35,13 @@ struct UpdateActionImportantChanged {
|
|||||||
QString oldVersion;
|
QString oldVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
using UpdateAction =
|
using UpdateActionNone = std::monostate;
|
||||||
std::variant<UpdateActionChangeVerison, UpdateActionLatestRecommendedCompatable, UpdateActionRemove, UpdateActionImportantChanged>;
|
|
||||||
|
using UpdateAction = std::variant<UpdateActionNone,
|
||||||
|
UpdateActionChangeVersion,
|
||||||
|
UpdateActionLatestRecommendedCompatable,
|
||||||
|
UpdateActionRemove,
|
||||||
|
UpdateActionImportantChanged>;
|
||||||
|
|
||||||
class Component : public QObject, public ProblemProvider {
|
class Component : public QObject, public ProblemProvider {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -92,8 +98,7 @@ class Component : public QObject, public ProblemProvider {
|
|||||||
|
|
||||||
void setUpdateAction(UpdateAction action);
|
void setUpdateAction(UpdateAction action);
|
||||||
void clearUpdateAction();
|
void clearUpdateAction();
|
||||||
std::optional<UpdateAction> getUpdateAction();
|
UpdateAction getUpdateAction();
|
||||||
std::optional<UpdateAction> takeUpdateAction();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataChanged();
|
void dataChanged();
|
||||||
@ -136,7 +141,7 @@ class Component : public QObject, public ProblemProvider {
|
|||||||
private:
|
private:
|
||||||
QList<PatchProblem> m_componentProblems;
|
QList<PatchProblem> m_componentProblems;
|
||||||
ProblemSeverity m_componentProblemSeverity = ProblemSeverity::None;
|
ProblemSeverity m_componentProblemSeverity = ProblemSeverity::None;
|
||||||
std::optional<UpdateAction> m_updateAction = std::nullopt;
|
UpdateAction m_updateAction = UpdateAction{ UpdateActionNone{} };
|
||||||
};
|
};
|
||||||
|
|
||||||
using ComponentPtr = shared_qobject_ptr<Component>;
|
using ComponentPtr = shared_qobject_ptr<Component>;
|
||||||
|
@ -153,6 +153,7 @@ void ComponentUpdateTask::loadComponents()
|
|||||||
Task::Ptr loadTask;
|
Task::Ptr loadTask;
|
||||||
LoadResult singleResult;
|
LoadResult singleResult;
|
||||||
RemoteLoadStatus::Type loadType;
|
RemoteLoadStatus::Type loadType;
|
||||||
|
component->resetComponentProblems();
|
||||||
// FIXME: to do this right, we need to load the lists and decide on which versions to use during dependency resolution. For now,
|
// FIXME: to do this right, we need to load the lists and decide on which versions to use during dependency resolution. For now,
|
||||||
// ignore all that...
|
// ignore all that...
|
||||||
#if 0
|
#if 0
|
||||||
@ -445,6 +446,7 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly)
|
|||||||
allRequires.clear();
|
allRequires.clear();
|
||||||
toRemove.clear();
|
toRemove.clear();
|
||||||
if (!gatherRequirementsFromComponents(components, allRequires)) {
|
if (!gatherRequirementsFromComponents(components, allRequires)) {
|
||||||
|
finalizeComponents();
|
||||||
emitFailed(tr("Conflicting requirements detected during dependency checking!"));
|
emitFailed(tr("Conflicting requirements detected during dependency checking!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -461,10 +463,12 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly)
|
|||||||
RequireExSet toChange;
|
RequireExSet toChange;
|
||||||
bool succeeded = getTrivialComponentChanges(componentIndex, allRequires, toAdd, toChange);
|
bool succeeded = getTrivialComponentChanges(componentIndex, allRequires, toAdd, toChange);
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
|
finalizeComponents();
|
||||||
emitFailed(tr("Instance has conflicting dependencies."));
|
emitFailed(tr("Instance has conflicting dependencies."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (checkOnly) {
|
if (checkOnly) {
|
||||||
|
finalizeComponents();
|
||||||
if (toAdd.size() || toChange.size()) {
|
if (toAdd.size() || toChange.size()) {
|
||||||
emitFailed(tr("Instance has unresolved dependencies while loading/checking for launch."));
|
emitFailed(tr("Instance has unresolved dependencies while loading/checking for launch."));
|
||||||
} else {
|
} else {
|
||||||
@ -542,19 +546,35 @@ overload(Ts...) -> overload<Ts...>;
|
|||||||
|
|
||||||
void ComponentUpdateTask::performUpdateActions()
|
void ComponentUpdateTask::performUpdateActions()
|
||||||
{
|
{
|
||||||
auto& components = d->m_profile->d->components;
|
auto& instance = d->m_profile->d->m_instance;
|
||||||
|
|
||||||
bool addedActions;
|
bool addedActions;
|
||||||
|
QStringList toRemove;
|
||||||
do {
|
do {
|
||||||
addedActions = false;
|
addedActions = false;
|
||||||
|
toRemove.clear();
|
||||||
|
auto& components = d->m_profile->d->components;
|
||||||
|
auto& componentIndex = d->m_profile->d->componentIndex;
|
||||||
for (auto component : components) {
|
for (auto component : components) {
|
||||||
if (auto action = component->getUpdateAction()) {
|
if (!component) {
|
||||||
auto visitor = overload{
|
continue;
|
||||||
[&component](const UpdateActionChangeVerison& cv) {
|
}
|
||||||
|
auto action = component->getUpdateAction();
|
||||||
|
auto visitor =
|
||||||
|
overload{ [](const UpdateActionNone&) {
|
||||||
|
// noop
|
||||||
|
},
|
||||||
|
[&component, &instance](const UpdateActionChangeVersion& cv) {
|
||||||
|
qCDebug(instanceProfileResolveC) << instance->name() << "|"
|
||||||
|
<< "UpdateActionChangeVersion" << component->getID() << ":"
|
||||||
|
<< component->getVersion() << "change to" << cv.targetVersion;
|
||||||
component->setVersion(cv.targetVersion);
|
component->setVersion(cv.targetVersion);
|
||||||
component->waitLoadMeta();
|
component->waitLoadMeta();
|
||||||
},
|
},
|
||||||
[&component](const UpdateActionLatestRecommendedCompatable lrc) {
|
[&component, &instance](const UpdateActionLatestRecommendedCompatable lrc) {
|
||||||
|
qCDebug(instanceProfileResolveC)
|
||||||
|
<< instance->name() << "|"
|
||||||
|
<< "UpdateActionLatestRecommendedCompatable" << component->getID() << ":" << component->getVersion()
|
||||||
|
<< "updating to latest recommend or compatible with" << lrc.parentUid << lrc.version;
|
||||||
auto versionList = APPLICATION->metadataIndex()->get(component->getID());
|
auto versionList = APPLICATION->metadataIndex()->get(component->getID());
|
||||||
versionList->waitToLoad();
|
versionList->waitToLoad();
|
||||||
if (versionList) {
|
if (versionList) {
|
||||||
@ -575,12 +595,33 @@ void ComponentUpdateTask::performUpdateActions()
|
|||||||
.arg(component->getName(), lrc.parentName, lrc.version));
|
.arg(component->getName(), lrc.parentName, lrc.version));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
component->addComponentProblem(ProblemSeverity::Error,
|
component->addComponentProblem(
|
||||||
|
ProblemSeverity::Error,
|
||||||
QObject::tr("No version list in metadata index for %1").arg(component->getID()));
|
QObject::tr("No version list in metadata index for %1").arg(component->getID()));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[this, &component](const UpdateActionRemove&) { d->m_profile->remove(component->getID()); },
|
[&component, &instance, &toRemove](const UpdateActionRemove&) {
|
||||||
[this, &component, &addedActions](const UpdateActionImportantChanged&) {
|
qCDebug(instanceProfileResolveC)
|
||||||
|
<< instance->name() << "|"
|
||||||
|
<< "UpdateActionRemove" << component->getID() << ":" << component->getVersion() << "removing";
|
||||||
|
toRemove.append(component->getID());
|
||||||
|
},
|
||||||
|
[this, &component, &instance, &addedActions, &componentIndex](const UpdateActionImportantChanged& ic) {
|
||||||
|
qCDebug(instanceProfileResolveC)
|
||||||
|
<< instance->name() << "|"
|
||||||
|
<< "UpdateImportantChanged" << component->getID() << ":" << component->getVersion() << "was changed from"
|
||||||
|
<< ic.oldVersion << "updating linked components";
|
||||||
|
auto oldVersion = APPLICATION->metadataIndex()->getLoadedVersion(component->getID(), ic.oldVersion);
|
||||||
|
for (auto oldReq : oldVersion->requiredSet()) {
|
||||||
|
auto currentlyRequired = component->m_cachedRequires.find(oldReq);
|
||||||
|
if (currentlyRequired == component->m_cachedRequires.cend()) {
|
||||||
|
auto oldReqComp = componentIndex.find(oldReq.uid);
|
||||||
|
if (oldReqComp != componentIndex.cend()) {
|
||||||
|
(*oldReqComp)->setUpdateAction(UpdateAction{ UpdateActionRemove{} });
|
||||||
|
addedActions = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
auto linked = collectTreeLinked(component->getID());
|
auto linked = collectTreeLinked(component->getID());
|
||||||
for (auto comp : linked) {
|
for (auto comp : linked) {
|
||||||
if (comp->isCustom()) {
|
if (comp->isCustom()) {
|
||||||
@ -592,7 +633,7 @@ void ComponentUpdateTask::performUpdateActions()
|
|||||||
if (parentReq != component->m_cachedRequires.end()) {
|
if (parentReq != component->m_cachedRequires.end()) {
|
||||||
auto newVersion = parentReq->equalsVersion.isEmpty() ? parentReq->suggests : parentReq->equalsVersion;
|
auto newVersion = parentReq->equalsVersion.isEmpty() ? parentReq->suggests : parentReq->equalsVersion;
|
||||||
if (!newVersion.isEmpty()) {
|
if (!newVersion.isEmpty()) {
|
||||||
comp->setUpdateAction(UpdateAction{ UpdateActionChangeVerison{ newVersion } });
|
comp->setUpdateAction(UpdateAction{ UpdateActionChangeVersion{ newVersion } });
|
||||||
} else {
|
} else {
|
||||||
comp->setUpdateAction(UpdateAction{ UpdateActionLatestRecommendedCompatable{
|
comp->setUpdateAction(UpdateAction{ UpdateActionLatestRecommendedCompatable{
|
||||||
component->getID(),
|
component->getID(),
|
||||||
@ -609,10 +650,11 @@ void ComponentUpdateTask::performUpdateActions()
|
|||||||
}
|
}
|
||||||
addedActions = true;
|
addedActions = true;
|
||||||
}
|
}
|
||||||
}
|
} };
|
||||||
};
|
std::visit(visitor, action);
|
||||||
std::visit(visitor, *action);
|
|
||||||
component->clearUpdateAction();
|
component->clearUpdateAction();
|
||||||
|
for (auto uid : toRemove) {
|
||||||
|
d->m_profile->remove(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (addedActions);
|
} while (addedActions);
|
||||||
@ -637,6 +679,15 @@ void ComponentUpdateTask::finalizeComponents()
|
|||||||
reqComp->getProblemSeverity(),
|
reqComp->getProblemSeverity(),
|
||||||
QObject::tr("%1, a dependency of this component, has reported issues").arg(reqComp->getName()));
|
QObject::tr("%1, a dependency of this component, has reported issues").arg(reqComp->getName()));
|
||||||
}
|
}
|
||||||
|
if (!req.equalsVersion.isEmpty() && req.equalsVersion != reqComp->getVersion()) {
|
||||||
|
component->addComponentProblem(ProblemSeverity::Error,
|
||||||
|
QObject::tr("%1, a dependency of this component, is not the required version %2")
|
||||||
|
.arg(reqComp->getName(), req.equalsVersion));
|
||||||
|
} else if (!req.suggests.isEmpty() && req.suggests != reqComp->getVersion()) {
|
||||||
|
component->addComponentProblem(ProblemSeverity::Warning,
|
||||||
|
QObject::tr("%1, a dependency of this component, is not the suggested version %2")
|
||||||
|
.arg(reqComp->getName(), req.suggests));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user