mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Enhance update checker
* Reduce initial update check notification to 500 ms to prevent inappropriately stealing focus from user * Add build flag WITH_XC_UPDATECHECK which defaults to ON * Update checks are resolved every 7 days instead of every time the application is started * Better checks for beta builds; ignore snapshots * Increase test cases
This commit is contained in:
parent
53a57ee8c7
commit
2ffefc95ae
@ -49,6 +49,7 @@ option(WITH_XC_YUBIKEY "Include YubiKey support." OFF)
|
|||||||
option(WITH_XC_SSHAGENT "Include SSH agent support." OFF)
|
option(WITH_XC_SSHAGENT "Include SSH agent support." OFF)
|
||||||
option(WITH_XC_KEESHARE "Sharing integration with KeeShare" OFF)
|
option(WITH_XC_KEESHARE "Sharing integration with KeeShare" OFF)
|
||||||
option(WITH_XC_KEESHARE_SECURE "Sharing integration with secured KeeShare containers" OFF)
|
option(WITH_XC_KEESHARE_SECURE "Sharing integration with secured KeeShare containers" OFF)
|
||||||
|
option(WITH_XC_UPDATECHECK "Include automatic update checks; disable for controlled distributions" ON)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
option(WITH_XC_TOUCHID "Include TouchID support for macOS." OFF)
|
option(WITH_XC_TOUCHID "Include TouchID support for macOS." OFF)
|
||||||
endif()
|
endif()
|
||||||
@ -76,6 +77,10 @@ else()
|
|||||||
set(WITH_XC_CRYPTO_SSH OFF)
|
set(WITH_XC_CRYPTO_SSH OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_XC_UPDATECHECK)
|
||||||
|
set(WITH_XC_NETWORKING ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(KEEPASSXC_VERSION_MAJOR "2")
|
set(KEEPASSXC_VERSION_MAJOR "2")
|
||||||
set(KEEPASSXC_VERSION_MINOR "4")
|
set(KEEPASSXC_VERSION_MINOR "4")
|
||||||
set(KEEPASSXC_VERSION_PATCH "0")
|
set(KEEPASSXC_VERSION_PATCH "0")
|
||||||
|
@ -195,6 +195,7 @@ add_feature_info(SSHAgent WITH_XC_SSHAGENT "SSH agent integration compatible wit
|
|||||||
add_feature_info(KeeShare WITH_XC_KEESHARE "Sharing integration with KeeShare")
|
add_feature_info(KeeShare WITH_XC_KEESHARE "Sharing integration with KeeShare")
|
||||||
add_feature_info(KeeShare-Secure WITH_XC_KEESHARE_SECURE "Sharing integration with KeeShare with secure sources")
|
add_feature_info(KeeShare-Secure WITH_XC_KEESHARE_SECURE "Sharing integration with KeeShare with secure sources")
|
||||||
add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response")
|
add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response")
|
||||||
|
add_feature_info(UpdateCheck WITH_XC_UPDATECHECK "Automatic update checking")
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_feature_info(TouchID WITH_XC_TOUCHID "TouchID integration")
|
add_feature_info(TouchID WITH_XC_TOUCHID "TouchID integration")
|
||||||
endif()
|
endif()
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#cmakedefine WITH_XC_KEESHARE
|
#cmakedefine WITH_XC_KEESHARE
|
||||||
#cmakedefine WITH_XC_KEESHARE_INSECURE
|
#cmakedefine WITH_XC_KEESHARE_INSECURE
|
||||||
#cmakedefine WITH_XC_KEESHARE_SECURE
|
#cmakedefine WITH_XC_KEESHARE_SECURE
|
||||||
|
#cmakedefine WITH_XC_UPDATECHECK
|
||||||
#cmakedefine WITH_XC_TOUCHID
|
#cmakedefine WITH_XC_TOUCHID
|
||||||
|
|
||||||
#cmakedefine KEEPASSXC_BUILD_TYPE "@KEEPASSXC_BUILD_TYPE@"
|
#cmakedefine KEEPASSXC_BUILD_TYPE "@KEEPASSXC_BUILD_TYPE@"
|
||||||
|
@ -30,6 +30,7 @@ QDateTime Clock::currentDateTime()
|
|||||||
|
|
||||||
uint Clock::currentSecondsSinceEpoch()
|
uint Clock::currentSecondsSinceEpoch()
|
||||||
{
|
{
|
||||||
|
// TODO: change to toSecsSinceEpoch() when min Qt >= 5.8
|
||||||
return instance().currentDateTimeImpl().toTime_t();
|
return instance().currentDateTimeImpl().toTime_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +92,15 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
|
|||||||
m_secUi->touchIDResetSpinBox, SLOT(setEnabled(bool)));
|
m_secUi->touchIDResetSpinBox, SLOT(setEnabled(bool)));
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#ifndef WITH_XC_NETWORKING
|
#ifdef WITH_XC_UPDATECHECK
|
||||||
|
connect(m_generalUi->checkForUpdatesOnStartupCheckBox, SIGNAL(toggled(bool)), SLOT(checkUpdatesToggled(bool)));
|
||||||
|
#else
|
||||||
m_generalUi->checkForUpdatesOnStartupCheckBox->setVisible(false);
|
m_generalUi->checkForUpdatesOnStartupCheckBox->setVisible(false);
|
||||||
|
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setVisible(false);
|
||||||
|
m_generalUi->checkUpdatesSpacer->changeSize(0,0, QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WITH_XC_NETWORKING
|
||||||
m_secUi->privacy->setVisible(false);
|
m_secUi->privacy->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -350,3 +357,8 @@ void ApplicationSettingsWidget::rememberDatabasesToggled(bool checked)
|
|||||||
m_generalUi->rememberLastKeyFilesCheckBox->setEnabled(checked);
|
m_generalUi->rememberLastKeyFilesCheckBox->setEnabled(checked);
|
||||||
m_generalUi->openPreviousDatabasesOnStartupCheckBox->setEnabled(checked);
|
m_generalUi->openPreviousDatabasesOnStartupCheckBox->setEnabled(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplicationSettingsWidget::checkUpdatesToggled(bool checked)
|
||||||
|
{
|
||||||
|
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setEnabled(checked);
|
||||||
|
}
|
||||||
|
@ -57,6 +57,7 @@ private slots:
|
|||||||
void systrayToggled(bool checked);
|
void systrayToggled(bool checked);
|
||||||
void toolbarSettingsToggled(bool checked);
|
void toolbarSettingsToggled(bool checked);
|
||||||
void rememberDatabasesToggled(bool checked);
|
void rememberDatabasesToggled(bool checked);
|
||||||
|
void checkUpdatesToggled(bool checked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget* const m_secWidget;
|
QWidget* const m_secWidget;
|
||||||
|
@ -141,10 +141,40 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkForUpdatesOnStartupCheckBox">
|
<widget class="QCheckBox" name="checkForUpdatesOnStartupCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Check for updates at application startup</string>
|
<string>Check for updates at application startup once per week</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="checkUpdatesSubLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="checkUpdatesSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkForUpdatesIncludeBetasCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Include beta releases when checking for updates</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -241,13 +271,6 @@
|
|||||||
<string>General</string>
|
<string>General</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="checkForUpdatesIncludeBetasCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Include pre-releases when checking for updates</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="toolbarHideCheckBox">
|
<widget class="QCheckBox" name="toolbarHideCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
#include "keys/FileKey.h"
|
#include "keys/FileKey.h"
|
||||||
#include "keys/PasswordKey.h"
|
#include "keys/PasswordKey.h"
|
||||||
|
|
||||||
#ifdef WITH_XC_NETWORKING
|
#ifdef WITH_XC_UPDATECHECK
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
#include "gui/UpdateCheckDialog.h"
|
#include "gui/UpdateCheckDialog.h"
|
||||||
#include "updatecheck/UpdateChecker.h"
|
#include "updatecheck/UpdateChecker.h"
|
||||||
@ -372,12 +372,12 @@ MainWindow::MainWindow()
|
|||||||
setUnifiedTitleAndToolBarOnMac(true);
|
setUnifiedTitleAndToolBarOnMac(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_XC_NETWORKING
|
#ifdef WITH_XC_UPDATECHECK
|
||||||
connect(m_ui->actionCheckForUpdates, SIGNAL(triggered()), SLOT(showUpdateCheckDialog()));
|
connect(m_ui->actionCheckForUpdates, SIGNAL(triggered()), SLOT(showUpdateCheckDialog()));
|
||||||
connect(UpdateChecker::instance(),
|
connect(UpdateChecker::instance(),
|
||||||
SIGNAL(updateCheckFinished(bool, QString, bool)),
|
SIGNAL(updateCheckFinished(bool, QString, bool)),
|
||||||
SLOT(hasUpdateAvailable(bool, QString, bool)));
|
SLOT(hasUpdateAvailable(bool, QString, bool)));
|
||||||
QTimer::singleShot(3000, this, SLOT(showUpdateCheckStartup()));
|
QTimer::singleShot(500, this, SLOT(showUpdateCheckStartup()));
|
||||||
#else
|
#else
|
||||||
m_ui->actionCheckForUpdates->setVisible(false);
|
m_ui->actionCheckForUpdates->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
@ -670,7 +670,7 @@ void MainWindow::showAboutDialog()
|
|||||||
|
|
||||||
void MainWindow::showUpdateCheckStartup()
|
void MainWindow::showUpdateCheckStartup()
|
||||||
{
|
{
|
||||||
#ifdef WITH_XC_NETWORKING
|
#ifdef WITH_XC_UPDATECHECK
|
||||||
if (!config()->get("UpdateCheckMessageShown", false).toBool()) {
|
if (!config()->get("UpdateCheckMessageShown", false).toBool()) {
|
||||||
auto result =
|
auto result =
|
||||||
MessageBox::question(this,
|
MessageBox::question(this,
|
||||||
@ -693,7 +693,7 @@ void MainWindow::showUpdateCheckStartup()
|
|||||||
|
|
||||||
void MainWindow::hasUpdateAvailable(bool hasUpdate, const QString& version, bool isManuallyRequested)
|
void MainWindow::hasUpdateAvailable(bool hasUpdate, const QString& version, bool isManuallyRequested)
|
||||||
{
|
{
|
||||||
#ifdef WITH_XC_NETWORKING
|
#ifdef WITH_XC_UPDATECHECK
|
||||||
if (hasUpdate && !isManuallyRequested) {
|
if (hasUpdate && !isManuallyRequested) {
|
||||||
auto* updateCheckDialog = new UpdateCheckDialog(this);
|
auto* updateCheckDialog = new UpdateCheckDialog(this);
|
||||||
updateCheckDialog->showUpdateCheckResponse(hasUpdate, version);
|
updateCheckDialog->showUpdateCheckResponse(hasUpdate, version);
|
||||||
@ -708,7 +708,7 @@ void MainWindow::hasUpdateAvailable(bool hasUpdate, const QString& version, bool
|
|||||||
|
|
||||||
void MainWindow::showUpdateCheckDialog()
|
void MainWindow::showUpdateCheckDialog()
|
||||||
{
|
{
|
||||||
#ifdef WITH_XC_NETWORKING
|
#ifdef WITH_XC_UPDATECHECK
|
||||||
updateCheck()->checkForUpdates(true);
|
updateCheck()->checkForUpdates(true);
|
||||||
auto* updateCheckDialog = new UpdateCheckDialog(this);
|
auto* updateCheckDialog = new UpdateCheckDialog(this);
|
||||||
updateCheckDialog->show();
|
updateCheckDialog->show();
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "UpdateChecker.h"
|
#include "UpdateChecker.h"
|
||||||
#include "config-keepassx.h"
|
#include "config-keepassx.h"
|
||||||
|
#include "core/Clock.h"
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
@ -38,7 +39,10 @@ UpdateChecker::~UpdateChecker()
|
|||||||
|
|
||||||
void UpdateChecker::checkForUpdates(bool manuallyRequested)
|
void UpdateChecker::checkForUpdates(bool manuallyRequested)
|
||||||
{
|
{
|
||||||
|
auto nextCheck = config()->get("GUI/CheckForUpdatesNextCheck", 0).toULongLong();
|
||||||
m_isManuallyRequested = manuallyRequested;
|
m_isManuallyRequested = manuallyRequested;
|
||||||
|
|
||||||
|
if (m_isManuallyRequested || Clock::currentSecondsSinceEpoch() >= nextCheck) {
|
||||||
m_bytesReceived.clear();
|
m_bytesReceived.clear();
|
||||||
|
|
||||||
QString apiUrlStr = QString("https://api.github.com/repos/keepassxreboot/keepassxc/releases");
|
QString apiUrlStr = QString("https://api.github.com/repos/keepassxreboot/keepassxc/releases");
|
||||||
@ -57,6 +61,7 @@ void UpdateChecker::checkForUpdates(bool manuallyRequested)
|
|||||||
connect(m_reply, &QNetworkReply::finished, this, &UpdateChecker::fetchFinished);
|
connect(m_reply, &QNetworkReply::finished, this, &UpdateChecker::fetchFinished);
|
||||||
connect(m_reply, &QIODevice::readyRead, this, &UpdateChecker::fetchReadyRead);
|
connect(m_reply, &QIODevice::readyRead, this, &UpdateChecker::fetchReadyRead);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateChecker::fetchReadyRead()
|
void UpdateChecker::fetchReadyRead()
|
||||||
{
|
{
|
||||||
@ -84,8 +89,12 @@ void UpdateChecker::fetchFinished()
|
|||||||
|
|
||||||
if (!jsonObject.value("tag_name").isUndefined()) {
|
if (!jsonObject.value("tag_name").isUndefined()) {
|
||||||
version = jsonObject.value("tag_name").toString();
|
version = jsonObject.value("tag_name").toString();
|
||||||
hasNewVersion = compareVersions(version, QString(KEEPASSXC_VERSION));
|
hasNewVersion = compareVersions(QString(KEEPASSXC_VERSION), version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check again in 7 days
|
||||||
|
// TODO: change to toSecsSinceEpoch() when min Qt >= 5.8
|
||||||
|
config()->set("GUI/CheckForUpdatesNextCheck", Clock::currentDateTime().addDays(7).toTime_t());
|
||||||
} else {
|
} else {
|
||||||
version = "error";
|
version = "error";
|
||||||
}
|
}
|
||||||
@ -93,38 +102,46 @@ void UpdateChecker::fetchFinished()
|
|||||||
emit updateCheckFinished(hasNewVersion, version, m_isManuallyRequested);
|
emit updateCheckFinished(hasNewVersion, version, m_isManuallyRequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateChecker::compareVersions(const QString& remoteVersion, const QString& localVersion)
|
bool UpdateChecker::compareVersions(const QString& localVersion, const QString& remoteVersion)
|
||||||
{
|
{
|
||||||
|
// Quick full-string equivalence check
|
||||||
if (localVersion == remoteVersion) {
|
if (localVersion == remoteVersion) {
|
||||||
return false; // Currently using updated version
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRegularExpression verRegex("^(\\d+(\\.\\d+){0,2})(-\\w+)?$", QRegularExpression::CaseInsensitiveOption);
|
QRegularExpression verRegex(R"(^((?:\d+\.){2}\d+)(?:-(\w+?)(\d+)?)?$)");
|
||||||
|
|
||||||
QRegularExpressionMatch lmatch = verRegex.match(localVersion);
|
auto lmatch = verRegex.match(localVersion);
|
||||||
QRegularExpressionMatch rmatch = verRegex.match(remoteVersion);
|
auto rmatch = verRegex.match(remoteVersion);
|
||||||
|
|
||||||
if (!lmatch.captured(1).isNull() && !rmatch.captured(1).isNull()) {
|
auto lVersion = lmatch.captured(1).split(".");
|
||||||
if (lmatch.captured(1) == rmatch.captured(1) && !lmatch.captured(3).isNull()) {
|
auto lSuffix = lmatch.captured(2);
|
||||||
// Same version, but installed version has snapshot/beta suffix and should be updated to stable
|
auto lBetaNum = lmatch.captured(3);
|
||||||
return true;
|
|
||||||
|
auto rVersion = rmatch.captured(1).split(".");
|
||||||
|
auto rSuffix = rmatch.captured(2);
|
||||||
|
auto rBetaNum = rmatch.captured(3);
|
||||||
|
|
||||||
|
if (!lVersion.isEmpty() && !rVersion.isEmpty()) {
|
||||||
|
if (lSuffix.compare("snapshot", Qt::CaseInsensitive) == 0) {
|
||||||
|
// Snapshots are not checked for version updates
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList lparts = lmatch.captured(1).split(".");
|
// Check "-beta[X]" versions
|
||||||
QStringList rparts = rmatch.captured(1).split(".");
|
if (lVersion == rVersion && !lSuffix.isEmpty()) {
|
||||||
|
// Check if stable version has been released or new beta is available
|
||||||
if (lparts.length() < 3)
|
// otherwise the version numbers are equal
|
||||||
lparts << "0";
|
return rSuffix.isEmpty() || lBetaNum.toInt() < rBetaNum.toInt();
|
||||||
|
}
|
||||||
if (rparts.length() < 3)
|
|
||||||
rparts << "0";
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
int l = lparts[i].toInt();
|
int l = lVersion[i].toInt();
|
||||||
int r = rparts[i].toInt();
|
int r = rVersion[i].toInt();
|
||||||
|
|
||||||
if (l == r)
|
if (l == r) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (l > r) {
|
if (l > r) {
|
||||||
return false; // Installed version is newer than release
|
return false; // Installed version is newer than release
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
~UpdateChecker() override;
|
~UpdateChecker() override;
|
||||||
|
|
||||||
void checkForUpdates(bool manuallyRequested);
|
void checkForUpdates(bool manuallyRequested);
|
||||||
static bool compareVersions(const QString& remoteVersion, const QString& localVersion);
|
static bool compareVersions(const QString& localVersion, const QString& remoteVersion);
|
||||||
static UpdateChecker* instance();
|
static UpdateChecker* instance();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -29,13 +29,32 @@ void TestUpdateCheck::initTestCase()
|
|||||||
|
|
||||||
void TestUpdateCheck::testCompareVersion()
|
void TestUpdateCheck::testCompareVersion()
|
||||||
{
|
{
|
||||||
// Remote Version , Installed Version
|
// No upgrade
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString("2.4.0"), QString("2.3.4")), true);
|
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.4.0")), false);
|
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0")), false);
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0")), false);
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0-beta1")), true);
|
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta2"), QString("2.3.0-beta1")), true);
|
// First digit upgrade
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.4"), QString("2.4.0-snapshot")), false);
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.4.0"), QString("3.0.0")), true);
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString("invalid"), QString("2.4.0")), false);
|
QCOMPARE(UpdateChecker::compareVersions(QString("3.0.0"), QString("2.4.0")), false);
|
||||||
QCOMPARE(UpdateChecker::compareVersions(QString(""), QString("2.4.0")), false);
|
|
||||||
|
// Second digit upgrade
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.4"), QString("2.4.0")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.4.0"), QString("2.3.4")), false);
|
||||||
|
|
||||||
|
// Third digit upgrade
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.1")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.1"), QString("2.3.0")), false);
|
||||||
|
|
||||||
|
// Beta builds
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0-beta1")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.1-beta1")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta1"), QString("2.3.0")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta"), QString("2.3.0-beta1")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta1"), QString("2.3.0-beta")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta1"), QString("2.3.0-beta2")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta2"), QString("2.3.0-beta1")), false);
|
||||||
|
|
||||||
|
// Snapshot and invalid data
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.4-snapshot"), QString("2.4.0")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.4.0"), QString("invalid")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.4.0"), QString("")), false);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user