diff options
20 files changed, 175 insertions, 19 deletions
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp index 702dd2763..c703bfdcd 100644 --- a/src/libs/installer/component.cpp +++ b/src/libs/installer/component.cpp @@ -308,6 +308,10 @@ void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package) setValue(scTreeName, package.treeName.first); d->m_treeNameMoveChildren = package.treeName.second; + + // scDependencies might be updated from repository later, + // keep the local dependencies as well. + setValue(scLocalDependencies, value(scDependencies)); } /*! @@ -1354,12 +1358,23 @@ void Component::addDependency(const QString &newDependency) setValue(scDependencies, oldDependencies + QLatin1String(", ") + newDependency); } +/*! + Returns a list of dependencies defined in the the repository or in the package.xml. +*/ QStringList Component::dependencies() const { return d->m_vars.value(scDependencies).split(QInstaller::commaRegExp(), Qt::SkipEmptyParts); } /*! + Returns a list of installed components dependencies defined in the components.xml. +*/ +QStringList Component::localDependencies() const +{ + return d->m_vars.value(scLocalDependencies).split(QInstaller::commaRegExp(), Qt::SkipEmptyParts); +} + +/*! Adds the component specified by \a newDependOn to the automatic depend-on list. Alternatively, multiple components can be specified by separating each with a comma. @@ -1383,6 +1398,24 @@ QStringList Component::autoDependencies() const } /*! + Returns a list of dependencies that the component currently has. The + dependencies can vary when component is already installed with different + dependency list than what is introduced in the repository. If component is + not installed, or update is requested to an installed component, + current dependencies are read from repository so that correct dependencies + are calculated for the component when it is installed or updated. +*/ +QStringList Component::currentDependencies() const +{ + QStringList dependenciesList; + if (isInstalled() && !updateRequested()) + dependenciesList = localDependencies(); + else + dependenciesList = dependencies(); + return dependenciesList; +} + +/*! \sa {component::setInstalled}{component.setInstalled} */ void Component::setInstalled() @@ -1519,7 +1552,7 @@ bool Component::isUpdateAvailable() const \sa {component::updateRequested}{component.updateRequested} */ -bool Component::updateRequested() +bool Component::updateRequested() const { return d->m_updateIsAvailable && isSelected() && !isUnstable(); } diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h index dbf604a56..e5f1b38da 100644 --- a/src/libs/installer/component.h +++ b/src/libs/installer/component.h @@ -170,8 +170,10 @@ public: Q_INVOKABLE void addDependency(const QString &newDependency); QStringList dependencies() const; + QStringList localDependencies() const; Q_INVOKABLE void addAutoDependOn(const QString &newDependOn); QStringList autoDependencies() const; + QStringList currentDependencies() const; void languageChanged(); QString localTempPath() const; @@ -195,7 +197,7 @@ public: Q_INVOKABLE void setUpdateAvailable(bool isUpdateAvailable); Q_INVOKABLE bool isUpdateAvailable() const; - Q_INVOKABLE bool updateRequested(); + Q_INVOKABLE bool updateRequested() const; Q_INVOKABLE bool componentChangeRequested(); Q_INVOKABLE bool isForcedUpdate(); diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h index af518a0f6..7fa54c4ec 100644 --- a/src/libs/installer/constants.h +++ b/src/libs/installer/constants.h @@ -59,6 +59,7 @@ static const QLatin1String scDisplayName("DisplayName"); static const QLatin1String scTreeName("TreeName"); static const QLatin1String scAutoTreeName("AutoTreeName"); static const QLatin1String scDependencies("Dependencies"); +static const QLatin1String scLocalDependencies("LocalDependencies"); static const QLatin1String scAutoDependOn("AutoDependOn"); static const QLatin1String scNewComponent("NewComponent"); static const QLatin1String scRepositories("Repositories"); diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp index 21e82fc9a..2ef5d3b74 100644 --- a/src/libs/installer/installercalculator.cpp +++ b/src/libs/installer/installercalculator.cpp @@ -109,7 +109,7 @@ bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &co } } - if (component->dependencies().isEmpty()) + if (component->currentDependencies().isEmpty()) realAppendToInstallComponents(component, QString(), revertFromInstall); else notAppendedComponents.append(component); @@ -177,7 +177,7 @@ void InstallerCalculator::realAppendToInstallComponents(Component *component, co bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version, bool revertFromInstall) { - const QStringList dependenciesList = component->dependencies(); + const QStringList dependenciesList = component->currentDependencies(); QSet<QString> allDependencies(dependenciesList.begin(), dependenciesList.end()); QString requiredDependencyVersion = version; foreach (const QString &dependencyComponentName, allDependencies) { diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index 8ebaefd62..543852e20 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -3922,6 +3922,8 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo // a possible component to replace that might be installed (to mark the replacement as installed). component->setInstalled(); component->setValue(scInstalledVersion, data.installedPackages->value(name).version); + component->setValue(scLocalDependencies, data.installedPackages->value(name). + dependencies.join(QLatin1String(","))); return true; } diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 85e902ac3..e279a8027 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -463,7 +463,7 @@ void PackageManagerCorePrivate::cleanUpComponentEnvironment() { m_componentReplaces.clear(); m_autoDependencyComponentHash.clear(); - m_dependencyComponentHash.clear(); + m_localDependencyComponentHash.clear(); m_localVirtualComponents.clear(); // clean up registered (downloaded) data if (m_core->isMaintainer()) @@ -596,7 +596,7 @@ UninstallerCalculator *PackageManagerCorePrivate::uninstallerCalculator() const } pmcp->m_uninstallerCalculator = new UninstallerCalculator(installedComponents, m_core, - pmcp->m_autoDependencyComponentHash, pmcp->m_dependencyComponentHash, pmcp->m_localVirtualComponents); + pmcp->m_autoDependencyComponentHash, pmcp->m_localDependencyComponentHash, pmcp->m_localVirtualComponents); } return m_uninstallerCalculator; } @@ -3164,11 +3164,11 @@ void PackageManagerCorePrivate::createDependencyHashes(const Component* componen m_autoDependencyComponentHash.insert(autodepend, value); } - for (const QString &depend : component->dependencies()) { - QStringList value = m_dependencyComponentHash.value(depend); + for (const QString &depend : component->localDependencies()) { + QStringList value = m_localDependencyComponentHash.value(depend); if (!value.contains(component->name())) value.append(component->name()); - m_dependencyComponentHash.insert(depend, value); + m_localDependencyComponentHash.insert(depend, value); } } diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index 3a859f63d..8a5b805d8 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -311,7 +311,7 @@ private: QHash<Component*, Qt::CheckState> m_coreCheckedHash; QList<Component*> m_deletedReplacedComponents; AutoDependencyHash m_autoDependencyComponentHash; - DependencyHash m_dependencyComponentHash; + LocalDependencyHash m_localDependencyComponentHash; QStringList m_localVirtualComponents; diff --git a/src/libs/installer/qinstallerglobal.h b/src/libs/installer/qinstallerglobal.h index 5bc87e21d..88f255af6 100644 --- a/src/libs/installer/qinstallerglobal.h +++ b/src/libs/installer/qinstallerglobal.h @@ -58,7 +58,7 @@ typedef QList<QInstaller::Package*> PackagesList; typedef QMap<QString, KDUpdater::LocalPackage> LocalPackagesMap; typedef QHash<QString, QStringList> AutoDependencyHash; -typedef QHash<QString, QStringList> DependencyHash; +typedef QHash<QString, QStringList> LocalDependencyHash; } // namespace QInstaller diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp index c717f6550..af03df8c5 100644 --- a/src/libs/installer/uninstallercalculator.cpp +++ b/src/libs/installer/uninstallercalculator.cpp @@ -45,12 +45,12 @@ namespace QInstaller { UninstallerCalculator::UninstallerCalculator(const QList<Component *> &installedComponents , PackageManagerCore *core , const AutoDependencyHash &autoDependencyComponentHash - , const DependencyHash &dependencyComponentHash + , const LocalDependencyHash &localDependencyComponentHash , const QStringList &localVirtualComponents) : m_installedComponents(installedComponents) , m_core(core) , m_autoDependencyComponentHash(autoDependencyComponentHash) - , m_dependencyComponentHash(dependencyComponentHash) + , m_localDependencyComponentHash(localDependencyComponentHash) , m_localVirtualComponents(localVirtualComponents) { } @@ -68,8 +68,8 @@ void UninstallerCalculator::appendComponentToUninstall(Component *component, con if (!component->isInstalled()) return; - if (m_dependencyComponentHash.contains(component->name())) { - const QStringList &dependencies = PackageManagerCore::parseNames(m_dependencyComponentHash.value(component->name())); + if (m_localDependencyComponentHash.contains(component->name())) { + const QStringList &dependencies = PackageManagerCore::parseNames(m_localDependencyComponentHash.value(component->name())); for (const QString &dependencyComponent : dependencies) { Component *depComponent = m_core->componentByName(dependencyComponent); if (depComponent && depComponent->isInstalled() && !m_componentsToUninstall.contains(depComponent)) { diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h index a458daa80..76e32c6a6 100644 --- a/src/libs/installer/uninstallercalculator.h +++ b/src/libs/installer/uninstallercalculator.h @@ -55,7 +55,7 @@ public: UninstallerCalculator(const QList<Component *> &installedComponents, PackageManagerCore *core, const AutoDependencyHash &autoDependencyComponentHash, - const DependencyHash &dependencyComponentHash, + const LocalDependencyHash &localDependencyComponentHash, const QStringList &localVirtualComponents); QSet<Component*> componentsToUninstall() const; @@ -78,7 +78,7 @@ private: PackageManagerCore *m_core; QHash<QString, QPair<UninstallReasonType, QString> > m_toUninstallComponentIdReasonHash; AutoDependencyHash m_autoDependencyComponentHash; - DependencyHash m_dependencyComponentHash; + LocalDependencyHash m_localDependencyComponentHash; QStringList m_localVirtualComponents; QList<Component *> m_virtualComponentsForReverse; }; diff --git a/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/Updates.xml b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/Updates.xml new file mode 100644 index 000000000..72931954a --- /dev/null +++ b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/Updates.xml @@ -0,0 +1,72 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>componentA</Name> + <DisplayName>Component A</DisplayName> + <Description>New dependency added</Description> + <Version>2.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>100</SortingPriority> + <UpdateFile OS="Any" CompressedSize="299" UncompressedSize="158"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>92b02a74d0886bc1569ff8b3a7edd1f9d828e56c</SHA1> + <Dependencies>componentF</Dependencies> + </PackageUpdate> + <PackageUpdate> + <Name>componentB</Name> + <DisplayName>Component B</DisplayName> + <Description>This component does not depend on any other component.</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>90</SortingPriority> + <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>aedfaef53cdc0f52353a8680009be405fa767811</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>componentC</Name> + <DisplayName>Component C. Dependencies removed</DisplayName> + <Description>This component dependencies on Component A and Component B are removed in update.</Description> + <Dependencies></Dependencies> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>80</SortingPriority> + <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>20b9463a5e06f373182b3c7c4cf879806d429409</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>componentD</Name> + <DisplayName>Component D (auto depends on A and B)</DisplayName> + <Description>This component has an automatic dependency on Component A and Component B. If both A and B are marked for installation, this component is also installed.</Description> + <AutoDependOn>componentA, componentB</AutoDependOn> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>70</SortingPriority> + <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>99cf24c71559c75dfae9933826ed16051fca6ea1</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>componentF</Name> + <DisplayName>Component F</DisplayName> + <Description>This component contains 2 subcomponents.</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>40</SortingPriority> + <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>e6443a8b5a5651f63c0604cae6d32431ca617f1a</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>componentH</Name> + <Description>This component does not depend on any other component.</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>50</SortingPriority> + <DownloadableArchives>content.7z</DownloadableArchives> + <Virtual>false</Virtual> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentA/2.0.0content.7z b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentA/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..4ddbe565b --- /dev/null +++ b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentA/2.0.0content.7z diff --git a/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentB/1.0.0content.7z b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentB/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..f84ffcdc5 --- /dev/null +++ b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentB/1.0.0content.7z diff --git a/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentC/1.0.0content.7z b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentC/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..9ad11e06f --- /dev/null +++ b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentC/1.0.0content.7z diff --git a/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentD/1.0.0content.7z b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentD/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..0c8c52e31 --- /dev/null +++ b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentD/1.0.0content.7z diff --git a/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentF/1.0.0content.7z b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentF/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..4a04b1394 --- /dev/null +++ b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentF/1.0.0content.7z diff --git a/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentH/1.0.0content.7z b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentH/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..e1449ad29 --- /dev/null +++ b/tests/auto/installer/cliinterface/data/installPackagesDependencyChanged/componentH/1.0.0content.7z diff --git a/tests/auto/installer/cliinterface/settings.qrc b/tests/auto/installer/cliinterface/settings.qrc index 6b46aaffd..824517e1e 100644 --- a/tests/auto/installer/cliinterface/settings.qrc +++ b/tests/auto/installer/cliinterface/settings.qrc @@ -21,6 +21,13 @@ <file>data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z</file> + <file>data/installPackagesDependencyChanged/Updates.xml</file> + <file>data/installPackagesDependencyChanged/componentA/2.0.0content.7z</file> + <file>data/installPackagesDependencyChanged/componentB/1.0.0content.7z</file> + <file>data/installPackagesDependencyChanged/componentC/1.0.0content.7z</file> + <file>data/installPackagesDependencyChanged/componentD/1.0.0content.7z</file> + <file>data/installPackagesDependencyChanged/componentF/1.0.0content.7z</file> + <file>data/installPackagesDependencyChanged/componentH/1.0.0content.7z</file> <file>data/filequeryrepository/Updates.xml</file> <file>data/filequeryrepository/A/1.0.2-1meta.7z</file> <file>data/componentsFromInstallPackagesRepository.xml</file> diff --git a/tests/auto/installer/cliinterface/tst_cliinterface.cpp b/tests/auto/installer/cliinterface/tst_cliinterface.cpp index c43eca381..8f1784543 100644 --- a/tests/auto/installer/cliinterface/tst_cliinterface.cpp +++ b/tests/auto/installer/cliinterface/tst_cliinterface.cpp @@ -413,6 +413,45 @@ private slots: << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt"); } + void testInstallPackagesWithChangedRepository() + { + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_installDir, ":///data/installPackagesRepository")); + core->setNoDefaultInstallation(true); + QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() + << QLatin1String("componentC"))); + + QCOMPARE(PackageManagerCore::Success, core->status()); + VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt"); //Dependency to componentC + VerifyInstaller::verifyInstallerResources(m_installDir, "componentB", "1.0.0content.txt"); //Dependency to componentC + VerifyInstaller::verifyInstallerResources(m_installDir, "componentC", "1.0.0content.txt"); //Selected + VerifyInstaller::verifyInstallerResources(m_installDir, "componentD", "1.0.0content.txt"); //Autodepend on componentA,componentB + VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt"); //AutodependOn componentC + VerifyInstaller::verifyInstallerResources(m_installDir, "componentI", "1.0.0content.txt"); //Virtual dependency to componentC + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "installcontent.txt" << "installcontentA.txt" << "installcontentB.txt" + << "installcontentC.txt" << "installcontentD.txt" << "installcontentE.txt" + << "installcontentI.txt"); + + core->reset(); + core->cancelMetaInfoJob(); //Call cancel to reset metadata so that update repositories are fetched + + QSet<Repository> repoList; + Repository repo = Repository::fromUserInput(":///data/installPackagesDependencyChanged"); + repoList.insert(repo); + core->settings().setDefaultRepositories(repoList); + + QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() + << QLatin1String("componentH"))); + // New dependency is added in repository from componentA to componentF, check that it is not installed + VerifyInstaller::verifyInstallerResourcesDeletion(m_installDir, "componentF"); + VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" + << "installcontent.txt" << "installcontentA.txt" << "installcontentB.txt" + << "installcontentC.txt" << "installcontentD.txt" << "installcontentE.txt" + << "installcontentI.txt" << "installcontentH.txt"); + core->setNoDefaultInstallation(false); + } + void testUnInstallDefaultPackagesSilently() { QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit diff --git a/tests/auto/installer/solver/tst_solver.cpp b/tests/auto/installer/solver/tst_solver.cpp index 45fadc4e6..8b5d1fdcf 100644 --- a/tests/auto/installer/solver/tst_solver.cpp +++ b/tests/auto/installer/solver/tst_solver.cpp @@ -252,7 +252,7 @@ private slots: QTest::addColumn<QList<Component *> >("installedComponents"); QTest::addColumn<QSet<Component *> >("expectedResult"); QTest::addColumn<UninstallReasonList >("uninstallReasons"); - QTest::addColumn<DependencyHash >("dependencyHash"); + QTest::addColumn<LocalDependencyHash >("dependencyHash"); UninstallReasonList uninstallReasonList; PackageManagerCore *core = new PackageManagerCore(); @@ -317,7 +317,7 @@ private slots: QFETCH(QList<Component *> , installedComponents); QFETCH(QSet<Component *> , expectedResult); QFETCH(UninstallReasonList, uninstallReasons); - QFETCH(DependencyHash, dependencyHash); + QFETCH(LocalDependencyHash, dependencyHash); UninstallerCalculator calc(installedComponents, core, QHash<QString, QStringList>(), dependencyHash, QStringList()); calc.appendComponentsToUninstall(selectedToUninstall); |