summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatja Marttila <katja.marttila@qt.io>2020-12-20 11:31:30 +0200
committerKatja Marttila <katja.marttila@qt.io>2020-12-22 08:38:36 +0200
commita606c9915b8ff1d6001a83aa350400d6286706ff (patch)
tree33fba20f96caf98be8d42382763d0f93f92a9366
parentb7df5571e0707f53716fa51d426d5ec31d36af43 (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>
-rw-r--r--doc/examples/package.xml1
-rw-r--r--doc/installerfw-using.qdoc8
-rw-r--r--doc/installerfw.qdoc6
-rw-r--r--doc/scripting-api/component.qdoc8
-rw-r--r--src/libs/installer/component.cpp16
-rw-r--r--src/libs/installer/component.h1
-rw-r--r--src/libs/installer/constants.h1
-rw-r--r--src/libs/installer/packagemanagercore.cpp30
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp4
-rw-r--r--src/libs/installer/printoutput.cpp1
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml9
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml9
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7zbin0 -> 225 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/settings.qrc2
-rw-r--r--tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp28
-rw-r--r--tests/auto/installer/shared/verifyinstaller.h6
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
new file mode 100644
index 000000000..e1449ad29
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7z
Binary files differ
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
new file mode 100644
index 000000000..f74b8da68
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z
Binary files differ
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());