summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatja Marttila <katja.marttila@qt.io>2022-03-18 14:13:24 +0200
committerKatja Marttila <katja.marttila@qt.io>2022-03-24 09:15:33 +0200
commitac1637b8976d7d85ac42f308c4be6de97dcf86cb (patch)
tree601dc434e0d8ae225758c2603fe4992a3b83418f
parent449afefe542d3411de4bdacd068c1116ec10779c (diff)
Add install reason why component is uninstalled
In details view uninstallable and installable components are listed. For installable components a reason is shown why the component is installed. Added similar kind of message for uninstallable components as well. Task-number: QTIFW-2581 Change-Id: Idbf31200793a6c89a4ed4a6fc115f49889b5f9b5 Reviewed-by: Arttu Tarkiainen <arttu.tarkiainen@qt.io>
-rw-r--r--src/libs/installer/packagemanagercore.cpp34
-rw-r--r--src/libs/installer/packagemanagercore.h1
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp2
-rw-r--r--src/libs/installer/uninstallercalculator.cpp53
-rw-r--r--src/libs/installer/uninstallercalculator.h16
-rw-r--r--tests/auto/installer/solver/tst_solver.cpp26
6 files changed, 119 insertions, 13 deletions
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 918b01ad6..363609a92 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -2107,7 +2107,6 @@ QList<Component*> PackageManagerCore::orderedComponentsToInstall() const
bool PackageManagerCore::calculateComponents(QString *displayString)
{
QString htmlOutput;
- QString lastInstallReason;
if (!calculateComponentsToUninstall() ||
!calculateComponentsToInstall()) {
htmlOutput.append(QString::fromLatin1("<h2><font color=\"red\">%1</font></h2><ul>")
@@ -2125,13 +2124,24 @@ bool PackageManagerCore::calculateComponents(QString *displayString)
QList<Component*> componentsToRemove = componentsToUninstall();
if (!componentsToRemove.isEmpty()) {
+ QMap<QString, QStringList> orderedUninstallReasons;
htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(tr("Components about to "
- "be removed.")));
- foreach (Component *component, componentsToRemove)
- htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name()));
+ "be removed:")));
+ foreach (Component *component, componentsToRemove) {
+ const QString reason = uninstallReason(component);
+ QStringList value = orderedUninstallReasons.value(reason);
+ orderedUninstallReasons.insert(reason, value << component->name());
+ }
+ for (auto &reason : orderedUninstallReasons.keys()) {
+ htmlOutput.append(QString::fromLatin1("<h4>%1</h4><ul>").arg(reason));
+ foreach (const QString componentName, orderedUninstallReasons.value(reason))
+ htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(componentName));
+ htmlOutput.append(QLatin1String("</ul>"));
+ }
htmlOutput.append(QLatin1String("</ul>"));
}
+ QString lastInstallReason;
foreach (Component *component, orderedComponentsToInstall()) {
const QString reason = installReason(component);
if (lastInstallReason != reason) {
@@ -2201,6 +2211,22 @@ QString PackageManagerCore::installReason(Component *component) const
}
/*!
+ Returns the reason why \a component needs to be uninstalled:
+
+ \list
+ \li The component was scheduled for uninstallation.
+ \li The component was replaced by another component.
+ \li The component is virtual and its dependencies are uninstalled.
+ \li The components dependencies are uninstalled.
+ \li The components autodependencies are uninstalled.
+ \endlist
+*/
+QString PackageManagerCore::uninstallReason(Component *component) const
+{
+ return d->uninstallerCalculator()->uninstallReason(component);
+}
+
+/*!
Returns a list of components that depend on \a _component. The list can be
empty.
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index 012c57d58..523661797 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -240,6 +240,7 @@ public:
QString componentsToInstallError() const;
QString installReason(Component *component) const;
+ QString uninstallReason(Component *component) const;
QList<Component*> dependees(const Component *component) const;
QList<Component*> installDependants(const Component *component) const;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 4aaa27cfd..464a68109 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -2792,6 +2792,8 @@ void PackageManagerCorePrivate::calculateUninstallComponents()
QPair<Component*, Component*> comp = componentsToReplace().value(component->name());
if (comp.first) {
if (comp.first->isSelectedForInstallation() || comp.first->updateRequested()) {
+ uninstallerCalculator()->insertUninstallReason(component,
+ UninstallerCalculator::Replaced, comp.first->name());
selectedComponentsToUninstall.append(comp.second);
}
}
diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp
index 7d5ce9e2a..a8c47e523 100644
--- a/src/libs/installer/uninstallercalculator.cpp
+++ b/src/libs/installer/uninstallercalculator.cpp
@@ -66,8 +66,10 @@ void UninstallerCalculator::appendComponentToUninstall(Component *component)
QSet<Component *> dependees = QSet<Component *>(dependeesList.begin(),
dependeesList.end()).subtract(m_componentsToUninstall);
- foreach (Component *dependee, dependees)
+ foreach (Component *dependee, dependees) {
appendComponentToUninstall(dependee);
+ insertUninstallReason(dependee, UninstallerCalculator::Dependent, component->name());
+ }
m_componentsToUninstall.insert(component);
}
@@ -119,6 +121,7 @@ void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*>
// A component requested auto uninstallation, keep it to resolve their dependencies as well.
if (!autoDependencies.isEmpty()) {
autoDependOnList.append(component);
+ insertUninstallReason(component, UninstallerCalculator::AutoDependent, autoDependencies.join(QLatin1String(", ")));
component->setInstallAction(ComponentModelHelper::AutodependUninstallation);
}
}
@@ -130,6 +133,50 @@ void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*>
appendVirtualComponentsToUninstall();
}
+void UninstallerCalculator::insertUninstallReason(Component *component, UninstallReasonType uninstallReason,
+ const QString &referencedComponentName)
+{
+ // keep the first reason
+ if (m_toUninstallComponentIdReasonHash.contains(component->name()))
+ return;
+ m_toUninstallComponentIdReasonHash.insert(component->name(),
+ qMakePair(uninstallReason, referencedComponentName));
+}
+
+QString UninstallerCalculator::uninstallReason(Component *component) const
+{
+ UninstallerCalculator::UninstallReasonType reason = uninstallReasonType(component);
+ switch (reason) {
+ case Selected:
+ return QCoreApplication::translate("UninstallerCalculator",
+ "Deselected Components:");
+ case Replaced:
+ return QCoreApplication::translate("UninstallerCalculator", "Components replaced "
+ "by \"%1\":").arg(uninstallReasonReferencedComponent(component));
+ case VirtualDependent:
+ return QCoreApplication::translate("UninstallerCalculator",
+ "Removing virtual components without existing dependencies:");
+ case Dependent:
+ return QCoreApplication::translate("UninstallerCalculator", "Components "
+ "dependency \"%1\" removed:").arg(uninstallReasonReferencedComponent(component));
+ case AutoDependent:
+ return QCoreApplication::translate("UninstallerCalculator", "Components "
+ "autodependency \"%1\" removed:").arg(uninstallReasonReferencedComponent(component));
+ }
+ return QString();
+}
+
+UninstallerCalculator::UninstallReasonType UninstallerCalculator::uninstallReasonType(Component *c) const
+{
+ return m_toUninstallComponentIdReasonHash.value(c->name()).first;
+}
+
+QString UninstallerCalculator::uninstallReasonReferencedComponent(Component *component) const
+{
+ return m_toUninstallComponentIdReasonHash.value(component->name()).second;
+}
+
+
void UninstallerCalculator::appendVirtualComponentsToUninstall()
{
QList<Component*> unneededVirtualList;
@@ -148,8 +195,10 @@ void UninstallerCalculator::appendVirtualComponentsToUninstall()
break;
}
}
- if (!required)
+ if (!required) {
unneededVirtualList.append(component);
+ insertUninstallReason(component, UninstallerCalculator::VirtualDependent);
+ }
}
}
diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h
index fb7035d4e..c20616e93 100644
--- a/src/libs/installer/uninstallercalculator.h
+++ b/src/libs/installer/uninstallercalculator.h
@@ -43,11 +43,26 @@ class PackageManagerCore;
class INSTALLER_EXPORT UninstallerCalculator
{
public:
+ enum UninstallReasonType
+ {
+ Selected, // "Deselected Component(s)"
+ Replaced, // "Component(s) replaced by other components"
+ VirtualDependent, // "No dependencies to virtual component"
+ Dependent, // "Removed as dependency component is removed"
+ AutoDependent // "Removed as autodependency component is removed"
+ };
+
UninstallerCalculator(const QList<Component *> &installedComponents, PackageManagerCore *core);
QSet<Component*> componentsToUninstall() const;
void appendComponentsToUninstall(const QList<Component*> &components);
+ void insertUninstallReason(Component *component,
+ UninstallReasonType installReasonType,
+ const QString &referencedComponentName = QString());
+ QString uninstallReason(Component *component) const;
+ UninstallerCalculator::UninstallReasonType uninstallReasonType(Component *c) const;
+ QString uninstallReasonReferencedComponent(Component *component) const;
private:
@@ -57,6 +72,7 @@ private:
QList<Component *> m_installedComponents;
QSet<Component *> m_componentsToUninstall;
PackageManagerCore *m_core;
+ QHash<QString, QPair<UninstallReasonType, QString> > m_toUninstallComponentIdReasonHash;
};
}
diff --git a/tests/auto/installer/solver/tst_solver.cpp b/tests/auto/installer/solver/tst_solver.cpp
index 2f4e17855..5e499da2d 100644
--- a/tests/auto/installer/solver/tst_solver.cpp
+++ b/tests/auto/installer/solver/tst_solver.cpp
@@ -39,6 +39,9 @@
using namespace QInstaller;
typedef QMap<Component *, QStringList> ComponentToStringList;
+typedef QList<QPair<Component *, UninstallerCalculator::UninstallReasonType>> UninstallReasonList;
+
+Q_DECLARE_METATYPE(UninstallReasonList)
class Data {
public:
@@ -218,7 +221,6 @@ private slots:
<< (QList<Component *>() << componentA)
<< (QList<Component *>());
}
-
}
void unresolvedDependencyVersion()
@@ -242,7 +244,9 @@ private slots:
QTest::addColumn<QList<Component *> >("selectedToUninstall");
QTest::addColumn<QList<Component *> >("installedComponents");
QTest::addColumn<QSet<Component *> >("expectedResult");
+ QTest::addColumn<UninstallReasonList >("uninstallReasons");
+ UninstallReasonList uninstallReasonList;
PackageManagerCore *core = new PackageManagerCore();
core->setPackageManager();
NamedComponent *componentA = new NamedComponent(core, QLatin1String("A"));
@@ -259,11 +263,15 @@ private slots:
componentB->setInstalled();
componentAB->setInstalled();
+ uninstallReasonList.append(qMakePair(componentAB, UninstallerCalculator::Selected));
+ uninstallReasonList.append(qMakePair(componentB, UninstallerCalculator::Dependent));
QTest::newRow("Uninstaller resolved") << core
<< (QList<Component *>() << componentAB)
<< (QList<Component *>() << componentA << componentB)
- << (QSet<Component *>() << componentAB << componentB);
+ << (QSet<Component *>() << componentAB << componentB)
+ << (uninstallReasonList);
+ uninstallReasonList.clear();
core = new PackageManagerCore();
core->setPackageManager();
NamedComponent *compA = new NamedComponent(core, QLatin1String("A"));
@@ -277,10 +285,13 @@ private slots:
compA->setInstalled();
compB->setInstalled();
+ uninstallReasonList.append(qMakePair(compA, UninstallerCalculator::Selected));
+ uninstallReasonList.append(qMakePair(compB, UninstallerCalculator::Dependent));
QTest::newRow("Cascade dependencies") << core
<< (QList<Component *>() << compA)
<< (QList<Component *>() << compB)
- << (QSet<Component *>() << compA << compB);
+ << (QSet<Component *>() << compA << compB)
+ << (uninstallReasonList);
}
void resolveUninstaller()
@@ -289,17 +300,19 @@ private slots:
QFETCH(QList<Component *> , selectedToUninstall);
QFETCH(QList<Component *> , installedComponents);
QFETCH(QSet<Component *> , expectedResult);
-
+ QFETCH(UninstallReasonList, uninstallReasons);
UninstallerCalculator calc(installedComponents, core);
calc.appendComponentsToUninstall(selectedToUninstall);
QSet<Component *> result = calc.componentsToUninstall();
-
+ for (auto pair : uninstallReasons) {
+ UninstallerCalculator::UninstallReasonType type = calc.uninstallReasonType(pair.first);
+ QCOMPARE(pair.second, type);
+ }
QCOMPARE(result.count(), expectedResult.count());
QCOMPARE(result, expectedResult);
delete core;
}
-
void checkComponent_data()
{
QTest::addColumn<QList<Component *> >("componentsToCheck");
@@ -342,7 +355,6 @@ private slots:
QTest::newRow("AutoDepend and dependency")
<< (QList<Component *>() << componentC << componentD << componentE)
<< result;
-
}
void checkComponent()