From b8877d4c0e09445f8b88797cc7da1f6a38764a41 Mon Sep 17 00:00:00 2001 From: Katja Marttila Date: Thu, 3 Nov 2022 18:08:15 +0200 Subject: Fix virtual component uninstallation Virtual components were still wrongly calculated for uninstall depending on which order the tree was clicked and whether the component had dependencies to already installed components or components about to be installed. Change-Id: I624fd1139d15d5e16c81365064dcea2392dc13b1 Reviewed-by: Arttu Tarkiainen --- src/libs/installer/packagemanagercore.cpp | 70 +++++++++++++++++++--------- src/libs/installer/packagemanagercore.h | 3 +- src/libs/installer/uninstallercalculator.cpp | 55 ++++++++++------------ src/libs/installer/uninstallercalculator.h | 3 +- 4 files changed, 77 insertions(+), 54 deletions(-) (limited to 'src/libs/installer') diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index 655d9cc7e..d0d635355 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -644,7 +644,7 @@ void PackageManagerCore::calculateUserSelectedComponentsToInstall(const QListisSelected() && installComponent->isInstalled() && !d->installerCalculator()->orderedComponentsToInstall().contains(installComponent)) { componentsToInstall.append(installComponent); @@ -669,6 +669,13 @@ void PackageManagerCore::calculateUserSelectedComponentsToInstall(const QListuninstallerCalculator()->appendComponentsToUninstall(componentsToUnInstall, false); } d->uninstallerCalculator()->removeComponentsFromUnInstall(componentsToInstall); + if (componentsToUnInstall.isEmpty() && !componentsToInstall.isEmpty()) { + // There are no new components to be uninstalled but there + // are new components to be installed which might have virtual + // dependences to components which are already selected for uninstall. + // We need to remove those components from uninstall. + d->uninstallerCalculator()->appendVirtualComponentsToUninstall(true); + } d->updateComponentCheckedState(); } @@ -2395,44 +2402,65 @@ QList PackageManagerCore::dependees(const Component *_component) con } /*! - Returns a list of components that depend on \a component. The list can be - empty. Dependendants are calculated from components which are about to be updated, - if no update is requested then the dependant is calculated from installed packages. - - \note Automatic dependencies are not resolved. + Returns true if components which are about to be installed or updated + are dependent on \a component. */ -QList PackageManagerCore::installDependants(const Component *component) const +bool PackageManagerCore::isDependencyForRequestedComponent(const Component *component) const { if (!component) - return QList(); + return false; const QList availableComponents = components(ComponentType::All); if (availableComponents.isEmpty()) - return QList(); + return false; - QList dependants; QString name; QString version; - foreach (Component *availableComponent, availableComponents) { - if (isUpdater() && availableComponent->updateRequested()) { + for (Component *availableComponent : availableComponents) { + if (!availableComponent) { + continue; + } + // 1. In updater mode, component to be updated might have new dependencies + // Check if the dependency is still needed + // 2. If component is selected and not installed, check if the dependency is needed + if (availableComponent->isSelected() + && ((isUpdater() && availableComponent->isInstalled()) + || (isPackageManager() && !availableComponent->isInstalled()))) { const QStringList &dependencies = availableComponent->dependencies(); foreach (const QString &dependency, dependencies) { parseNameAndVersion(dependency, &name, &version); if (componentMatches(component, name, version)) { - dependants.append(availableComponent); + return true; } } - } else { - KDUpdater::LocalPackage localPackage = d->m_localPackageHub->packageInfo(availableComponent->name()); - foreach (const QString &dependency, localPackage.dependencies) { - parseNameAndVersion(dependency, &name, &version); - if (componentMatches(component, name, version)) { - dependants.append(availableComponent); - } + } + } + return false; +} + + +/*! + Returns a list of local components which are dependent on \a component. +*/ +QStringList PackageManagerCore::localDependenciesToComponent(const Component *component) const +{ + if (!component) + return QStringList(); + + QStringList dependents; + QString name; + QString version; + + QMap localPackages = d->m_localPackageHub->localPackages(); + for (const KDUpdater::LocalPackage &localPackage : qAsConst(localPackages)) { + for (const QString &dependency : localPackage.dependencies) { + parseNameAndVersion(dependency, &name, &version); + if (componentMatches(component, name, version)) { + dependents.append(localPackage.name); } } } - return dependants; + return dependents; } /*! diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h index 2c307971a..cd1bbf306 100644 --- a/src/libs/installer/packagemanagercore.h +++ b/src/libs/installer/packagemanagercore.h @@ -248,7 +248,8 @@ public: QString uninstallReason(Component *component) const; QList dependees(const Component *component) const; - QList installDependants(const Component *component) const; + bool isDependencyForRequestedComponent(const Component *component) const; + QStringList localDependenciesToComponent(const Component *component) const; ComponentModel *defaultComponentModel() const; ComponentModel *updaterComponentModel() const; diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp index d54b5c2ab..36d769207 100644 --- a/src/libs/installer/uninstallercalculator.cpp +++ b/src/libs/installer/uninstallercalculator.cpp @@ -72,12 +72,16 @@ void UninstallerCalculator::appendComponentToUninstall(Component *component, con const QStringList &dependencies = PackageManagerCore::parseNames(m_localDependencyComponentHash.value(component->name())); for (const QString &dependencyComponent : dependencies) { Component *depComponent = m_core->componentByName(dependencyComponent); - if (depComponent && depComponent->isInstalled() && !m_componentsToUninstall.contains(depComponent)) { - appendComponentToUninstall(depComponent, reverse); - insertUninstallReason(depComponent, UninstallerCalculator::Dependent, component->name()); - } else if (reverse) { - appendComponentToUninstall(depComponent, true); - } + if (!depComponent) + continue; + if (depComponent->isInstalled() && !m_componentsToUninstall.contains(depComponent)) { + appendComponentToUninstall(depComponent, reverse); + insertUninstallReason(depComponent, UninstallerCalculator::Dependent, component->name()); + } else if (reverse && depComponent->isVirtual()) { + // Remove from uninstall only hidden components, user + // can select other dependencies manually + appendComponentToUninstall(depComponent, true); + } } } if (reverse) { @@ -175,20 +179,8 @@ void UninstallerCalculator::appendVirtualComponentsToUninstall(const bool revers // Check for virtual components without dependees if (reverse) { for (Component *reverseFromUninstall : qAsConst(m_virtualComponentsForReverse)) { - if (m_componentsToUninstall.contains(reverseFromUninstall)) { - bool required = false; - // Check if installed or about to be updated -packages are dependant on the package - const QList installDependants = m_core->installDependants(reverseFromUninstall); - for (Component *dependant : installDependants) { - if (dependant->isInstalled() && !m_componentsToUninstall.contains(dependant)) { - required = true; - break; - } - } - if (required) { - unneededVirtualList.append(reverseFromUninstall); - } - } + if (m_componentsToUninstall.contains(reverseFromUninstall) && (isRequiredVirtualPackage(reverseFromUninstall))) + unneededVirtualList.append(reverseFromUninstall); } } else { for (const QString &componentName : qAsConst(m_localVirtualComponents)) { @@ -201,17 +193,7 @@ void UninstallerCalculator::appendVirtualComponentsToUninstall(const bool revers if (!virtualComponent->autoDependencies().isEmpty() || virtualComponent->forcedInstallation()) continue; - bool required = false; - // Check if installed or about to be updated -packages are dependant on the package - const QList installDependants = m_core->installDependants(virtualComponent); - for (Component *dependant : installDependants) { - if ((dependant->isInstalled() && !m_componentsToUninstall.contains(dependant)) - || m_core->orderedComponentsToInstall().contains(dependant)) { - required = true; - break; - } - } - if (!required) { + if (!isRequiredVirtualPackage(virtualComponent)) { unneededVirtualList.append(virtualComponent); m_virtualComponentsForReverse.append(virtualComponent); insertUninstallReason(virtualComponent, UninstallerCalculator::VirtualDependent); @@ -224,4 +206,15 @@ void UninstallerCalculator::appendVirtualComponentsToUninstall(const bool revers appendComponentsToUninstall(unneededVirtualList, reverse); } +bool UninstallerCalculator::isRequiredVirtualPackage(Component *component) +{ + const QStringList localInstallDependents = m_core->localDependenciesToComponent(component); + for (const QString &dependent : localInstallDependents) { + Component *comp = m_core->componentByName(dependent); + if (!m_componentsToUninstall.contains(comp)) { + return true; + } + } + return m_core->isDependencyForRequestedComponent(component); +} } // namespace QInstaller diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h index 76e32c6a6..57f2f926a 100644 --- a/src/libs/installer/uninstallercalculator.h +++ b/src/libs/installer/uninstallercalculator.h @@ -68,10 +68,11 @@ public: QString uninstallReason(Component *component) const; UninstallerCalculator::UninstallReasonType uninstallReasonType(Component *c) const; QString uninstallReasonReferencedComponent(Component *component) const; + bool isRequiredVirtualPackage(Component *component); + void appendVirtualComponentsToUninstall(const bool reverse); private: void appendComponentToUninstall(Component *component, const bool reverse); - void appendVirtualComponentsToUninstall(const bool reverse); QList m_installedComponents; QSet m_componentsToUninstall; -- cgit v1.2.3