4
0
mirror of https://github.com/QuasarApp/installer-framework.git synced 2025-05-08 19:19:33 +00:00

Make installer to check the dependency version

Installer was able to install dependency correctly. However, it ignored
the version dependency might have.
Dependencies>componentA->=4.0</Dependencies>
If there was already a dependency installed with lower version number,
the newer version, which was required by the selected component, was not
installed. Fixed so that maintenancetool will not only check if the
dependency is installed but also the installed version.

Change-Id: Ia26b5233cf8847bce73095d19a13c481318d27f2
Task-number: QTIFW-914
Reviewed-by: Iikka Eklund <iikka.eklund@qt.io>
This commit is contained in:
Katja Marttila 2017-03-14 14:30:09 +02:00
parent 9772474dd9
commit 7ee08852f3
5 changed files with 89 additions and 27 deletions

@ -1241,9 +1241,13 @@ bool Component::isDefault() const
return d->m_vars.value(scDefault).compare(scTrue, Qt::CaseInsensitive) == 0;
}
bool Component::isInstalled() const
bool Component::isInstalled(const QString version) const
{
return scInstalled == d->m_vars.value(scCurrentState);
if (version.isEmpty()) {
return scInstalled == d->m_vars.value(scCurrentState);
} else {
return d->m_vars.value(scInstalledVersion) == version;
}
}
/*!

@ -166,7 +166,7 @@ public:
Q_INVOKABLE bool isAutoDependOn(const QSet<QString> &componentsToInstall) const;
Q_INVOKABLE void setInstalled();
Q_INVOKABLE bool isInstalled() const;
Q_INVOKABLE bool isInstalled(const QString version = QString()) const;
Q_INVOKABLE bool installationRequested() const;
bool isSelectedForInstallation() const;

@ -92,9 +92,9 @@ QString InstallerCalculator::componentsToInstallError() const
return m_componentsToInstallError;
}
void InstallerCalculator::realAppendToInstallComponents(Component *component)
void InstallerCalculator::realAppendToInstallComponents(Component *component, const QString &version)
{
if (!component->isInstalled() || component->updateRequested()) {
if (!component->isInstalled(version) || component->updateRequested()) {
m_orderedComponentsToInstall.append(component);
m_toInstallComponentIds.insert(component->name());
}
@ -154,10 +154,10 @@ bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &co
return true;
}
bool InstallerCalculator::appendComponentToInstall(Component *component)
bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version)
{
QSet<QString> allDependencies = component->dependencies().toSet();
QString requiredDependencyVersion = version;
foreach (const QString &dependencyComponentName, allDependencies) {
// PackageManagerCore::componentByName returns 0 if dependencyComponentName contains a
// version which is not available
@ -171,30 +171,50 @@ bool InstallerCalculator::appendComponentToInstall(Component *component)
m_componentsToInstallError.append(errorMessage);
return false;
}
//Check if component requires higher version than what might be already installed
bool isUpdateRequired = false;
if (dependencyComponentName.contains(QChar::fromLatin1('-')) &&
!dependencyComponent->value(scInstalledVersion).isEmpty()) {
QRegExp compEx(QLatin1String("([<=>]+)(.*)"));
const QString installedVersion = compEx.exactMatch(dependencyComponent->value(scInstalledVersion)) ?
compEx.cap(2) : dependencyComponent->value(scInstalledVersion);
if ((!dependencyComponent->isInstalled() || dependencyComponent->updateRequested())
&& !m_toInstallComponentIds.contains(dependencyComponent->name())) {
if (m_visitedComponents.value(component).contains(dependencyComponent)) {
const QString errorMessage = recursionError(component);
qWarning().noquote() << errorMessage;
m_componentsToInstallError = errorMessage;
Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent),
Q_FUNC_INFO, qPrintable(errorMessage));
return false;
}
m_visitedComponents[component].insert(dependencyComponent);
QString requiredVersion = dependencyComponentName.section(QLatin1Char('-'), 1);
requiredVersion = compEx.exactMatch(requiredVersion) ? compEx.cap(2) : requiredVersion;
// add needed dependency components to the next run
insertInstallReason(dependencyComponent, InstallerCalculator::Dependent,
component->name());
if (KDUpdater::compareVersion(requiredVersion, installedVersion) >= 1 ) {
isUpdateRequired = true;
requiredDependencyVersion = requiredVersion;
}
}
//Check dependencies only if
//- Dependency is not installed or update requested, nor newer version of dependency component required
//- And dependency component is not already added for install
//- And component is not already added for install, then dependencies are already resolved
if (((!dependencyComponent->isInstalled() || dependencyComponent->updateRequested())
|| isUpdateRequired) && (!m_toInstallComponentIds.contains(dependencyComponent->name())
&& !m_toInstallComponentIds.contains(component->name()))) {
if (m_visitedComponents.value(component).contains(dependencyComponent)) {
const QString errorMessage = recursionError(component);
qWarning().noquote() << errorMessage;
m_componentsToInstallError = errorMessage;
Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent),
Q_FUNC_INFO, qPrintable(errorMessage));
return false;
}
m_visitedComponents[component].insert(dependencyComponent);
if (!appendComponentToInstall(dependencyComponent))
return false;
// add needed dependency components to the next run
insertInstallReason(dependencyComponent, InstallerCalculator::Dependent,
component->name());
if (!appendComponentToInstall(dependencyComponent, requiredDependencyVersion))
return false;
}
}
if (!m_toInstallComponentIds.contains(component->name())) {
realAppendToInstallComponents(component);
realAppendToInstallComponents(component, requiredDependencyVersion);
insertInstallReason(component, InstallerCalculator::Resolved);
}
return true;

@ -64,8 +64,8 @@ private:
void insertInstallReason(Component *component,
InstallReasonType installReasonType,
const QString &referencedComponentName = QString());
void realAppendToInstallComponents(Component *component);
bool appendComponentToInstall(Component *components);
void realAppendToInstallComponents(Component *component, const QString &version = QString());
bool appendComponentToInstall(Component *components, const QString &version = QString());
QString recursionError(Component *component);
QList<Component*> m_allComponents;

@ -155,14 +155,18 @@ private slots:
componentA->appendComponent(componentAA);
componentA->appendComponent(componentAB);
NamedComponent *componentB = new NamedComponent(core, QLatin1String("B"));
NamedComponent *componentB_NewVersion = new NamedComponent(core, QLatin1String("B_version"), QLatin1String("2.0.0"));
componentB->addDependency(QLatin1String("A.B"));
componentAB->addDependency(QLatin1String("B_version->=2.0.0"));
core->appendRootComponent(componentA);
core->appendRootComponent(componentB);
core->appendRootComponent(componentB_NewVersion);
QTest::newRow("Installer resolved") << core
<< (QList<Component *>() << componentB)
<< (QList<Component *>() << componentAB << componentB)
<< (QList<Component *>() << componentB_NewVersion << componentAB << componentB)
<< (QList<int>()
<< InstallerCalculator::Dependent
<< InstallerCalculator::Dependent
<< InstallerCalculator::Resolved);
}
@ -186,6 +190,40 @@ private slots:
delete core;
}
void unresolvedDependencyVersion_data()
{
QTest::addColumn<PackageManagerCore *>("core");
QTest::addColumn<QList<Component *> >("selectedComponents");
QTest::addColumn<QList<Component *> >("expectedResult");
PackageManagerCore *core = new PackageManagerCore();
core->setPackageManager();
NamedComponent *componentA = new NamedComponent(core, QLatin1String("A"));
NamedComponent *componentB = new NamedComponent(core, QLatin1String("B"), QLatin1String("1.0.0"));
componentA->addDependency(QLatin1String("B->=2.0.0"));
core->appendRootComponent(componentA);
core->appendRootComponent(componentB);
QTest::newRow("Installer resolved") << core
<< (QList<Component *>() << componentA)
<< (QList<Component *>());
}
void unresolvedDependencyVersion()
{
QFETCH(PackageManagerCore *, core);
QFETCH(QList<Component *> , selectedComponents);
QFETCH(QList<Component *> , expectedResult);
InstallerCalculator calc(core->components(PackageManagerCore::ComponentType::AllNoReplacements));
QTest::ignoreMessage(QtWarningMsg, "Cannot find missing dependency \"B->=2.0.0\" for \"A\".");
calc.appendComponentsToInstall(selectedComponents);
QList<Component *> result = calc.orderedComponentsToInstall();
QCOMPARE(result.count(), expectedResult.count());
delete core;
}
void resolveUninstaller_data()
{
QTest::addColumn<PackageManagerCore *>("core");