diff options
author | Robert Griebl <robert.griebl@qt.io> | 2022-03-23 15:24:21 +0100 |
---|---|---|
committer | Robert Griebl <robert.griebl@qt.io> | 2022-03-24 12:03:33 +0100 |
commit | 626138dcd2123c2a54a3b3b252dc7307b135268e (patch) | |
tree | d39faccf8a834def59bbacb779160fe47aac063c | |
parent | aa9c353420c515b0673287606dbc0916a2d52a05 (diff) | |
download | qtapplicationmanager-626138dcd2123c2a54a3b3b252dc7307b135268e.tar.gz |
Detect and prevent installing the same package multiple times in parallel
Change-Id: I8aa7e1f520346b6c946b0e1e122808d638ccb52c
Reviewed-by: Bernd Weimer <bernd.weimer@qt.io>
(cherry picked from commit 7309841d99e76577758adb11c5b905004555b338)
Reviewed-by: Robert Griebl <robert.griebl@qt.io>
-rw-r--r-- | src/manager-lib/installationtask.cpp | 7 | ||||
-rw-r--r-- | src/manager-lib/packagemanager.cpp | 9 | ||||
-rw-r--r-- | src/manager-lib/packagemanager.h | 2 | ||||
-rw-r--r-- | tests/applicationinstaller/tst_applicationinstaller.cpp | 23 |
4 files changed, 41 insertions, 0 deletions
diff --git a/src/manager-lib/installationtask.cpp b/src/manager-lib/installationtask.cpp index 06e10ac9..7cdd2555 100644 --- a/src/manager-lib/installationtask.cpp +++ b/src/manager-lib/installationtask.cpp @@ -321,6 +321,13 @@ void InstallationTask::checkExtractedFile(const QString &file) Q_DECL_NOEXCEPT_E } if (m_foundIcon && m_foundInfo) { + bool doubleInstallation = false; + QMetaObject::invokeMethod(PackageManager::instance(), [this, &doubleInstallation]() { + doubleInstallation = PackageManager::instance()->isPackageInstallationActive(m_packageId); + }, Qt::BlockingQueuedConnection); + if (doubleInstallation) + throw Exception(Error::Package, "Cannot install the same package %1 multiple times in parallel").arg(m_packageId); + qCDebug(LogInstaller) << "emit taskRequestingInstallationAcknowledge" << id() << "for package" << m_package->id(); // this is a temporary just for the signal emission below diff --git a/src/manager-lib/packagemanager.cpp b/src/manager-lib/packagemanager.cpp index 301bf80b..8a70b465 100644 --- a/src/manager-lib/packagemanager.cpp +++ b/src/manager-lib/packagemanager.cpp @@ -839,6 +839,15 @@ QVariantMap PackageManager::documentLocation() const return locationMap(d->documentPath); } +bool PackageManager::isPackageInstallationActive(const QString &packageId) const +{ + for (const auto *t : qAsConst(d->installationTaskList)) { + if (t->packageId() == packageId) + return true; + } + return false; +} + void PackageManager::cleanupBrokenInstallations() Q_DECL_NOEXCEPT_EXPR(false) { if (d->cleanupBrokenInstallationsDone) diff --git a/src/manager-lib/packagemanager.h b/src/manager-lib/packagemanager.h index ef9863b0..4be96f5d 100644 --- a/src/manager-lib/packagemanager.h +++ b/src/manager-lib/packagemanager.h @@ -152,6 +152,8 @@ public: QVariantMap installationLocation() const; QVariantMap documentLocation() const; + bool isPackageInstallationActive(const QString &packageId) const; + // Q_SCRIPTABLEs are available via both QML and D-Bus Q_SCRIPTABLE QStringList packageIds() const; Q_SCRIPTABLE QVariantMap get(const QString &packageId) const; diff --git a/tests/applicationinstaller/tst_applicationinstaller.cpp b/tests/applicationinstaller/tst_applicationinstaller.cpp index 309d15b2..d5f7829e 100644 --- a/tests/applicationinstaller/tst_applicationinstaller.cpp +++ b/tests/applicationinstaller/tst_applicationinstaller.cpp @@ -120,6 +120,7 @@ private slots: void cancelPackageInstallation(); void parallelPackageInstallation(); + void doublePackageInstallation(); void validateDnsName_data(); void validateDnsName(); @@ -685,6 +686,28 @@ void tst_PackageManager::parallelPackageInstallation() clearSignalSpies(); } +void tst_PackageManager::doublePackageInstallation() +{ + QString task1Id = m_pm->startPackageInstallation(QUrl::fromLocalFile(qL1S(AM_TESTDATA_DIR "packages/test-dev-signed.appkg"))); + QVERIFY(!task1Id.isEmpty()); + QVERIFY(m_blockingUntilInstallationAcknowledgeSpy->wait(spyTimeout)); + QCOMPARE(m_blockingUntilInstallationAcknowledgeSpy->first()[0].toString(), task1Id); + + QString task2Id = m_pm->startPackageInstallation(QUrl::fromLocalFile(qL1S(AM_TESTDATA_DIR "packages/test-dev-signed.appkg"))); + QVERIFY(!task2Id.isEmpty()); + m_pm->acknowledgePackageInstallation(task2Id); + QVERIFY(m_failedSpy->wait(spyTimeout)); + QCOMPARE(m_failedSpy->first()[0].toString(), task2Id); + QCOMPARE(m_failedSpy->first()[2].toString(), qL1S("Cannot install the same package com.pelagicore.test multiple times in parallel")); + + clearSignalSpies(); + m_pm->cancelTask(task1Id); + QVERIFY(m_failedSpy->wait(spyTimeout)); + QCOMPARE(m_failedSpy->first()[0].toString(), task1Id); + + clearSignalSpies(); +} + void tst_PackageManager::validateDnsName_data() { QTest::addColumn<QString>("dnsName"); |