diff options
author | Katja Marttila <katja.marttila@qt.io> | 2020-12-20 11:31:30 +0200 |
---|---|---|
committer | Katja Marttila <katja.marttila@qt.io> | 2020-12-22 08:38:36 +0200 |
commit | a606c9915b8ff1d6001a83aa350400d6286706ff (patch) | |
tree | 33fba20f96caf98be8d42382763d0f93f92a9366 | |
parent | b7df5571e0707f53716fa51d426d5ec31d36af43 (diff) |
Introduce ForcedUpdate element for component
Setting ForcedUpdate for component will cause a mandatory update for
component if it is installed. Component must be updated before any other
component can be updated/installed/removed. Essential components are updated
at the same time with ForcedUpdate.
Task-number: QTIFW-1565
Change-Id: I6af07fba222371e8cd161d1fec65301450077d86
Reviewed-by: Arttu Tarkiainen <arttu.tarkiainen@qt.io>
17 files changed, 111 insertions, 19 deletions
diff --git a/doc/examples/package.xml b/doc/examples/package.xml index 4248a7e83..16b9e07ce 100644 --- a/doc/examples/package.xml +++ b/doc/examples/package.xml @@ -26,6 +26,7 @@ <UpdateText>This changed compared to the last release</UpdateText> <Default>false</Default> <ForcedInstallation>false</ForcedInstallation> + <ForcedUpdate>false</ForcedUpdate> <Essential>false</Essential> <Replaces>com.vendor.root.component2old</Replaces> <Operations> diff --git a/doc/installerfw-using.qdoc b/doc/installerfw-using.qdoc index 89c3351ee..cb0e4d3ad 100644 --- a/doc/installerfw-using.qdoc +++ b/doc/installerfw-using.qdoc @@ -419,9 +419,11 @@ \section1 Updating Components Running \c update without arguments will update all components that have an update - available. Essential components are always updated first, same way as it is done when - launching updater from GUI. To update only a specific subset of installed components, - they can be provided as an optional argument for \c update: + available. Essential and ForcedUpdate components are always updated first, same way as + when launching the updater from GUI. After Essential and ForcedUpdate components + are updated, the installer needs to be restarted for other updates. To update only + a specific subset of installed components, they can be provided as an optional argument + for \c update: \code maintenancetool.exe update componentA componentB diff --git a/doc/installerfw.qdoc b/doc/installerfw.qdoc index 22407e17d..d5335d585 100644 --- a/doc/installerfw.qdoc +++ b/doc/installerfw.qdoc @@ -895,6 +895,12 @@ \li Determines that the package must always be installed. End users cannot deselect it in the installer. \row + \li ForcedUpdate + \li Marks the package as \c ForcedUpdate to force a restart of the + \c MaintenanceTool. If there are updates available + for a \c ForcedUpdate component, the package manager stays + disabled until that component is updated. + \row \li Replaces \li Comma-separated list of components to replace. Optional. diff --git a/doc/scripting-api/component.qdoc b/doc/scripting-api/component.qdoc index c7a9509c8..ffa2988a3 100644 --- a/doc/scripting-api/component.qdoc +++ b/doc/scripting-api/component.qdoc @@ -421,6 +421,14 @@ */ /*! + \qmlmethod boolean component::isForcedUpdate() + + Returns \c true if the component is installed and has a \c ForcedUpdate flag set. + Forced updates will be updated together with essential components before any + other component can be updated or installed. +*/ + +/*! \qmlmethod void component::setUninstalled() Sets the component state to uninstalled. diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp index cb028b940..4d614d242 100644 --- a/src/libs/installer/component.cpp +++ b/src/libs/installer/component.cpp @@ -314,6 +314,7 @@ void Component::loadDataFromPackage(const Package &package) setValue(scSortingPriority, package.data(scSortingPriority).toString()); setValue(scEssential, package.data(scEssential).toString()); + setValue(scForcedUpdate, package.data(scForcedUpdate).toString()); setValue(scUpdateText, package.data(scUpdateText).toString()); setValue(scNewComponent, package.data(scNewComponent).toString()); setValue(scRequiresAdminRights, package.data(scRequiresAdminRights).toString()); @@ -1341,8 +1342,10 @@ bool Component::isAutoDependOn(const QSet<QString> &componentsToInstall) const if (componentsToInstall.contains(autoDependOnSet)) { foreach (const QString &autoDep, autoDependOnSet) { Component *component = packageManagerCore()->componentByName(autoDep); - if (component->value(scEssential, scFalse).toLower() == scTrue) + if ((component->value(scEssential, scFalse).toLower() == scTrue) + || component->isForcedUpdate()) { return true; + } } } return false; @@ -1449,6 +1452,17 @@ bool Component::componentChangeRequested() return updateRequested() || isSelectedForInstallation() || uninstallationRequested(); } +/*! + Returns \c true if the component is installed and has a \c ForcedUpdate flag set. + ForcedUpdate components will be updated together with essential components before + any other component can be updated or installed. + + \sa {component::isForcedUpdate}{component.isForcedUpdate} +*/ +bool Component::isForcedUpdate() +{ + return isInstalled() && (value(scForcedUpdate, scFalse).toLower() == scTrue); +} /*! \sa {component::setUninstalled}{component.setUninstalled} diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h index 494d79b13..f7f03391f 100644 --- a/src/libs/installer/component.h +++ b/src/libs/installer/component.h @@ -191,6 +191,7 @@ public: Q_INVOKABLE bool updateRequested(); Q_INVOKABLE bool componentChangeRequested(); + Q_INVOKABLE bool isForcedUpdate(); bool isUnstable() const; void setUnstable(Component::UnstableError error, const QString &errorMessage = QString()); diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h index 711aaa66b..be42426fb 100644 --- a/src/libs/installer/constants.h +++ b/src/libs/installer/constants.h @@ -50,6 +50,7 @@ static const QLatin1String scInheritVersion("inheritVersionFrom"); static const QLatin1String scReplaces("Replaces"); static const QLatin1String scDownloadableArchives("DownloadableArchives"); static const QLatin1String scEssential("Essential"); +static const QLatin1String scForcedUpdate("ForcedUpdate"); static const QLatin1String scTargetDir("TargetDir"); static const QLatin1String scReleaseDate("ReleaseDate"); static const QLatin1String scDescription("Description"); diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index e4b0e1689..8e205b7d7 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -1551,12 +1551,18 @@ bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const L return false; if (success && isPackageManager()) { foreach (Package *const update, packages) { - if (update->data(scEssential, scFalse).toString().toLower() == scTrue) { + bool essentialUpdate = (update->data(scEssential, scFalse).toString().toLower() == scTrue); + bool forcedUpdate = (update->data(scForcedUpdate, scFalse).toString().toLower() == scTrue); + if (essentialUpdate || forcedUpdate) { const QString name = update->data(scName).toString(); - if (!installedPackages.contains(name)) { + // 'Essential' package not installed, install. + if (essentialUpdate && !installedPackages.contains(name)) { success = false; - continue; // unusual, the maintenance tool should always be available + continue; } + // 'Forced update' package not installed, no update needed + if (forcedUpdate && !installedPackages.contains(name)) + continue; const LocalPackage localPackage = installedPackages.value(name); const QString updateVersion = update->data(scVersion).toString(); @@ -1568,7 +1574,7 @@ bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const L continue; // remote release date equals or is less than the installed maintenance tool success = false; - break; // we found a newer version of the maintenance tool + break; // we found a newer version of the forced/essential update package } } @@ -2290,7 +2296,8 @@ PackageManagerCore::Status PackageManagerCore::updateComponentsSilently(const QS // restart installer and install rest of the updates. bool essentialUpdatesFound = false; foreach (Component *component, componentList) { - if (component->value(scEssential, scFalse).toLower() == scTrue) + if ((component->value(scEssential, scFalse).toLower() == scTrue) + || component->isForcedUpdate()) essentialUpdatesFound = true; } if (!essentialUpdatesFound) { @@ -3634,8 +3641,10 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const if (localPackage.lastUpdateDate > updateDate) continue; - if (update->data(scEssential, scFalse).toString().toLower() == scTrue) + if (update->data(scEssential, scFalse).toString().toLower() == scTrue || + update->data(scForcedUpdate, scFalse).toString().toLower() == scTrue) { setFoundEssentialUpdate(true); + } // this is not a dependency, it is a real update components.insert(name, d->m_updaterComponentsDeps.takeLast()); @@ -3693,13 +3702,14 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const component->setCheckable(false); component->setSelectable(false); - if (component->value(scEssential, scFalse).toLower() == scFalse) { + if ((component->value(scEssential, scFalse).toLower() == scTrue) + || (component->value(scForcedUpdate, scFalse).toLower() == scTrue)) { + // essential updates are enabled, still not checkable but checked + component->setEnabled(true); + } else { // non essential updates are disabled, not checkable and unchecked component->setEnabled(false); component->setCheckState(Qt::Unchecked); - } else { - // essential updates are enabled, still not checkable but checked - component->setEnabled(true); } } } diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 79e07a9f9..b3c543758 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -1996,8 +1996,10 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr if (!ok && !ignoreError) throw Error(operation->errorString()); - if ((component->value(scEssential, scFalse) == scTrue) && !m_core->isCommandLineInstance()) + if (((component->value(scEssential, scFalse) == scTrue) || (component->value(scForcedUpdate, scFalse) == scTrue)) + && !m_core->isCommandLineInstance()) { m_needsHardRestart = true; + } } registerPathsForUninstallation(component->pathsForUninstallation(), component->name()); diff --git a/src/libs/installer/printoutput.cpp b/src/libs/installer/printoutput.cpp index 1759d6642..27281aaf0 100644 --- a/src/libs/installer/printoutput.cpp +++ b/src/libs/installer/printoutput.cpp @@ -104,6 +104,7 @@ void printPackageInformation(const PackagesList &matchedPackages, const LocalPac update.setAttribute(QLatin1String("checkable"), package->data(scCheckable).toString()); update.setAttribute(QLatin1String("default"), package->data(scDefault).toString()); update.setAttribute(QLatin1String("essential"), package->data(scEssential).toString()); + update.setAttribute(QLatin1String("forcedUpdate"), package->data(scForcedUpdate).toString()); update.setAttribute(QLatin1String("compressedsize"), package->data(QLatin1String("CompressedSize")).toString()); update.setAttribute(QLatin1String("uncompressedsize"), package->data(QLatin1String("UncompressedSize")).toString()); update.setAttribute(QLatin1String("releaseDate"), package->data(scReleaseDate).toString()); diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml index 345b462d0..9e01f1800 100644 --- a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml +++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml @@ -151,4 +151,13 @@ <DownloadableArchives>content.7z</DownloadableArchives> <SHA1>8cba36dd589492c28e0d04942b4f8aa0a09f59cc</SHA1> </PackageUpdate> + <PackageUpdate> + <Name>componentH</Name> + <DisplayName>Component H. ForcedUpdate</DisplayName> + <Description>Component H. ForcedUpdate</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <ForcedUpdate>true</ForcedUpdate> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> </Updates> diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..e1449ad29 --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7z diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml index 125289261..f56888022 100644 --- a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml +++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml @@ -151,4 +151,13 @@ <DownloadableArchives>content.7z</DownloadableArchives> <SHA1>098b5ecafe8853371fd608acd9b1ccab252ef5df</SHA1> </PackageUpdate> + <PackageUpdate> + <Name>componentH</Name> + <DisplayName>Component H. ForcedUpdate</DisplayName> + <Description>Component H. ForcedUpdate</Description> + <Version>2.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <ForcedUpdate>true</ForcedUpdate> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> </Updates> diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..f74b8da68 --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z diff --git a/tests/auto/installer/commandlineupdate/settings.qrc b/tests/auto/installer/commandlineupdate/settings.qrc index a0a04a9e3..bed0619d8 100644 --- a/tests/auto/installer/commandlineupdate/settings.qrc +++ b/tests/auto/installer/commandlineupdate/settings.qrc @@ -10,6 +10,7 @@ <file>data/installPackagesRepository/componentF/1.0.0content.7z</file> <file>data/installPackagesRepository/componentG/1.0.0content.7z</file> <file>data/installPackagesRepository/componentG/1.0.0meta.7z</file> + <file>data/installPackagesRepository/componentH/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z</file> @@ -25,6 +26,7 @@ <file>data/installPackagesRepositoryUpdate/componentF/2.0.0content.7z</file> <file>data/installPackagesRepositoryUpdate/componentG/2.0.0content.7z</file> <file>data/installPackagesRepositoryUpdate/componentG/2.0.0meta.7z</file> + <file>data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z</file> <file>data/installPackagesRepositoryUpdate/componentF.subcomponent1/1.0.0content.7z</file> <file>data/installPackagesRepositoryUpdate/componentF.subcomponent2/2.0.0content.7z</file> <file>data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z</file> diff --git a/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp b/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp index e465f8a75..5a25bbb39 100644 --- a/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp +++ b/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp @@ -108,6 +108,30 @@ private slots: core->setFoundEssentialUpdate(false); } + void testUpdateForceUpdatePackagesSilently() + { + setRepository(":///data/installPackagesRepository"); + QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() + << "componentH")); + VerifyInstaller::verifyInstallerResources(m_installDir, "componentH", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt"); + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "installcontentA_update.txt" << "installcontentE.txt" << "installcontentG.txt" + << "installContentAutoDependOnA.txt" << "installcontentH.txt"); + core->commitSessionOperations(); + + setRepository(":///data/installPackagesRepositoryUpdate"); + QCOMPARE(PackageManagerCore::EssentialUpdated, core->updateComponentsSilently(QStringList())); + VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "componentH", "1.0.0content.txt"); + VerifyInstaller::verifyInstallerResources(m_installDir, "componentH", "2.0.0content.txt"); + //Verify that no other installed components got update + VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt"); + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "installcontentA_update.txt" << "installcontentE.txt" << "installcontentG.txt" + << "installContentAutoDependOnA.txt" << "installcontentH_update.txt"); + core->setFoundEssentialUpdate(false); + } + void testUpdatePackageSilently() { setRepository(":///data/installPackagesRepository"); @@ -122,7 +146,7 @@ private slots: VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" << "installcontentA_update.txt" << "installcontentE.txt" << "installcontentG.txt" << "installcontentB.txt" << "installcontentD.txt" - << "installContentAutoDependOnA.txt"); + << "installContentAutoDependOnA.txt" << "installcontentH_update.txt"); core->commitSessionOperations(); setRepository(":///data/installPackagesRepositoryUpdate"); @@ -141,7 +165,7 @@ private slots: VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" << "installcontentA_update.txt" << "installcontentE_update.txt" << "installcontentG.txt" << "installcontentB_update.txt" << "installcontentD_update.txt" - << "installContentAutoDependOnA.txt"); + << "installContentAutoDependOnA.txt" << "installcontentH_update.txt"); } void testUpdateNoUpdatesForSelectedPackage() diff --git a/tests/auto/installer/shared/verifyinstaller.h b/tests/auto/installer/shared/verifyinstaller.h index 4445743af..7cd2af05b 100644 --- a/tests/auto/installer/shared/verifyinstaller.h +++ b/tests/auto/installer/shared/verifyinstaller.h @@ -63,8 +63,10 @@ struct VerifyInstaller static void verifyFileExistence(const QString &installDir, const QStringList &fileList) { - for (int i = 0; i < fileList.count(); i++) - QVERIFY(QFileInfo::exists(installDir + QDir::separator() + fileList.at(i))); + for (int i = 0; i < fileList.count(); i++) { + bool fileExists = QFileInfo::exists(installDir + QDir::separator() + fileList.at(i)); + QVERIFY2(fileExists, QString("File \"%1\" does not exist.").arg(fileList.at(i)).toLatin1()); + } QDir dir(installDir); QCOMPARE(dir.entryList(QStringList() << "*.*", QDir::Files).count(), fileList.count()); |