diff options
author | Katja Marttila <katja.marttila@qt.io> | 2022-03-14 18:52:22 +0200 |
---|---|---|
committer | Katja Marttila <katja.marttila@qt.io> | 2022-03-22 10:44:04 +0200 |
commit | caee7332c4a049508c91fe23e3e3bed062a4815d (patch) | |
tree | 1ad9570f3443e95643854de456c24acf5da0ff1e | |
parent | 72939d59553ba00d50df72bfb28367595c5e7425 (diff) |
Fix replaced component uninstall4.3
Replaced component was uninstalled when installing other components
although no update or install was requested to the component. Fixes also
a bug when some components were uninstalled unvisible from user.
Task-number: QTIFW-2577
Change-Id: I6a7e9ce4a56991dfbdea53eb376d782dfb5d050a
Reviewed-by: Arttu Tarkiainen <arttu.tarkiainen@qt.io>
9 files changed, 138 insertions, 33 deletions
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index f0b923024..918b01ad6 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -570,7 +570,7 @@ void PackageManagerCore::cancelMetaInfoJob() void PackageManagerCore::componentsToInstallNeedsRecalculation() { d->clearInstallerCalculator(); - d->clearUninstallerCalculator(); + QList<Component*> selectedComponentsToInstall = componentsMarkedForInstallation(); d->m_componentsToInstallCalculated = @@ -578,13 +578,7 @@ void PackageManagerCore::componentsToInstallNeedsRecalculation() QList<Component *> componentsToInstall = d->installerCalculator()->orderedComponentsToInstall(); - QList<Component *> selectedComponentsToUninstall; - foreach (Component *component, components(ComponentType::All)) { - if (component->uninstallationRequested() && !selectedComponentsToInstall.contains(component)) - selectedComponentsToUninstall.append(component); - } - - d->uninstallerCalculator()->appendComponentsToUninstall(selectedComponentsToUninstall); + d->calculateUninstallComponents(); QSet<Component *> componentsToUninstall = d->uninstallerCalculator()->componentsToUninstall(); @@ -2165,20 +2159,8 @@ bool PackageManagerCore::calculateComponentsToUninstall() const { emit aboutCalculateComponentsToUninstall(); if (!isUpdater()) { - // hack to avoid removing needed dependencies - const QList<Component *> componentsToInstallList - = d->installerCalculator()->orderedComponentsToInstall(); - QSet<Component*> componentsToInstall(componentsToInstallList.begin(), componentsToInstallList.end()); - - QList<Component*> componentsToUninstall; - foreach (Component *component, components(ComponentType::All)) { - if (component->uninstallationRequested() && !componentsToInstall.contains(component)) - componentsToUninstall.append(component); - } - - d->clearUninstallerCalculator(); + d->calculateUninstallComponents(); d->storeCheckState(); - d->uninstallerCalculator()->appendComponentsToUninstall(componentsToUninstall); } emit finishedCalculateComponentsToUninstall(); return true; @@ -3873,7 +3855,7 @@ void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &co key = treeNameComponents->value(componentName); treeNameComponents->remove(componentName); } - Component *componentToReplace = components.take(key); + Component *componentToReplace = components.value(key); if (!componentToReplace) { // If a component replaces another component which is not existing in the // installer binary or the installed component list, just ignore it. This @@ -3882,8 +3864,21 @@ void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &co qCWarning(QInstaller::lcDeveloperBuild) << componentName << "- Does not exist in the repositories anymore."; continue; } - d->replacementDependencyComponents().append(componentToReplace); + // Remove the replaced component from instal tree if + // 1. Running installer (component is replaced by other component) + // 2. Replacement is already installed but replacable is not + // Do not remove the replaced component from install tree + // in updater so that would show as an update + // Also do not remove the replaced component from install tree + // if it is already installed together with replacable component, + // otherwise it does not match what we have defined in components.xml + if (!isUpdater() + && (isInstaller() || (it.key() && it.key()->isInstalled() && !componentToReplace->isInstalled()))) { + components.remove(key); + d->m_deletedReplacedComponents.append(componentToReplace); + } d->componentsToReplace().insert(componentName, qMakePair(it.key(), componentToReplace)); + d->replacementDependencyComponents().append(componentToReplace); } } } diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 154f2f638..4aaa27cfd 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -514,14 +514,11 @@ void PackageManagerCorePrivate::clearAllComponentLists() { QList<QInstaller::Component*> toDelete; - toDelete << m_rootComponents; + toDelete << m_rootComponents << m_deletedReplacedComponents; m_rootComponents.clear(); - m_rootDependencyReplacements.clear(); + m_deletedReplacedComponents.clear(); - const QList<QPair<Component*, Component*> > list = m_componentsToReplaceAllMode.values(); - for (int i = 0; i < list.count(); ++i) - toDelete << list.at(i).second; m_componentsToReplaceAllMode.clear(); m_componentsToInstallCalculated = false; @@ -2783,6 +2780,29 @@ bool PackageManagerCorePrivate::calculateComponentsAndRun() return false; } +void PackageManagerCorePrivate::calculateUninstallComponents() +{ + clearUninstallerCalculator(); + const QList<Component *> componentsToInstallList = installerCalculator()->orderedComponentsToInstall(); + QSet<Component*> componentsToInstall(componentsToInstallList.begin(), componentsToInstallList.end()); + + QList<Component *> selectedComponentsToUninstall; + foreach (Component* component, m_core->components(PackageManagerCore::ComponentType::Replacements)) { + // Uninstall the component if replacement is selected for install or update + QPair<Component*, Component*> comp = componentsToReplace().value(component->name()); + if (comp.first) { + if (comp.first->isSelectedForInstallation() || comp.first->updateRequested()) { + selectedComponentsToUninstall.append(comp.second); + } + } + } + foreach (Component *component, m_core->components(PackageManagerCore::ComponentType::AllNoReplacements)) { + if (component->uninstallationRequested() && !componentsToInstallList.contains(component)) + selectedComponentsToUninstall.append(component); + } + uninstallerCalculator()->appendComponentsToUninstall(selectedComponentsToUninstall); +} + bool PackageManagerCorePrivate::acceptLicenseAgreements() const { // Always skip for uninstaller diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index 73c378f43..d17a752f9 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -250,6 +250,7 @@ private: void findExecutablesRecursive(const QString &path, const QStringList &excludeFiles, QStringList *result); QStringList runningInstallerProcesses(const QStringList &exludeFiles); bool calculateComponentsAndRun(); + void calculateUninstallComponents(); bool acceptLicenseAgreements() const; bool askUserAcceptLicense(const QString &name, const QString &content) const; bool askUserConfirmCommand() const; @@ -294,6 +295,7 @@ private: void restoreCheckState(); void storeCheckState(); QHash<Component*, Qt::CheckState> m_coreCheckedHash; + QList<Component*> m_deletedReplacedComponents; }; } // namespace QInstaller diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/C/1.0.0content.7z b/tests/auto/installer/componentreplace/data/installPackagesRepository/C/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..d498f1900 --- /dev/null +++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/C/1.0.0content.7z diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml b/tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml index 6f02aad2b..e77207777 100644 --- a/tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml +++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml @@ -42,4 +42,14 @@ <DownloadableArchives>content.7z</DownloadableArchives> <SHA1>a10463141e30ce3fede9ac84bc52a07b0c5e919e</SHA1> </PackageUpdate> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C component</DisplayName> + <Description>Component C</Description> + <Version>1.0.0</Version> + <ReleaseDate>2021-01-01</ReleaseDate> + <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>a10463141e30ce3fede9ac84bc52a07b0c5e919e</SHA1> + </PackageUpdate> </Updates> diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..d498f1900 --- /dev/null +++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml index 5276637ed..e0fb351ff 100644 --- a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml +++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml @@ -43,4 +43,14 @@ <DownloadableArchives>content.7z</DownloadableArchives> <SHA1>4331736562fc047a4f47263be75f816298cbda30</SHA1> </PackageUpdate> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C component</DisplayName> + <Description>Component C</Description> + <Version>2.0.0</Version> + <ReleaseDate>2021-01-01</ReleaseDate> + <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>a10463141e30ce3fede9ac84bc52a07b0c5e919e</SHA1> + </PackageUpdate> </Updates> diff --git a/tests/auto/installer/componentreplace/settings.qrc b/tests/auto/installer/componentreplace/settings.qrc index 706cf91c6..ba1b0ab98 100644 --- a/tests/auto/installer/componentreplace/settings.qrc +++ b/tests/auto/installer/componentreplace/settings.qrc @@ -5,6 +5,7 @@ <file>data/installPackagesRepository/B/1.0.0content.7z</file> <file>data/installPackagesRepository/A.sub1/1.0.0content.7z</file> <file>data/installPackagesRepository/B.sub1/1.0.0content.7z</file> + <file>data/installPackagesRepository/C/1.0.0content.7z</file> <file>data/repositoryWithReplace/Updates.xml</file> <file>data/repositoryWithReplace/A/1.0.0content.7z</file> <file>data/repositoryWithReplace/B/2.0.0content.7z</file> @@ -25,5 +26,6 @@ <file>data/repositoryWithMultiReplaceInUpdate/B/2.0.0content.7z</file> <file>data/repositoryWithMultiReplaceInUpdate/A.sub1/1.0.0content.7z</file> <file>data/repositoryWithMultiReplaceInUpdate/B.sub1/1.0.0content.7z</file> + <file>data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z</file> </qresource> </RCC> diff --git a/tests/auto/installer/componentreplace/tst_componentreplace.cpp b/tests/auto/installer/componentreplace/tst_componentreplace.cpp index 55121019b..98fee27d0 100644 --- a/tests/auto/installer/componentreplace/tst_componentreplace.cpp +++ b/tests/auto/installer/componentreplace/tst_componentreplace.cpp @@ -87,11 +87,11 @@ private slots: core->setPackageManager(); setRepository(":///data/repositoryWithReplace", core); QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "B")); - + QCOMPARE(core->componentsToUninstall().count(), 1); QVERIFY(core->componentByName("B.sub1") != 0); QVERIFY(core->componentByName("B") != 0); - QVERIFY(core->componentByName("A.sub1") != 0); - QVERIFY(core->componentByName("A") == 0); // B has replaced A + VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt"); VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt"); VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" @@ -117,6 +117,7 @@ private slots: core->setUpdater(); setRepository(":///data/repositoryWithReplace", core); QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "B")); + QCOMPARE(core->componentsToUninstall().count(), 1); VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt"); @@ -144,6 +145,7 @@ private slots: core->setUpdater(); setRepository(":///data/repositoryWithUpdateToReplaceble", core); QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "B")); + QCOMPARE(core->componentsToUninstall().count(), 1); VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "2.0.0content.txt"); VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt"); @@ -169,6 +171,7 @@ private slots: core->setPackageManager(); setRepository(":///data/repositoryWithMultiReplace", core); QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "B")); + QCOMPARE(core->componentsToUninstall().count(), 2); VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A.sub1", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt"); @@ -196,6 +199,7 @@ private slots: core->setUpdater(); setRepository(":///data/repositoryWithMultiReplaceInUpdate", core); QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "B")); + QCOMPARE(core->componentsToUninstall().count(), 2); VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A.sub1", "1.0.0content.txt"); VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt"); @@ -205,6 +209,68 @@ private slots: delete core; } + void installOtherComponentsWhileReplacementsExists() + { + PackageManagerCore *core = PackageManager::getPackageManagerWithInit + (m_installDir, ":///data/installPackagesRepository"); + QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B")); + + QCOMPARE(core->orderedComponentsToInstall().count(), 4); + VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt"); + + core->commitSessionOperations(); + core->setPackageManager(); + setRepository(":///data/repositoryWithMultiReplaceInUpdate", core); + QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "C")); + QCOMPARE(core->orderedComponentsToInstall().count(), 1); + QCOMPARE(core->componentsToUninstall().count(), 0); + VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "C", "2.0.0content.txt"); + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt" << "C.txt"); + + delete core; + } + + void updateOtherComponentsWhileReplacementsExists() + { + PackageManagerCore *core = PackageManager::getPackageManagerWithInit + (m_installDir, ":///data/installPackagesRepository"); + QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B" << "C")); + + QCOMPARE(core->orderedComponentsToInstall().count(), 5); + VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt" << "C.txt"); + + core->commitSessionOperations(); + core->setUpdater(); + setRepository(":///data/repositoryWithMultiReplaceInUpdate", core); + QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "C")); + QCOMPARE(core->orderedComponentsToInstall().count(), 1); + QCOMPARE(core->componentsToUninstall().count(), 0); + VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "C", "2.0.0content.txt"); + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt" << "C.txt"); + + delete core; + } + void cleanup() { QDir dir(m_installDir); |