fix segfaults consistently set component problems

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers 2024-06-27 17:28:09 -07:00
parent a85d6cb1f2
commit 4ed92a95c2
No known key found for this signature in database
GPG Key ID: E10E321EB160949B
3 changed files with 131 additions and 74 deletions

View File

@ -45,6 +45,7 @@
#include "OneSixVersionFormat.h"
#include "VersionFile.h"
#include "meta/Version.h"
#include "minecraft/Component.h"
#include "minecraft/PackProfile.h"
#include <assert.h>
@ -438,14 +439,14 @@ void Component::setUpdateAction(UpdateAction action)
m_updateAction = action;
}
std::optional<UpdateAction> Component::getUpdateAction()
UpdateAction Component::getUpdateAction()
{
return m_updateAction;
}
void Component::clearUpdateAction()
{
m_updateAction.reset();
m_updateAction = UpdateAction{ UpdateActionNone{} };
}
QDebug operator<<(QDebug d, const Component& comp)

View File

@ -5,6 +5,7 @@
#include <QList>
#include <memory>
#include <optional>
#include <variant>
#include "ProblemProvider.h"
#include "QObjectPtr.h"
#include "meta/JsonFormat.h"
@ -17,7 +18,7 @@ class VersionList;
} // namespace Meta
class VersionFile;
struct UpdateActionChangeVerison {
struct UpdateActionChangeVersion {
/// version to change to
QString targetVersion;
};
@ -34,8 +35,13 @@ struct UpdateActionImportantChanged {
QString oldVersion;
};
using UpdateAction =
std::variant<UpdateActionChangeVerison, UpdateActionLatestRecommendedCompatable, UpdateActionRemove, UpdateActionImportantChanged>;
using UpdateActionNone = std::monostate;
using UpdateAction = std::variant<UpdateActionNone,
UpdateActionChangeVersion,
UpdateActionLatestRecommendedCompatable,
UpdateActionRemove,
UpdateActionImportantChanged>;
class Component : public QObject, public ProblemProvider {
Q_OBJECT
@ -92,8 +98,7 @@ class Component : public QObject, public ProblemProvider {
void setUpdateAction(UpdateAction action);
void clearUpdateAction();
std::optional<UpdateAction> getUpdateAction();
std::optional<UpdateAction> takeUpdateAction();
UpdateAction getUpdateAction();
signals:
void dataChanged();
@ -136,7 +141,7 @@ class Component : public QObject, public ProblemProvider {
private:
QList<PatchProblem> m_componentProblems;
ProblemSeverity m_componentProblemSeverity = ProblemSeverity::None;
std::optional<UpdateAction> m_updateAction = std::nullopt;
UpdateAction m_updateAction = UpdateAction{ UpdateActionNone{} };
};
using ComponentPtr = shared_qobject_ptr<Component>;

View File

@ -153,6 +153,7 @@ void ComponentUpdateTask::loadComponents()
Task::Ptr loadTask;
LoadResult singleResult;
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,
// ignore all that...
#if 0
@ -445,6 +446,7 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly)
allRequires.clear();
toRemove.clear();
if (!gatherRequirementsFromComponents(components, allRequires)) {
finalizeComponents();
emitFailed(tr("Conflicting requirements detected during dependency checking!"));
return;
}
@ -461,10 +463,12 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly)
RequireExSet toChange;
bool succeeded = getTrivialComponentChanges(componentIndex, allRequires, toAdd, toChange);
if (!succeeded) {
finalizeComponents();
emitFailed(tr("Instance has conflicting dependencies."));
return;
}
if (checkOnly) {
finalizeComponents();
if (toAdd.size() || toChange.size()) {
emitFailed(tr("Instance has unresolved dependencies while loading/checking for launch."));
} else {
@ -542,19 +546,35 @@ overload(Ts...) -> overload<Ts...>;
void ComponentUpdateTask::performUpdateActions()
{
auto& components = d->m_profile->d->components;
auto& instance = d->m_profile->d->m_instance;
bool addedActions;
QStringList toRemove;
do {
addedActions = false;
toRemove.clear();
auto& components = d->m_profile->d->components;
auto& componentIndex = d->m_profile->d->componentIndex;
for (auto component : components) {
if (auto action = component->getUpdateAction()) {
auto visitor = overload{
[&component](const UpdateActionChangeVerison& cv) {
if (!component) {
continue;
}
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->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());
versionList->waitToLoad();
if (versionList) {
@ -575,12 +595,33 @@ void ComponentUpdateTask::performUpdateActions()
.arg(component->getName(), lrc.parentName, lrc.version));
}
} else {
component->addComponentProblem(ProblemSeverity::Error,
component->addComponentProblem(
ProblemSeverity::Error,
QObject::tr("No version list in metadata index for %1").arg(component->getID()));
}
},
[this, &component](const UpdateActionRemove&) { d->m_profile->remove(component->getID()); },
[this, &component, &addedActions](const UpdateActionImportantChanged&) {
[&component, &instance, &toRemove](const UpdateActionRemove&) {
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());
for (auto comp : linked) {
if (comp->isCustom()) {
@ -592,7 +633,7 @@ void ComponentUpdateTask::performUpdateActions()
if (parentReq != component->m_cachedRequires.end()) {
auto newVersion = parentReq->equalsVersion.isEmpty() ? parentReq->suggests : parentReq->equalsVersion;
if (!newVersion.isEmpty()) {
comp->setUpdateAction(UpdateAction{ UpdateActionChangeVerison{ newVersion } });
comp->setUpdateAction(UpdateAction{ UpdateActionChangeVersion{ newVersion } });
} else {
comp->setUpdateAction(UpdateAction{ UpdateActionLatestRecommendedCompatable{
component->getID(),
@ -609,10 +650,11 @@ void ComponentUpdateTask::performUpdateActions()
}
addedActions = true;
}
}
};
std::visit(visitor, *action);
} };
std::visit(visitor, action);
component->clearUpdateAction();
for (auto uid : toRemove) {
d->m_profile->remove(uid);
}
}
} while (addedActions);
@ -637,6 +679,15 @@ void ComponentUpdateTask::finalizeComponents()
reqComp->getProblemSeverity(),
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));
}
}
}
}