diff options
author | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2023-01-10 14:17:21 +0200 |
---|---|---|
committer | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2023-01-26 15:25:41 +0200 |
commit | 50575212455fbd3109adbe92d8509fca3c51850a (patch) | |
tree | c098c162795ec071653ffe082dda782b61edb813 /src/libs/installer/uninstallercalculator.cpp | |
parent | f5750078a7a75e7ad7b0260b54236ee87f3900f9 (diff) |
Support detecting invalid dependency resolutions on component selection
IFW could already previously detect circular and missing dependencies by
running a precheck calculation when building the component tree.
However, there can be also cases of where the user selection results in
unsolvable changes to components.
One such case was the erroneous possibility to uninstall a component
marked with ForcedInstallation, if any of its dependencies was checkable
and the user unselected it for uninstallation.
Add support for reacting to such errors in the component tree view,
displaying a message box about the invalid dependency resolvation error,
and blocking further navigation until the component selection passes
the dependency calculations.
Also attempt some refactoring the related code to simplify the different
call sequences resulting in recalculation of the components.
Change-Id: I9dc78f858bd4be7932f89f8e14bbfd97fbd3a0f6
Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs/installer/uninstallercalculator.cpp')
-rw-r--r-- | src/libs/installer/uninstallercalculator.cpp | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp index 2f029630f..214e1124a 100644 --- a/src/libs/installer/uninstallercalculator.cpp +++ b/src/libs/installer/uninstallercalculator.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -30,6 +30,7 @@ #include "component.h" #include "packagemanagercore.h" +#include "globals.h" namespace QInstaller { @@ -55,35 +56,60 @@ QSet<Component *> UninstallerCalculator::componentsToUninstall() const return m_componentsToUninstall; } -void UninstallerCalculator::appendComponentToUninstall(Component *component) +QString UninstallerCalculator::componentsToUninstallError() const +{ + return m_componentsToUninstallError; +} + +bool UninstallerCalculator::appendComponentToUninstall(Component *component) { if (!component) - return; + return true; if (!component->isInstalled()) - return; + return true; if (m_localDependencyComponentHash.contains(component->name())) { const QStringList &dependencies = PackageManagerCore::parseNames(m_localDependencyComponentHash.value(component->name())); for (const QString &dependencyComponent : dependencies) { Component *depComponent = m_core->componentByName(dependencyComponent); - if (!depComponent) + if (!depComponent || !depComponent->isInstalled()) + continue; + + if (m_componentsToUninstall.contains(depComponent) + || m_core->orderedComponentsToInstall().contains(depComponent)) { + // Component is already selected for uninstall or update continue; - if (depComponent->isInstalled() && !m_componentsToUninstall.contains(depComponent) - && !m_core->orderedComponentsToInstall().contains(depComponent)) { - appendComponentToUninstall(depComponent); - insertUninstallReason(depComponent, UninstallerCalculator::Dependent, component->name()); } + + if (depComponent->isEssential() || depComponent->forcedInstallation()) { + const QString errorMessage = QCoreApplication::translate("InstallerCalculator", + "Impossible dependency resolution detected. Forced install component \"%1\" would be uninstalled " + "because its dependency \"%2\" is marked for uninstallation with reason: \"%3\".") + .arg(depComponent->name(), component->name(), uninstallReason(component)); + + qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; + m_componentsToUninstallError.append(errorMessage); + return false; + } + // Resolve also all cascading dependencies + if (!appendComponentToUninstall(depComponent)) + return false; + + insertUninstallReason(depComponent, UninstallerCalculator::Dependent, component->name()); } } m_componentsToUninstall.insert(component); + return true; } -void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components) +bool UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components) { - foreach (Component *component, components) - appendComponentToUninstall(component); + foreach (Component *component, components) { + if (!appendComponentToUninstall(component)) + return false; + } QList<Component*> autoDependOnList; // All regular dependees are resolved. Now we are looking for auto depend on components. @@ -109,6 +135,8 @@ void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> appendComponentsToUninstall(autoDependOnList); else appendVirtualComponentsToUninstall(); + + return true; } void UninstallerCalculator::insertUninstallReason(Component *component, const UninstallReasonType uninstallReason, |