summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/installer/installer.pro6
-rw-r--r--src/libs/installer/packagemanagercore.cpp7
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp127
-rw-r--r--src/libs/installer/packagemanagercore_p.h9
-rw-r--r--src/libs/installer/uninstallercalculator.cpp158
-rw-r--r--src/libs/installer/uninstallercalculator.h75
-rw-r--r--tests/auto/installer/solver/tst_solver.cpp52
7 files changed, 323 insertions, 111 deletions
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro
index 290f78d37..448b4acc4 100644
--- a/src/libs/installer/installer.pro
+++ b/src/libs/installer/installer.pro
@@ -121,7 +121,8 @@ HEADERS += packagemanagercore.h \
fileio.h \
binarycontent.h \
binarylayout.h \
- installercalculator.h
+ installercalculator.h \
+ uninstallercalculator.h
SOURCES += packagemanagercore.cpp \
packagemanagercore_p.cpp \
@@ -191,7 +192,8 @@ SOURCES += packagemanagercore.cpp \
fileio.cpp \
binarycontent.cpp \
binarylayout.cpp \
- installercalculator.cpp
+ installercalculator.cpp \
+ uninstallercalculator.cpp
RESOURCES += resources/patch_file_lists.qrc \
resources/installer.qrc
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index a9e7f7216..93a97ccc6 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -57,6 +57,7 @@
#include "settings.h"
#include "utils.h"
#include "installercalculator.h"
+#include "uninstallercalculator.h"
#include <productkeycheck.h>
@@ -1269,9 +1270,9 @@ bool PackageManagerCore::calculateComponentsToUninstall() const
componentsToUninstall.append(component);
}
- d->m_componentsToUninstall.clear();
+ d->clearUninstallerCalculator();
d->storeCheckState();
- result = d->appendComponentsToUninstall(componentsToUninstall);
+ result = d->uninstallerCalculator()->appendComponentsToUninstall(componentsToUninstall);
}
emit finishedCalculateComponentsToUninstall();
return result;
@@ -1282,7 +1283,7 @@ bool PackageManagerCore::calculateComponentsToUninstall() const
*/
QList<Component *> PackageManagerCore::componentsToUninstall() const
{
- return d->m_componentsToUninstall.toList();
+ return d->uninstallerCalculator()->componentsToUninstall().toList();
}
QString PackageManagerCore::componentsToInstallError() const
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index ca9aca625..5b31255e5 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -50,7 +50,6 @@
#include "errors.h"
#include "fileio.h"
#include "remotefileengine.h"
-#include "globals.h"
#include "graph.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
@@ -60,6 +59,7 @@
#include "qsettingswrapper.h"
#include "remoteclient.h"
#include "installercalculator.h"
+#include "uninstallercalculator.h"
#include "kdselfrestarter.h"
#include "kdupdaterfiledownloaderfactory.h"
@@ -198,6 +198,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
, m_componentScriptEngine(0)
, m_controlScriptEngine(0)
, m_installerCalculator(0)
+ , m_uninstallerCalculator(0)
, m_proxyFactory(0)
, m_defaultModel(0)
, m_updaterModel(0)
@@ -226,6 +227,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_componentScriptEngine(0)
, m_controlScriptEngine(0)
, m_installerCalculator(0)
+ , m_uninstallerCalculator(0)
, m_proxyFactory(0)
, m_defaultModel(0)
, m_updaterModel(0)
@@ -269,6 +271,7 @@ PackageManagerCorePrivate::~PackageManagerCorePrivate()
clearAllComponentLists();
clearUpdaterComponentLists();
clearInstallerCalculator();
+ clearUninstallerCalculator();
qDeleteAll(m_ownedOperations);
qDeleteAll(m_performedOperationsOld);
@@ -497,6 +500,30 @@ InstallerCalculator *PackageManagerCorePrivate::installerCalculator() const
return m_installerCalculator;
}
+void PackageManagerCorePrivate::clearUninstallerCalculator()
+{
+ delete m_uninstallerCalculator;
+ m_uninstallerCalculator = 0;
+}
+
+UninstallerCalculator *PackageManagerCorePrivate::uninstallerCalculator() const
+{
+ if (!m_uninstallerCalculator) {
+ PackageManagerCorePrivate *const pmcp = const_cast<PackageManagerCorePrivate *> (this);
+
+ QList<Component*> installedComponents;
+ foreach (const QString &name, pmcp->localInstalledPackages().keys()) {
+ if (Component *component = m_core->componentByName(name)) {
+ if (!component->uninstallationRequested())
+ installedComponents.append(component);
+ }
+ }
+
+ pmcp->m_uninstallerCalculator = new UninstallerCalculator(installedComponents);
+ }
+ return m_uninstallerCalculator;
+}
+
void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params)
{
m_coreCheckedHash.clear();
@@ -2178,104 +2205,6 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
return m_updateSourcesAdded;
}
-bool PackageManagerCorePrivate::appendComponentToUninstall(Component *component)
-{
- // remove all already resolved dependees
- QSet<Component *> dependees = m_core->dependees(component).toSet().subtract(m_componentsToUninstall);
- if (dependees.isEmpty()) {
- component->setCheckState(Qt::Unchecked);
- m_componentsToUninstall.insert(component);
- return true;
- }
-
- QSet<Component *> dependeesToResolve;
- foreach (Component *dependee, dependees) {
- if (dependee->isInstalled()) {
- // keep them as already resolved
- dependee->setCheckState(Qt::Unchecked);
- m_componentsToUninstall.insert(dependee);
- // gather possible dependees, keep them to resolve it later
- dependeesToResolve.unite(m_core->dependees(dependee).toSet());
- }
- }
-
- bool allResolved = true;
- foreach (Component *dependee, dependeesToResolve)
- allResolved &= appendComponentToUninstall(dependee);
-
- return allResolved;
-}
-
-bool PackageManagerCorePrivate::appendComponentsToUninstall(const QList<Component*> &components)
-{
- if (components.isEmpty()) {
- qDebug() << "components list is empty in" << Q_FUNC_INFO;
- return true;
- }
-
- bool allResolved = true;
- foreach (Component *component, components) {
- if (component->isInstalled()) {
- component->setCheckState(Qt::Unchecked);
- m_componentsToUninstall.insert(component);
- allResolved &= appendComponentToUninstall(component);
- }
- }
-
- QSet<Component*> installedComponents;
- foreach (const QString &name, localInstalledPackages().keys()) {
- if (Component *component = m_core->componentByName(name)) {
- if (!component->uninstallationRequested())
- installedComponents.insert(component);
- }
- }
-
- QList<Component*> autoDependOnList;
- if (allResolved) {
- // All regular dependees are resolved. Now we are looking for auto depend on components.
- foreach (Component *component, installedComponents) {
- // If a components is installed and not yet scheduled for un-installation, check for auto depend.
- if (component->isInstalled() && !m_componentsToUninstall.contains(component)) {
- QStringList autoDependencies = component->autoDependencies();
- if (autoDependencies.isEmpty())
- continue;
-
- // This code needs to be enabled once the scripts use isInstalled, installationRequested and
- // uninstallationRequested...
- if (autoDependencies.first().compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) {
- //QScriptValue valueFromScript;
- //try {
- // valueFromScript = callScriptMethod(QLatin1String("isAutoDependOn"));
- //} catch (const Error &error) {
- // // keep the component, should do no harm
- // continue;
- //}
-
- //if (valueFromScript.isValid() && !valueFromScript.toBool())
- // autoDependOnList.append(component);
- continue;
- }
-
- foreach (Component *c, installedComponents) {
- const QString replaces = c->value(scReplaces);
- const QStringList possibleNames = replaces.split(QInstaller::commaRegExp(),
- QString::SkipEmptyParts) << c->name();
- foreach (const QString &possibleName, possibleNames)
- autoDependencies.removeAll(possibleName);
- }
-
- // A component requested auto installation, keep it to resolve their dependencies as well.
- if (!autoDependencies.isEmpty())
- autoDependOnList.append(component);
- }
- }
- }
-
- if (!autoDependOnList.isEmpty())
- return appendComponentsToUninstall(autoDependOnList);
- return allResolved;
-}
-
void PackageManagerCorePrivate::restoreCheckState()
{
if (m_coreCheckedHash.isEmpty())
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 06ccaf50d..cf686f0e0 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -70,6 +70,7 @@ class ScriptEngine;
class ComponentModel;
class TempDirDeleter;
class InstallerCalculator;
+class UninstallerCalculator;
/*
The default configuration interface implementation does call QSettings to save files for later deletion,
@@ -149,6 +150,9 @@ public:
void clearInstallerCalculator();
InstallerCalculator *installerCalculator() const;
+ void clearUninstallerCalculator();
+ UninstallerCalculator *uninstallerCalculator() const;
+
bool runInstaller();
bool isInstaller() const;
@@ -191,9 +195,6 @@ public:
void installComponent(Component *component, double progressOperationSize,
bool adminRightsGained = false);
- bool appendComponentToUninstall(Component *component);
- bool appendComponentsToUninstall(const QList<Component*> &components);
-
signals:
void installationStarted();
void installationFinished();
@@ -273,8 +274,8 @@ private:
QHash<QString, QPair<Component*, Component*> > m_componentsToReplaceUpdaterMode;
InstallerCalculator *m_installerCalculator;
+ UninstallerCalculator *m_uninstallerCalculator;
- QSet<Component*> m_componentsToUninstall;
FileDownloaderProxyFactory *m_proxyFactory;
ComponentModel *m_defaultModel;
diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp
new file mode 100644
index 000000000..0266bbb06
--- /dev/null
+++ b/src/libs/installer/uninstallercalculator.cpp
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "uninstallercalculator.h"
+
+#include "component.h"
+#include "packagemanagercore.h"
+#include "globals.h"
+
+#include <QDebug>
+
+namespace QInstaller {
+
+UninstallerCalculator::UninstallerCalculator(const QList<Component *> &installedComponents)
+ : m_installedComponents(installedComponents)
+{
+}
+
+QSet<Component *> UninstallerCalculator::componentsToUninstall() const
+{
+ return m_componentsToUninstall;
+}
+
+bool UninstallerCalculator::appendComponentToUninstall(Component *component)
+{
+ if (!component)
+ return false;
+
+ PackageManagerCore *core = component->packageManagerCore();
+ // remove all already resolved dependees
+ QSet<Component *> dependees = core->dependees(component).toSet()
+ .subtract(m_componentsToUninstall);
+ if (dependees.isEmpty()) {
+ component->setCheckState(Qt::Unchecked);
+ m_componentsToUninstall.insert(component);
+ return true;
+ }
+
+ QSet<Component *> dependeesToResolve;
+ foreach (Component *dependee, dependees) {
+ if (dependee->isInstalled()) {
+ // keep them as already resolved
+ dependee->setCheckState(Qt::Unchecked);
+ m_componentsToUninstall.insert(dependee);
+ // gather possible dependees, keep them to resolve it later
+ dependeesToResolve.unite(core->dependees(dependee).toSet());
+ }
+ }
+
+ bool allResolved = true;
+ foreach (Component *dependee, dependeesToResolve)
+ allResolved &= appendComponentToUninstall(dependee);
+
+ return allResolved;
+}
+
+bool UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components)
+{
+ if (components.isEmpty()) {
+ qDebug() << "components list is empty in" << Q_FUNC_INFO;
+ return true;
+ }
+
+ bool allResolved = true;
+ foreach (Component *component, components) {
+ if (component->isInstalled()) {
+ component->setCheckState(Qt::Unchecked);
+ m_componentsToUninstall.insert(component);
+ allResolved &= appendComponentToUninstall(component);
+ }
+ }
+
+ QList<Component*> autoDependOnList;
+ if (allResolved) {
+ // All regular dependees are resolved. Now we are looking for auto depend on components.
+ foreach (Component *component, m_installedComponents) {
+ // If a components is installed and not yet scheduled for un-installation, check for auto depend.
+ if (component->isInstalled() && !m_componentsToUninstall.contains(component)) {
+ QStringList autoDependencies = component->autoDependencies();
+ if (autoDependencies.isEmpty())
+ continue;
+
+ // This code needs to be enabled once the scripts use isInstalled, installationRequested and
+ // uninstallationRequested...
+ if (autoDependencies.first().compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) {
+ //QScriptValue valueFromScript;
+ //try {
+ // valueFromScript = callScriptMethod(QLatin1String("isAutoDependOn"));
+ //} catch (const Error &error) {
+ // // keep the component, should do no harm
+ // continue;
+ //}
+
+ //if (valueFromScript.isValid() && !valueFromScript.toBool())
+ // autoDependOnList.append(component);
+ continue;
+ }
+
+ foreach (Component *c, m_installedComponents) {
+ const QString replaces = c->value(scReplaces);
+ const QStringList possibleNames = replaces.split(QInstaller::commaRegExp(),
+ QString::SkipEmptyParts) << c->name();
+ foreach (const QString &possibleName, possibleNames)
+ autoDependencies.removeAll(possibleName);
+ }
+
+ // A component requested auto installation, keep it to resolve their dependencies as well.
+ if (!autoDependencies.isEmpty())
+ autoDependOnList.append(component);
+ }
+ }
+ }
+
+ if (!autoDependOnList.isEmpty())
+ return appendComponentsToUninstall(autoDependOnList);
+ return allResolved;
+}
+
+
+} // namespace QInstaller
diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h
new file mode 100644
index 000000000..e5da7898e
--- /dev/null
+++ b/src/libs/installer/uninstallercalculator.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+#ifndef UNINSTALLERCALCULATOR_H
+#define UNINSTALLERCALCULATOR_H
+
+#include "installer_global.h"
+
+#include <QHash>
+#include <QList>
+#include <QSet>
+#include <QString>
+
+namespace QInstaller {
+
+class Component;
+
+class INSTALLER_EXPORT UninstallerCalculator
+{
+public:
+ UninstallerCalculator(const QList<Component *> &installedComponents);
+
+ QSet<Component*> componentsToUninstall() const;
+
+ bool appendComponentsToUninstall(const QList<Component*> &components);
+
+private:
+
+ bool appendComponentToUninstall(Component *component);
+
+ QList<Component *> m_installedComponents;
+ QSet<Component *> m_componentsToUninstall;
+};
+
+}
+
+
+#endif // UNINSTALLERCALCULATOR_H
diff --git a/tests/auto/installer/solver/tst_solver.cpp b/tests/auto/installer/solver/tst_solver.cpp
index 3c1530a1c..b2a932419 100644
--- a/tests/auto/installer/solver/tst_solver.cpp
+++ b/tests/auto/installer/solver/tst_solver.cpp
@@ -42,6 +42,7 @@
#include <component.h>
#include <graph.h>
#include <installercalculator.h>
+#include <uninstallercalculator.h>
#include <packagemanagercore.h>
#include <QTest>
@@ -149,7 +150,7 @@ private slots:
qPrintable(cycle.first.data()));
}
- void resolve_data()
+ void resolveInstaller_data()
{
QTest::addColumn<PackageManagerCore *>("core");
QTest::addColumn<QList<Component *> >("selectedComponents");
@@ -168,7 +169,7 @@ private slots:
core->appendRootComponent(componentA);
core->appendRootComponent(componentB);
- QTest::newRow("Simple resolved") << core
+ QTest::newRow("Installer resolved") << core
<< (QList<Component *>() << componentB)
<< (QList<Component *>() << componentAB << componentB)
<< (QList<int>()
@@ -176,7 +177,7 @@ private slots:
<< InstallerCalculator::Resolved);
}
- void resolve()
+ void resolveInstaller()
{
QFETCH(PackageManagerCore *, core);
QFETCH(QList<Component *> , selectedComponents);
@@ -194,6 +195,51 @@ private slots:
}
delete core;
}
+
+ void resolveUninstaller_data()
+ {
+ QTest::addColumn<PackageManagerCore *>("core");
+ QTest::addColumn<QList<Component *> >("selectedToUninstall");
+ QTest::addColumn<QList<Component *> >("installedComponents");
+ QTest::addColumn<QSet<Component *> >("expectedResult");
+
+ PackageManagerCore *core = new PackageManagerCore();
+ core->setPackageManager();
+ NamedComponent *componentA = new NamedComponent(core, QLatin1String("A"));
+ NamedComponent *componentAA = new NamedComponent(core, QLatin1String("A.A"));
+ NamedComponent *componentAB = new NamedComponent(core, QLatin1String("A.B"));
+ componentA->appendComponent(componentAA);
+ componentA->appendComponent(componentAB);
+ NamedComponent *componentB = new NamedComponent(core, QLatin1String("B"));
+ componentB->addDependency(QLatin1String("A.B"));
+ core->appendRootComponent(componentA);
+ core->appendRootComponent(componentB);
+
+ componentA->setInstalled();
+ componentB->setInstalled();
+ componentAB->setInstalled();
+
+ QTest::newRow("Uninstaller resolved") << core
+ << (QList<Component *>() << componentAB)
+ << (QList<Component *>() << componentA << componentB << componentAB)
+ << (QSet<Component *>() << componentAB << componentB);
+ }
+
+ void resolveUninstaller()
+ {
+ QFETCH(PackageManagerCore *, core);
+ QFETCH(QList<Component *> , selectedToUninstall);
+ QFETCH(QList<Component *> , installedComponents);
+ QFETCH(QSet<Component *> , expectedResult);
+
+ UninstallerCalculator calc(installedComponents);
+ calc.appendComponentsToUninstall(selectedToUninstall);
+ QSet<Component *> result = calc.componentsToUninstall();
+
+ QCOMPARE(result.count(), expectedResult.count());
+ QCOMPARE(result, expectedResult);
+ delete core;
+ }
};
QTEST_MAIN(tst_Solver)