diff options
27 files changed, 344 insertions, 27 deletions
diff --git a/doc/installerfw.qdoc b/doc/installerfw.qdoc index e9a6463bc..4ae62eff6 100644 --- a/doc/installerfw.qdoc +++ b/doc/installerfw.qdoc @@ -1215,6 +1215,11 @@ \row \li -v or --verbose \li Display debug output. + \row + \li -s or --sha-update p1,...,pn + \li Comma-separated list of packages to be updated based on the component sha + checksum instead of the version number. This parameter adds a new \c <ContentSha1> + node to the \c Updates.xml. \endtable \note We recommend that you use the \c {--update-new-packages} parameter to update an existing repository, especially if you have a content delivery diff --git a/src/libs/ifwtools/repositorygen.cpp b/src/libs/ifwtools/repositorygen.cpp index c269f4931..842d4f9cb 100644 --- a/src/libs/ifwtools/repositorygen.cpp +++ b/src/libs/ifwtools/repositorygen.cpp @@ -72,6 +72,8 @@ void QInstallerTools::printRepositoryGenOptions() std::cout << " --ignore-translations Do not use any translation" << std::endl; std::cout << " --ignore-invalid-packages Ignore all invalid packages instead of aborting." << std::endl; std::cout << " --ignore-invalid-repositories Ignore all invalid repositories instead of aborting." << std::endl; + std::cout << " -s|--sha-update p1,...,pn List of packages which are updated using" <<std::endl; + std::cout << " content sha1 instead of version number." << std::endl; } QString QInstallerTools::makePathAbsolute(const QString &path) @@ -292,6 +294,11 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met fileElement.setAttribute(QLatin1String("OS"), QLatin1String("Any")); update.appendChild(fileElement); + if (info.createContentSha1Node) { + QDomNode contentSha1Element = update.appendChild(doc.createElement(QLatin1String("ContentSha1"))); + contentSha1Element.appendChild(doc.createTextNode(info.contentSha1)); + } + root.appendChild(update); // copy script file @@ -417,7 +424,7 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met } PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packagesDirectories, - QStringList *packagesToFilter, FilterType filterType) + QStringList *packagesToFilter, FilterType filterType, QStringList packagesUpdatedWithSha) { qDebug() << "Collecting information about available packages..."; @@ -511,6 +518,13 @@ PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packa info.dependencies = packageElement.firstChildElement(QLatin1String("Dependencies")).text() .split(QInstaller::commaRegExp(), QString::SkipEmptyParts); info.directory = it->filePath(); + if (packagesUpdatedWithSha.contains(info.name)) { + info.createContentSha1Node = true; + packagesUpdatedWithSha.removeOne(info.name); + } else { + info.createContentSha1Node = false; + } + dict.push_back(info); qDebug() << "- it provides the package" << info.name << " - " << info.version; @@ -524,6 +538,11 @@ PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packa if (dict.isEmpty()) qDebug() << "No available packages found at the specified location."; + if (!packagesUpdatedWithSha.isEmpty()) { + throw QInstaller::Error(QString::fromLatin1("The following packages could not be found in " + "package directory: %1").arg(packagesUpdatedWithSha.join(QLatin1String(", ")))); + } + return dict; } @@ -905,6 +924,8 @@ void QInstallerTools::copyComponentData(const QStringList &packageDirs, const QS archiveHashFile.write(hashOfArchiveData); qDebug() << "Generated sha1 hash:" << hashOfArchiveData; (*infos)[i].copiedFiles.append(archiveHashFile.fileName()); + if ((*infos)[i].createContentSha1Node) + (*infos)[i].contentSha1 = QLatin1String(hashOfArchiveData); archiveHashFile.close(); } catch (const QInstaller::Error &/*e*/) { archiveFile.close(); @@ -991,7 +1012,7 @@ QString QInstallerTools::existingUniteMeta7z(const QString &repositoryDir) return uniteMeta7z; } -PackageInfoVector QInstallerTools::collectPackages(RepositoryInfo info, QStringList *filteredPackages, FilterType filterType, bool updateNewComponents) +PackageInfoVector QInstallerTools::collectPackages(RepositoryInfo info, QStringList *filteredPackages, FilterType filterType, bool updateNewComponents, QStringList packagesUpdatedWithSha) { PackageInfoVector packages; PackageInfoVector precompressedPackages = QInstallerTools::createListOfRepositoryPackages(info.repositoryPackages, @@ -999,18 +1020,16 @@ PackageInfoVector QInstallerTools::collectPackages(RepositoryInfo info, QStringL packages.append(precompressedPackages); PackageInfoVector preparedPackages = QInstallerTools::createListOfPackages(info.packages, - filteredPackages, filterType); + filteredPackages, filterType, packagesUpdatedWithSha); packages.append(preparedPackages); if (updateNewComponents) { filterNewComponents(info.repositoryDir, packages); } - foreach (const QInstallerTools::PackageInfo &package, packages) { const QFileInfo fi(info.repositoryDir, package.name); if (fi.exists()) removeDirectory(fi.absoluteFilePath()); } - return packages; } diff --git a/src/libs/ifwtools/repositorygen.h b/src/libs/ifwtools/repositorygen.h index 7204a0e13..0da81db67 100644 --- a/src/libs/ifwtools/repositorygen.h +++ b/src/libs/ifwtools/repositorygen.h @@ -48,6 +48,8 @@ struct IFWTOOLS_EXPORT PackageInfo QStringList copiedFiles; QString metaFile; QString metaNode; + QString contentSha1; + bool createContentSha1Node; }; typedef QVector<PackageInfo> PackageInfoVector; @@ -68,7 +70,7 @@ QString IFWTOOLS_EXPORT makePathAbsolute(const QString &path); void IFWTOOLS_EXPORT copyWithException(const QString &source, const QString &target, const QString &kind = QString()); PackageInfoVector IFWTOOLS_EXPORT createListOfPackages(const QStringList &packagesDirectories, QStringList *packagesToFilter, - FilterType ftype); + FilterType ftype, QStringList packagesUpdatedWithSha = QStringList()); PackageInfoVector IFWTOOLS_EXPORT createListOfRepositoryPackages(const QStringList &repositoryDirectories, QStringList *packagesToFilter, FilterType filterType); @@ -89,9 +91,8 @@ void IFWTOOLS_EXPORT copyComponentData(const QStringList &packageDir, const QStr void IFWTOOLS_EXPORT filterNewComponents(const QString &repositoryDir, QInstallerTools::PackageInfoVector &packages); QString IFWTOOLS_EXPORT existingUniteMeta7z(const QString &repositoryDir); -PackageInfoVector IFWTOOLS_EXPORT collectPackages(RepositoryInfo info, QStringList *filteredPackages, FilterType filterType, bool updateNewComponents); +PackageInfoVector IFWTOOLS_EXPORT collectPackages(RepositoryInfo info, QStringList *filteredPackages, FilterType filterType, bool updateNewComponents, QStringList packagesUpdatedWithSha); void IFWTOOLS_EXPORT createRepository(RepositoryInfo info, PackageInfoVector *packages, const QString &tmpMetaDir, bool createComponentMetadata, bool createUnifiedMetadata); - } // namespace QInstallerTools #endif // REPOSITORYGEN_H diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp index 66f333377..c5d74cdfa 100644 --- a/src/libs/installer/component.cpp +++ b/src/libs/installer/component.cpp @@ -300,6 +300,7 @@ void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package) setValue(scCurrentState, scInstalled); setValue(scCheckable, package.checkable ? scTrue : scFalse); setValue(scExpandedByDefault, package.expandedByDefault ? scTrue : scFalse); + setValue(scContentSha1, package.contentSha1); } /*! @@ -341,6 +342,7 @@ void Component::loadDataFromPackage(const Package &package) if (PackageManagerCore::noForceInstallation()) forced = scFalse; setValue(scForcedInstallation, forced); + setValue(scContentSha1, package.data(scContentSha1).toString()); setLocalTempPath(QInstaller::pathFromUrl(package.packageSource().url)); const QStringList uis = package.data(QLatin1String("UserInterfaces")).toString() diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h index 42b14ce63..f1105941b 100644 --- a/src/libs/installer/constants.h +++ b/src/libs/installer/constants.h @@ -67,6 +67,7 @@ static const QLatin1String scUncompressedSizeSum("UncompressedSizeSum"); static const QLatin1String scRequiresAdminRights("RequiresAdminRights"); static const QLatin1String scOfflineBinaryName("OfflineBinaryName"); static const QLatin1String scSHA1("SHA1"); +static const QLatin1String scContentSha1("ContentSha1"); // constants used throughout the components class static const QLatin1String scVirtual("Virtual"); diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index 7528a3188..5bbccbe98 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -1549,9 +1549,8 @@ bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const L continue; const LocalPackage localPackage = installedPackages.value(name); - const QString updateVersion = update->data(scVersion).toString(); - if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0) - continue; // remote version equals or is less than the installed maintenance tool + if (!d->packageNeedsUpdate(localPackage, update)) + continue; const QDate updateDate = update->data(scReleaseDate).toDate(); if (localPackage.lastUpdateDate >= updateDate) @@ -2322,6 +2321,7 @@ PackageManagerCore::Status PackageManagerCore::updateComponentsSilently(const QS if (componentList.count() == 0) { qCDebug(QInstaller::lcInstallerInstallLog) << "No updates available."; + setCanceled(); } else { // Check if essential components are available (essential components are disabled). // If essential components are found, update first essential updates, @@ -3769,10 +3769,8 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const continue; // Update for not installed package found, skip it. const LocalPackage &localPackage = locals.value(name); - const QString updateVersion = update->data(scVersion).toString(); - if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0) + if (!d->packageNeedsUpdate(localPackage, update)) continue; - // It is quite possible that we may have already installed the update. Lets check the last // update date of the package and the release date of the update. This way we can compare and // figure out if the update has been installed or not. diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index f4670c738..e6220ba35 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -2246,7 +2246,8 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr component->value(scUncompressedSize).toULongLong(), component->value(scInheritVersion), component->isCheckable(), - component->isExpandedByDefault()); + component->isExpandedByDefault(), + component->value(scContentSha1)); m_localPackageHub->writeToDisk(); component->setInstalled(); @@ -2898,4 +2899,19 @@ bool PackageManagerCorePrivate::askUserConfirmCommand() const } } +bool PackageManagerCorePrivate::packageNeedsUpdate(const LocalPackage &localPackage, const Package *update) const +{ + bool updateNeeded = true; + const QString contentSha1 = update->data(scContentSha1).toString(); + if (!contentSha1.isEmpty()) { + if (contentSha1 == localPackage.contentSha1) + updateNeeded = false; + } else { + const QString updateVersion = update->data(scVersion).toString(); + if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0) + updateNeeded = false; + } + return updateNeeded; +} + } // namespace QInstaller diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index 858baf9eb..4d5021471 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -254,6 +254,7 @@ private: bool acceptLicenseAgreements() const; bool askUserAcceptLicense(const QString &name, const QString &content) const; bool askUserConfirmCommand() const; + bool packageNeedsUpdate(const LocalPackage &localPackage, const Package *update) const; private: PackageManagerCore *m_core; diff --git a/src/libs/kdtools/localpackagehub.cpp b/src/libs/kdtools/localpackagehub.cpp index 1a754d7d5..2ee880e04 100644 --- a/src/libs/kdtools/localpackagehub.cpp +++ b/src/libs/kdtools/localpackagehub.cpp @@ -327,7 +327,8 @@ void LocalPackageHub::addPackage(const QString &name, quint64 uncompressedSize, const QString &inheritVersionFrom, bool checkable, - bool expandedByDefault) + bool expandedByDefault, + const QString &contentSha1) { // TODO: This somewhat unexpected, remove? if (d->m_packageInfoMap.contains(name)) { @@ -350,6 +351,7 @@ void LocalPackageHub::addPackage(const QString &name, info.uncompressedSize = uncompressedSize; info.checkable = checkable; info.expandedByDefault = expandedByDefault; + info.contentSha1 = contentSha1; d->m_packageInfoMap.insert(name, info); } d->modified = true; @@ -426,6 +428,8 @@ void LocalPackageHub::writeToDisk() addTextChildHelper(&package, QLatin1String("Checkable"), QLatin1String("true")); if (info.expandedByDefault) addTextChildHelper(&package, QLatin1String("ExpandedByDefault"), QLatin1String("true")); + if (!info.contentSha1.isEmpty()) + addTextChildHelper(&package, scContentSha1, info.contentSha1); root.appendChild(package); } @@ -498,6 +502,8 @@ void LocalPackageHub::PackagesInfoData::addPackageFrom(const QDomElement &packag info.checkable = childNodeE.text().toLower() == QLatin1String("true") ? true : false; else if (childNodeE.tagName() == QLatin1String("ExpandedByDefault")) info.expandedByDefault = childNodeE.text().toLower() == QLatin1String("true") ? true : false; + else if (childNodeE.tagName() == QLatin1String("ContentSha1")) + info.contentSha1 = childNodeE.text(); } m_packageInfoMap.insert(info.name, info); } diff --git a/src/libs/kdtools/localpackagehub.h b/src/libs/kdtools/localpackagehub.h index d43c4a6a5..648d6cf6e 100644 --- a/src/libs/kdtools/localpackagehub.h +++ b/src/libs/kdtools/localpackagehub.h @@ -55,6 +55,7 @@ struct KDTOOLS_EXPORT LocalPackage quint64 uncompressedSize; bool checkable; bool expandedByDefault; + QString contentSha1; }; class KDTOOLS_EXPORT LocalPackageHub @@ -108,7 +109,8 @@ public: quint64 uncompressedSize, const QString &inheritVersionFrom, bool checkable, - bool expandedByDefault); + bool expandedByDefault, + const QString &contentSha1); bool removePackage(const QString &pkgName); void refresh(); diff --git a/tests/auto/installer/contentshaupdate/contentshaupdate.pro b/tests/auto/installer/contentshaupdate/contentshaupdate.pro new file mode 100644 index 000000000..84402794f --- /dev/null +++ b/tests/auto/installer/contentshaupdate/contentshaupdate.pro @@ -0,0 +1,9 @@ +include(../../qttest.pri) + +QT += qml + +SOURCES += tst_contentshaupdate.cpp + +RESOURCES += \ + settings.qrc \ + ..\shared\config.qrc diff --git a/tests/auto/installer/contentshaupdate/data/repository/Updates.xml b/tests/auto/installer/contentshaupdate/data/repository/Updates.xml new file mode 100644 index 000000000..a83d41384 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repository/Updates.xml @@ -0,0 +1,48 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>componentA</Name> + <DisplayName>Component A</DisplayName> + <Description>This component does not depend on any other component.</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>100</SortingPriority> + <UpdateFile OS="Any" CompressedSize="283" UncompressedSize="101"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>10</ContentSha1> + </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="283" UncompressedSize="101"/> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> + <PackageUpdate> + <Name>componentC</Name> + <DisplayName>Component C</DisplayName> + <Description>Component C</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>80</SortingPriority> + <UpdateFile OS="Any" CompressedSize="283" UncompressedSize="101"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>10</ContentSha1> + </PackageUpdate> + <PackageUpdate> + <Name>componentD</Name> + <DisplayName>Component D</DisplayName> + <Description>Component D</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>80</SortingPriority> + <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>10</ContentSha1> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentA/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentA/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..46a9f1d1e --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repository/componentA/1.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentB/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentB/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..5f1fb2e1b --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repository/componentB/1.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentC/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentC/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..83e82b5a3 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repository/componentC/1.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentD/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentD/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..da50742a4 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repository/componentD/1.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/Updates.xml new file mode 100644 index 000000000..87017cf91 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/Updates.xml @@ -0,0 +1,48 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>componentA</Name> + <DisplayName>Component A</DisplayName> + <Description>Component A.</Description> + <Version>0.1.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>100</SortingPriority> + <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>5</ContentSha1> + </PackageUpdate> + <PackageUpdate> + <Name>componentB</Name> + <DisplayName>Component B</DisplayName> + <Description>Component B.</Description> + <Version>0.1.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>90</SortingPriority> + <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>10</ContentSha1> + </PackageUpdate> + <PackageUpdate> + <Name>componentC</Name> + <DisplayName>Component C</DisplayName> + <Description>Component C</Description> + <Version>2.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>80</SortingPriority> + <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>10</ContentSha1> + </PackageUpdate> + <PackageUpdate> + <Name>componentD</Name> + <DisplayName>Component D</DisplayName> + <Description>Component D</Description> + <Version>2.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>80</SortingPriority> + <UpdateFile UncompressedSize="101" CompressedSize="283" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentA/0.1.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentA/0.1.0content.7z Binary files differnew file mode 100644 index 000000000..bdbabc7fd --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentA/0.1.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentB/0.1.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentB/0.1.0content.7z Binary files differnew file mode 100644 index 000000000..1c1129b9f --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentB/0.1.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentC/2.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentC/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..7f75bf503 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentC/2.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentD/2.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentD/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..4207dfbf2 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentD/2.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/settings.qrc b/tests/auto/installer/contentshaupdate/settings.qrc new file mode 100644 index 000000000..a5d045f46 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/settings.qrc @@ -0,0 +1,14 @@ +<RCC> + <qresource prefix="/"> + <file>data/repository/Updates.xml</file> + <file>data/repository/componentA/1.0.0content.7z</file> + <file>data/repository/componentB/1.0.0content.7z</file> + <file>data/repository/componentC/1.0.0content.7z</file> + <file>data/repository/componentD/1.0.0content.7z</file> + <file>data/repositoryUpdate/Updates.xml</file> + <file>data/repositoryUpdate/componentA/0.1.0content.7z</file> + <file>data/repositoryUpdate/componentB/0.1.0content.7z</file> + <file>data/repositoryUpdate/componentC/2.0.0content.7z</file> + <file>data/repositoryUpdate/componentD/2.0.0content.7z</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp new file mode 100644 index 000000000..d8d2f5377 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp @@ -0,0 +1,108 @@ +/************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "../shared/packagemanager.h" +#include "../shared/verifyinstaller.h" + +#include <QTest> + +using namespace QInstaller; + +class tst_ContentSha1Update : public QObject +{ + Q_OBJECT + +private: + void setRepository(const QString &repository) + { + core->reset(); + core->cancelMetaInfoJob(); //Call cancel to reset metadata so that update repositories are fetched + + QSet<Repository> repoList; + Repository repo = Repository::fromUserInput(repository); + repoList.insert(repo); + core->settings().setDefaultRepositories(repoList); + } + +private slots: + void initTestCase() + { + m_installDir = QInstaller::generateTemporaryFileName(); + core = PackageManager::getPackageManagerWithInit(m_installDir); + } + + void updateWithContentSha1_data() + { + QTest::addColumn<QString>("component"); + QTest::addColumn<QString>("content"); + QTest::addColumn<QString>("updatedContent"); + QTest::addColumn<PackageManagerCore::Status>("expectedStatusAfterInstall"); + QTest::addColumn<PackageManagerCore::Status>("expectedStatusAfterUpdate"); + + QTest::newRow("ContentSha1Change") << "componentA" << "1.0.0content.txt" << "0.1.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Success; + QTest::newRow("NewContentSha1") << "componentB" << "1.0.0content.txt" << "0.1.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Success; + QTest::newRow("SameContentSha1") << "componentC" << "1.0.0content.txt" << "1.0.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Canceled; + QTest::newRow("Sha1RemovedFromRepo") << "componentD" << "1.0.0content.txt" << "2.0.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Success; + } + + void updateWithContentSha1() + { + QFETCH(QString, component); + QFETCH(QString, content); + QFETCH(QString, updatedContent); + QFETCH(PackageManagerCore::Status, expectedStatusAfterInstall); + QFETCH(PackageManagerCore::Status, expectedStatusAfterUpdate); + + setRepository(":///data/repository"); + QCOMPARE(expectedStatusAfterInstall, core->installSelectedComponentsSilently(QStringList() << component)); + QCOMPARE(expectedStatusAfterInstall, core->status()); + VerifyInstaller::verifyInstallerResources(m_installDir, component, content); + + core->commitSessionOperations(); + core->setPackageManager(); + setRepository(":///data/repositoryUpdate"); + QCOMPARE(expectedStatusAfterUpdate, core->updateComponentsSilently(QStringList())); + VerifyInstaller::verifyInstallerResources(m_installDir, component, updatedContent); + } + + void cleanupTestCase() + { + QDir dir(m_installDir); + QVERIFY(dir.removeRecursively()); + delete core; + } + +private: + QString m_installDir; + PackageManagerCore *core; +}; + + +QTEST_MAIN(tst_ContentSha1Update) + +#include "tst_contentshaupdate.moc" diff --git a/tests/auto/installer/installer.pro b/tests/auto/installer/installer.pro index 114c43d7a..cb0438ab3 100644 --- a/tests/auto/installer/installer.pro +++ b/tests/auto/installer/installer.pro @@ -39,7 +39,8 @@ SUBDIRS += \ globalsettingsoperation \ elevatedexecuteoperation \ treename \ - createoffline + createoffline \ + contentshaupdate win32 { SUBDIRS += registerfiletypeoperation \ diff --git a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp index ae2c3b211..17343e49d 100644 --- a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp +++ b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp @@ -306,7 +306,7 @@ private slots: QTest::ignoreMessage(QtWarningMsg, re); QTest::ignoreMessage(QtDebugMsg, "No updates available."); - QCOMPARE(PackageManagerCore::Failure, core.updateComponentsSilently(QStringList())); + QCOMPARE(PackageManagerCore::Canceled, core.updateComponentsSilently(QStringList())); QVERIFY(QDir().rmdir(testDirectory)); } diff --git a/tests/auto/tools/repotest/tst_repotest.cpp b/tests/auto/tools/repotest/tst_repotest.cpp index 7a8542b7e..228c13c80 100644 --- a/tests/auto/tools/repotest/tst_repotest.cpp +++ b/tests/auto/tools/repotest/tst_repotest.cpp @@ -39,13 +39,13 @@ class tst_repotest : public QObject { Q_OBJECT private: - - void generateRepo(bool createSplitMetadata, bool createUnifiedMetadata, bool updateNewComponents) + void generateRepo(bool createSplitMetadata, bool createUnifiedMetadata, bool updateNewComponents, + QStringList packagesUpdatedWithSha = QStringList()) { QStringList filteredPackages; QInstallerTools::PackageInfoVector m_packages = QInstallerTools::collectPackages(m_repoInfo, - &filteredPackages, QInstallerTools::Exclude, updateNewComponents); + &filteredPackages, QInstallerTools::Exclude, updateNewComponents, packagesUpdatedWithSha); if (updateNewComponents) { //Verify that component B exists as that is not updated if (createSplitMetadata) { @@ -119,11 +119,11 @@ private: void verifyComponentRepository(const QString &componentAVersion, bool hasComponentMeta) { const QString content = "%1content.7z"; - const QString contentSha = "%1content.7z.sha1"; + const QString contentSha1 = "%1content.7z.sha1"; const QString meta = "%1meta.7z"; QStringList componentA; QStringList componentB; - componentA << qPrintable(content.arg(componentAVersion)) << qPrintable(contentSha.arg(componentAVersion)); + componentA << qPrintable(content.arg(componentAVersion)) << qPrintable(contentSha1.arg(componentAVersion)); componentB << "1.0.0content.7z" << "1.0.0content.7z.sha1"; if (hasComponentMeta) { componentA << qPrintable(meta.arg(componentAVersion)); @@ -257,6 +257,20 @@ private: QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(m_repoInfo.repositoryDir))); } + void verifyComponentShaUpdate(int shaUpdateComponents) + { + QString updatesXmlFile(m_repoInfo.repositoryDir + QDir::separator() + "Updates.xml"); + QFile file(updatesXmlFile); + QDomDocument dom; + + QVERIFY(file.open(QIODevice::ReadOnly)); + QVERIFY(dom.setContent(&file)); + file.close(); + QCOMPARE(dom.elementsByTagName("ContentSha1").count(), shaUpdateComponents); + VerifyInstaller::verifyFileContent(updatesXmlFile, + "<ContentSha1>059e5ed8cd3a1fbca08cccfa4075265192603e3f</ContentSha1>"); + } + private slots: void init() { @@ -305,6 +319,26 @@ private slots: verifyUniteMetadata("1.0.0"); } + void testWithComponentShaUpdate() + { + ignoreMessagesForComponentSha(QStringList () << "A" << "B", false); + generateRepo(true, false, false, QStringList () << "A"); + + verifyComponentRepository("1.0.0", true); + verifyComponentMetaUpdatesXml(); + verifyComponentShaUpdate(1); + } + + void testWithTwoComponentsShaUpdate() + { + ignoreMessagesForComponentSha(QStringList () << "A" << "B", false); + generateRepo(true, false, false, QStringList () << "A" << "B"); + + verifyComponentRepository("1.0.0", true); + verifyComponentMetaUpdatesXml(); + verifyComponentShaUpdate(2); + } + void testUpdateNewComponents() { // Create 'base' repository which will be updated diff --git a/tools/repogen/repogen.cpp b/tools/repogen/repogen.cpp index 33cf6a3cd..b630f8cd3 100644 --- a/tools/repogen/repogen.cpp +++ b/tools/repogen/repogen.cpp @@ -99,6 +99,7 @@ int main(int argc, char** argv) QStringList filteredPackages; bool updateExistingRepository = false; QInstallerTools::RepositoryInfo repoInfo; + QStringList packagesUpdatedWithSha; QInstallerTools::FilterType filterType = QInstallerTools::Exclude; bool remove = false; bool updateExistingRepositoryWithNewComponents = false; @@ -192,8 +193,11 @@ int main(int argc, char** argv) } else if (args.first() == QLatin1String("--component-metadata")) { createUnifiedMetadata = false; args.removeFirst(); - } - else { + } else if (args.first() == QLatin1String("--sha-update") || args.first() == QLatin1String("-s")) { + args.removeFirst(); + packagesUpdatedWithSha = args.first().split(QLatin1Char(',')); + args.removeFirst(); + } else { printUsage(); return 1; } @@ -233,7 +237,7 @@ int main(int argc, char** argv) } QInstallerTools::PackageInfoVector packages = QInstallerTools::collectPackages(repoInfo, - &filteredPackages, filterType, updateExistingRepositoryWithNewComponents); + &filteredPackages, filterType, updateExistingRepositoryWithNewComponents, packagesUpdatedWithSha); if (packages.isEmpty()) { std::cout << QString::fromLatin1("Cannot find components to update \"%1\".") .arg(repoInfo.repositoryDir) << std::endl; |