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:
parent
9772474dd9
commit
7ee08852f3
src/libs/installer
tests/auto/installer/solver
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user