summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--Changelog9
-rw-r--r--coin/instructions/make_instructions.yaml22
-rw-r--r--dist/packages/org.qtproject.ifw.binaries/meta/package.xml4
-rw-r--r--dist/packages/org.qtproject.ifw/meta/package.xml4
-rw-r--r--installerfw.pri6
-rw-r--r--src/libs/installer/commandlineparser.cpp4
-rw-r--r--src/libs/installer/component.cpp10
-rw-r--r--src/libs/installer/directoryguard.cpp4
-rw-r--r--src/libs/installer/extractarchiveoperation.cpp18
-rw-r--r--src/libs/installer/fileutils.cpp46
-rw-r--r--src/libs/installer/fileutils.h1
-rw-r--r--src/libs/installer/installercalculator.cpp10
-rw-r--r--src/libs/installer/licenseoperation.cpp3
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp23
-rw-r--r--src/libs/installer/uninstallercalculator.cpp3
-rw-r--r--src/sdk/installerbase.cpp20
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data.qrc1
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/subdirs.7zbin0 -> 18715 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp52
20 files changed, 173 insertions, 69 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 560bbf5ce..95fc3f4da 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,2 +1,2 @@
-VERSION=4.4.1
+VERSION=4.4.2
CONFIG=prepare_docs qt_docs_targets $$CONFIG
diff --git a/Changelog b/Changelog
index adaa00a8a..da5f393c2 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,12 @@
+4.4.2
+- Fix uninstallation of needed virtual components
+- Attach to squish only when the port is separately given (QTIFW-2746)
+- Windows: fix installation error with concurrent Extract operations (QTIFW-2752)
+- Uninstaller remove target directory if it is empty (QTIFW-884)
+- Uninstaller remove maintenancetool's data files (QTIFW-884)
+- Do not convert newline characters in license files (QTIFW-903)
+- Set encoding to UTF-8 when writing license file (QTIFW-1436)
+
4.4.1
- Fix bug when all requested packages are not installed (QTIFW-2708)
diff --git a/coin/instructions/make_instructions.yaml b/coin/instructions/make_instructions.yaml
index c3e2452ae..357445fbb 100644
--- a/coin/instructions/make_instructions.yaml
+++ b/coin/instructions/make_instructions.yaml
@@ -77,13 +77,13 @@ instructions:
- type: ChangeDirectory
directory: "{{.InstallRoot}}/{{.AgentWorkingDir}}"
- type: ExecuteCommand
- command: "python3 {{.SourceDir}}/coin/create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir {{.SourceDir}}/IfwInstaller --target-name QtInstallerFramework-linux-x64-4.4.1.run"
+ command: "python3 {{.SourceDir}}/coin/create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir {{.SourceDir}}/IfwInstaller --target-name QtInstallerFramework-linux-x64-4.4.2.run"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to create ifw installer."
- type: Rename
- sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-linux-x64-4.4.1.run"
- targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-linux-x64-4.4.1.run"
+ sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-linux-x64-4.4.2.run"
+ targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-linux-x64-4.4.2.run"
userMessageOnFailure: "Failed to copy installer."
enable_if:
condition: and
@@ -97,7 +97,7 @@ instructions:
- type: ChangeDirectory
directory: "{{.InstallRoot}}/{{.AgentWorkingDir}}"
- type: ExecuteCommand
- command: "python3 {{.SourceDir}}/coin/create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir {{.SourceDir}}/IfwInstaller --target-name QtInstallerFramework-macOS-x64-4.4.1.app"
+ command: "python3 {{.SourceDir}}/coin/create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir {{.SourceDir}}/IfwInstaller --target-name QtInstallerFramework-macOS-x64-4.4.2.app"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to create ifw installer."
@@ -105,18 +105,18 @@ instructions:
variableName: QT_CODESIGN_IDENTITY_KEY
variableValue: "A5GTH44LYL"
- type: ExecuteCommand
- command: "{{.AgentWorkingDir}}/qtsdk/qtsdk/packaging-tools/sign_installer.py mac --file={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.4.1.app"
+ command: "{{.AgentWorkingDir}}/qtsdk/qtsdk/packaging-tools/sign_installer.py mac --file={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.4.2.app"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to sign the ifw installer"
- type: ExecuteCommand
- command: "{{.AgentWorkingDir}}/qtsdk/qtsdk/packaging-tools/notarize.py --dmg={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.4.1.dmg"
+ command: "{{.AgentWorkingDir}}/qtsdk/qtsdk/packaging-tools/notarize.py --dmg={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.4.2.dmg"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to notarize the ifw installer"
- type: Rename
- sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.4.1.dmg"
- targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-macOS-x64-4.4.1.dmg"
+ sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.4.2.dmg"
+ targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-macOS-x64-4.4.2.dmg"
userMessageOnFailure: "Failed to copy installer."
enable_if:
condition: and
@@ -130,7 +130,7 @@ instructions:
- type: ChangeDirectory
directory: "{{.SourceDir}}"
- type: ExecuteCommand
- command: "{{.Env.PYTHON3_PATH}}\\python {{.SourceDir}}\\coin\\create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir C:\\{{.SourceDir}}\\IfwInstaller --target-name QtInstallerFramework-windows-x64-4.4.1"
+ command: "{{.Env.PYTHON3_PATH}}\\python {{.SourceDir}}\\coin\\create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir C:\\{{.SourceDir}}\\IfwInstaller --target-name QtInstallerFramework-windows-x64-4.4.2"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
userMessageOnFailure: "Failed to create ifw installer."
@@ -151,8 +151,8 @@ instructions:
equals_value: Windows
- type: Rename
- sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-windows-x64-4.4.1.exe"
- targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-windows-x64-4.4.1.exe"
+ sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-windows-x64-4.4.2.exe"
+ targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-windows-x64-4.4.2.exe"
userMessageOnFailure: "Failed to copy installer."
enable_if:
condition: property
diff --git a/dist/packages/org.qtproject.ifw.binaries/meta/package.xml b/dist/packages/org.qtproject.ifw.binaries/meta/package.xml
index 73ed953f3..ca19108b7 100644
--- a/dist/packages/org.qtproject.ifw.binaries/meta/package.xml
+++ b/dist/packages/org.qtproject.ifw.binaries/meta/package.xml
@@ -2,7 +2,7 @@
<Package>
<DisplayName>Qt Installer Framework Binaries</DisplayName>
<Description>Installs the binaries, examples and help files.</Description>
- <Version>4.4.1</Version>
- <ReleaseDate>2022-06-17</ReleaseDate>
+ <Version>4.4.2</Version>
+ <ReleaseDate>2022-09-12</ReleaseDate>
<Default>True</Default>
</Package>
diff --git a/dist/packages/org.qtproject.ifw/meta/package.xml b/dist/packages/org.qtproject.ifw/meta/package.xml
index d10ae0348..3922d58f8 100644
--- a/dist/packages/org.qtproject.ifw/meta/package.xml
+++ b/dist/packages/org.qtproject.ifw/meta/package.xml
@@ -2,8 +2,8 @@
<Package>
<DisplayName>Qt Installer Framework</DisplayName>
<Description>Installs the Qt Installer Framework.</Description>
- <Version>4.4.1</Version>
- <ReleaseDate>2022-06-17</ReleaseDate>
+ <Version>4.4.2</Version>
+ <ReleaseDate>2022-09-12</ReleaseDate>
<Licenses>
<License name="The Qt Company GPL Exception 1.0" file="LICENSE.GPL3-EXCEPT" />
<License name="Third Party Code Licenses" file="3RDPARTY" />
diff --git a/installerfw.pri b/installerfw.pri
index 036ee4cc3..f09d78973 100644
--- a/installerfw.pri
+++ b/installerfw.pri
@@ -3,9 +3,9 @@
}
IFW_PRI_INCLUDED = 1
-IFW_VERSION_STR = 4.4.1
-IFW_VERSION = 0x040401
-IFW_VERSION_WIN32 = 4,4,1,0
+IFW_VERSION_STR = 4.4.2
+IFW_VERSION = 0x040402
+IFW_VERSION_WIN32 = 4,4,2,0
IFW_VERSION_STR_WIN32 = $$IFW_VERSION_STR\0
diff --git a/src/libs/installer/commandlineparser.cpp b/src/libs/installer/commandlineparser.cpp
index a04891303..b40556f6c 100644
--- a/src/libs/installer/commandlineparser.cpp
+++ b/src/libs/installer/commandlineparser.cpp
@@ -220,8 +220,8 @@ CommandLineParser::CommandLineParser()
QLatin1String("socketname, key")));
addOption(QCommandLineOption(QStringList()
<< CommandLineOptions::scSquishPortShort << CommandLineOptions::scSquishPortLong,
- QLatin1String("Give a port where Squish can connect to. If no port is given, default port 11233 is "
- "used. Note: To enable Squish support you first need to build IFW with SQUISH_PATH "
+ QLatin1String("Give a port where Squish can connect to. If no port is given, attach to squish "
+ "not done. Note: To enable Squish support you first need to build IFW with SQUISH_PATH "
"parameter where SQUISH_PATH is pointing to your Squish installation folder: "
"<path_to_qt>/bin/qmake -r SQUISH_PATH=<pat_to_squish>"),
QLatin1String("port number")));
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index c7dfa65da..37abcea8a 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -1082,10 +1082,12 @@ OperationList Component::operations(const Operation::OperationGroups &mask) cons
d->m_operations.append(d->m_licenseOperation);
}
}
- OperationList operations = d->m_operations;
- QtConcurrent::blockingFilter(operations, [&](const Operation *op) {
- return mask.testFlag(op->group());
- });
+ OperationList operations;
+ std::copy_if(d->m_operations.begin(), d->m_operations.end(), std::back_inserter(operations),
+ [&](const Operation *op) {
+ return mask.testFlag(op->group());
+ }
+ );
return operations;
}
diff --git a/src/libs/installer/directoryguard.cpp b/src/libs/installer/directoryguard.cpp
index 9c97130a4..014d213d7 100644
--- a/src/libs/installer/directoryguard.cpp
+++ b/src/libs/installer/directoryguard.cpp
@@ -28,6 +28,7 @@
#include "directoryguard.h"
+#include "fileutils.h"
#include "globals.h"
#include "errors.h"
@@ -92,8 +93,7 @@ QStringList DirectoryGuard::tryCreate()
toCreate = QDir(p);
}
- QDir dir(m_path);
- m_created = dir.mkpath(m_path);
+ m_created = QInstaller::createDirectoryWithParents(m_path);
if (!m_created) {
throw Error(QCoreApplication::translate("DirectoryGuard",
"Cannot create directory \"%1\".").arg(QDir::toNativeSeparators(m_path)));
diff --git a/src/libs/installer/extractarchiveoperation.cpp b/src/libs/installer/extractarchiveoperation.cpp
index 5ff2d9a1a..986b9d8c8 100644
--- a/src/libs/installer/extractarchiveoperation.cpp
+++ b/src/libs/installer/extractarchiveoperation.cpp
@@ -193,20 +193,7 @@ bool ExtractArchiveOperation::performOperation()
QFileInfo targetDirectoryInfo(fileDirectory);
- // We need to create the directory structure step-by-step to avoid a rare race condition
- // on Windows. QDir::mkpath() doesn't check if the leading directories were created elsewhere
- // (like from within another thread) after the initial check that the given path requires
- // creating also parent directories.
- //
- // On Unix patforms this case is handled by QFileSystemEngine though.
- QDir resourcesDir(resourcesPath);
- if (!resourcesDir.exists())
- resourcesDir.mkdir(resourcesPath);
-
- QDir resourceFileDir(targetDirectoryInfo.absolutePath());
- if (!resourceFileDir.exists())
- resourceFileDir.mkdir(targetDirectoryInfo.absolutePath());
-
+ QInstaller::createDirectoryWithParents(targetDirectoryInfo.absolutePath());
setDefaultFilePermissions(resourcesPath, DefaultFilePermissions::Executable);
setDefaultFilePermissions(targetDirectoryInfo.absolutePath(), DefaultFilePermissions::Executable);
@@ -259,6 +246,9 @@ bool ExtractArchiveOperation::undoOperation()
if (!useStringListType)
deleteDataFile(m_relocatedDataFileName);
+ // Remove the installerResources directory if it is empty.
+ QDir(targetDir).rmdir(QLatin1String("installerResources"));
+
return true;
}
diff --git a/src/libs/installer/fileutils.cpp b/src/libs/installer/fileutils.cpp
index 5a89073fc..11ae397fd 100644
--- a/src/libs/installer/fileutils.cpp
+++ b/src/libs/installer/fileutils.cpp
@@ -449,6 +449,52 @@ void QInstaller::mkpath(const QString &path)
/*!
\internal
+ Creates directory \a path including all parent directories. Return \c true on
+ success, \c false otherwise.
+
+ On Windows \c QDir::mkpath() doesn't check if the leading directories were created
+ elsewhere (i.e. in another thread) after the initial check that the given path
+ requires creating also parent directories, and returns \c false.
+
+ On Unix platforms this case is handled different by QFileSystemEngine though,
+ which checks for \c EEXIST error code in case any of the recursive directories
+ could not be created.
+
+ Compared to \c QInstaller::mkpath() and \c QDir::mkpath() this function checks if
+ each parent directory to-be-created were created elsewhere.
+*/
+bool QInstaller::createDirectoryWithParents(const QString &path)
+{
+ if (path.isEmpty())
+ return false;
+
+ QFileInfo dirInfo(path);
+ if (dirInfo.exists() && dirInfo.isDir())
+ return true;
+
+ // bail out if we are at the root directory
+ if (dirInfo.isRoot())
+ return false;
+
+ QDir dir(path);
+ if (dir.mkdir(path))
+ return true;
+
+ // mkdir failed, try to create the parent directory
+ if (!createDirectoryWithParents(dirInfo.absolutePath()))
+ return false;
+
+ // now try again
+ if (dir.mkdir(path))
+ return true;
+
+ // directory may be have also been created elsewhere
+ return (dirInfo.exists() && dirInfo.isDir());
+}
+
+/*!
+ \internal
+
Generates and returns a temporary file name. The name can start with
a template \a templ.
*/
diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h
index 8b79ce052..1114cd60c 100644
--- a/src/libs/installer/fileutils.h
+++ b/src/libs/installer/fileutils.h
@@ -89,6 +89,7 @@ private:
void INSTALLER_EXPORT mkdir(const QString &path);
void INSTALLER_EXPORT mkpath(const QString &path);
+ bool INSTALLER_EXPORT createDirectoryWithParents(const QString &path);
#ifdef Q_OS_MACOS
void INSTALLER_EXPORT mkalias(const QString &path, const QString &alias);
#endif
diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp
index e321872ee..9f8293545 100644
--- a/src/libs/installer/installercalculator.cpp
+++ b/src/libs/installer/installercalculator.cpp
@@ -107,9 +107,7 @@ bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &co
// user explicitly selects it to install. Increase the references to
// know when the component should be removed from install
const QStringList dependenciesList = component->currentDependencies();
- QSet<QString> allDependencies(dependenciesList.begin(), dependenciesList.end());
-
- foreach (const QString &dependencyComponentName, allDependencies)
+ for (const QString &dependencyComponentName : dependenciesList)
calculateComponentDependencyReferences(dependencyComponentName, component);
continue;
}
@@ -184,9 +182,8 @@ void InstallerCalculator::realAppendToInstallComponents(Component *component, co
bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version, bool revertFromInstall)
{
const QStringList dependenciesList = component->currentDependencies();
- const QSet<QString> allDependencies(dependenciesList.begin(), dependenciesList.end());
QString requiredDependencyVersion = version;
- foreach (const QString &dependencyComponentName, allDependencies) {
+ for (const QString &dependencyComponentName : dependenciesList) {
// PackageManagerCore::componentByName returns 0 if dependencyComponentName contains a
// version which is not available
Component *dependencyComponent =
@@ -345,8 +342,7 @@ void InstallerCalculator::calculateComponentDependencyReferences(const QString d
m_referenceCount.insert(dependencyComponentName, value);
const QStringList dependenciesList = dependencyComponent->currentDependencies();
- QSet<QString> allDependencies(dependenciesList.begin(), dependenciesList.end());
- for (const QString &depComponentName : allDependencies) {
+ for (const QString &depComponentName : dependenciesList) {
Component *dependencyComponent =
PackageManagerCore::componentByName(depComponentName, m_allComponents);
calculateComponentDependencyReferences(depComponentName, dependencyComponent);
diff --git a/src/libs/installer/licenseoperation.cpp b/src/libs/installer/licenseoperation.cpp
index a5a61c71f..dc863c1da 100644
--- a/src/libs/installer/licenseoperation.cpp
+++ b/src/libs/installer/licenseoperation.cpp
@@ -80,13 +80,14 @@ bool LicenseOperation::performOperation()
for (QVariantMap::const_iterator it = licenses.constBegin(); it != licenses.constEnd(); ++it) {
QFile file(targetDir + QLatin1Char('/') + it.key());
- if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
setError(UserDefinedError);
setErrorString(tr("Can not write license file \"%1\".").arg(QDir::toNativeSeparators(file.fileName())));
return false;
}
QTextStream stream(&file);
+ stream.setCodec("UTF-8");
stream << it.value().toString();
}
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 66630b98d..d90dfdec2 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -2311,7 +2311,7 @@ void PackageManagerCorePrivate::unpackComponents(const QList<Component *> &compo
runner.setType(Operation::Perform);
const QHash<Operation *, bool> results = runner.run();
- const OperationList performedOperations = backupResults.keys();
+ const OperationList performedOperations = results.keys();
QString error;
for (auto &operation : performedOperations) {
@@ -2508,6 +2508,14 @@ void PackageManagerCorePrivate::setComponentSelection(const QString &id, Qt::Che
void PackageManagerCorePrivate::deleteMaintenanceTool()
{
+ QDir resourcePath(QFileInfo(maintenanceToolName()).dir());
+ resourcePath.remove(QLatin1String("installer.dat"));
+ QDir installDir(targetDir());
+ installDir.remove(m_data.settings().maintenanceToolName() + QLatin1String(".dat"));
+ installDir.remove(QLatin1String("network.xml"));
+ installDir.remove(m_data.settings().maintenanceToolIniFile());
+ QInstaller::VerboseWriter::instance()->setFileName(QString());
+ installDir.remove(m_core->value(QLatin1String("LogFileName"), QLatin1String("InstallationLog.txt")));
#ifdef Q_OS_WIN
// Since Windows does not support that the maintenance tool deletes itself we have to go with a rather dirty
// hack. What we do is to create a batchfile that will try to remove the maintenance tool once per second. Then
@@ -2520,6 +2528,7 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
throw Error(tr("Cannot prepare removal"));
+ const bool removeTargetDir = QVariant(m_core->value(scRemoveTargetDir)).toBool();
QTextStream batch(&f);
batch << "Set fso = WScript.CreateObject(\"Scripting.FileSystemObject\")\n";
batch << "file = WScript.Arguments.Item(0)\n";
@@ -2531,10 +2540,12 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
batch << " fso.DeleteFile(file)\n";
batch << " WScript.Sleep(1000)\n";
batch << "wend\n";
-// batch << "if folder.SubFolders.Count = 0 and folder.Files.Count = 0 then\n";
+ if (!removeTargetDir)
+ batch << "if folder.SubFolders.Count = 0 and folder.Files.Count = 0 then\n";
batch << " Set folder = Nothing\n";
batch << " fso.DeleteFolder folderpath, true\n";
-// batch << "end if\n";
+ if (!removeTargetDir)
+ batch << "end if\n";
batch << "fso.DeleteFile(WScript.ScriptFullName)\n";
f.close();
@@ -2542,11 +2553,7 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
QStringList arguments;
arguments << QLatin1String("//Nologo") << batchfile; // execute the batchfile
arguments << QDir::toNativeSeparators(QFileInfo(installerBinaryPath()).absoluteFilePath());
- if (!m_performedOperationsOld.isEmpty()) {
- const Operation *const op = m_performedOperationsOld.first();
- if (op->name() == QLatin1String("Mkdir")) // the target directory name
- arguments << QDir::toNativeSeparators(QFileInfo(op->arguments().first()).absoluteFilePath());
- }
+ arguments << targetDir();
if (!QProcessWrapper::startDetached(QLatin1String("cscript"), arguments, QDir::rootPath()))
throw Error(tr("Cannot start removal"));
diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp
index 3de9f5b60..d54b5c2ab 100644
--- a/src/libs/installer/uninstallercalculator.cpp
+++ b/src/libs/installer/uninstallercalculator.cpp
@@ -205,7 +205,8 @@ void UninstallerCalculator::appendVirtualComponentsToUninstall(const bool revers
// Check if installed or about to be updated -packages are dependant on the package
const QList<Component*> installDependants = m_core->installDependants(virtualComponent);
for (Component *dependant : installDependants) {
- if (dependant->isInstalled() && !m_componentsToUninstall.contains(dependant)) {
+ if ((dependant->isInstalled() && !m_componentsToUninstall.contains(dependant))
+ || m_core->orderedComponentsToInstall().contains(dependant)) {
required = true;
break;
}
diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp
index 32df0b550..dcbf15228 100644
--- a/src/sdk/installerbase.cpp
+++ b/src/sdk/installerbase.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -98,17 +98,15 @@ int InstallerBase::run()
return status;
#ifdef ENABLE_SQUISH
- int squishPort = 11233;
if (m_parser.isSet(CommandLineOptions::scSquishPortLong)) {
- squishPort = m_parser.value(CommandLineOptions::scSquishPortLong).toInt();
- }
- if (squishPort != 0) {
- if (Squish::allowAttaching(squishPort))
- qCDebug(QInstaller::lcDeveloperBuild) << "Attaching to squish port " << squishPort << " succeeded";
- else
- qCDebug(QInstaller::lcDeveloperBuild) << "Attaching to squish failed.";
- } else {
- qCWarning(QInstaller::lcDeveloperBuild) << "Invalid squish port number: " << squishPort;
+ const int maxSquishPortNumber = 65535;
+ int squishPort = m_parser.value(CommandLineOptions::scSquishPortLong).toInt();
+ if (squishPort <= 0 || squishPort > maxSquishPortNumber) {
+ qWarning().noquote() << "Invalid Squish port:" << squishPort;
+ } else {
+ Squish::allowAttaching(squishPort);
+ qCDebug(QInstaller::lcDeveloperBuild) << "Attaching to squish port" << squishPort << "succeeded";
+ }
}
#endif
const int result = QCoreApplication::instance()->exec();
diff --git a/tests/auto/installer/extractarchiveoperationtest/data.qrc b/tests/auto/installer/extractarchiveoperationtest/data.qrc
index 974c0c6f7..a8cc1a892 100644
--- a/tests/auto/installer/extractarchiveoperationtest/data.qrc
+++ b/tests/auto/installer/extractarchiveoperationtest/data.qrc
@@ -2,6 +2,7 @@
<qresource prefix="/">
<file>data/valid.7z</file>
<file>data/invalid.7z</file>
+ <file>data/subdirs.7z</file>
<file>data/xmloperationrepository/Updates.xml</file>
<file>data/xmloperationrepository/A/1.0.0content.7z</file>
<file>data/xmloperationrepository/A/1.0.0content1.tar.gz</file>
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z b/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z
new file mode 100644
index 000000000..7f93fe106
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp
index 8ceaa76c7..89492bd94 100644
--- a/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp
+++ b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp
@@ -28,6 +28,7 @@
#include "../shared/packagemanager.h"
+#include "concurrentoperationrunner.h"
#include "init.h"
#include "extractarchiveoperation.h"
@@ -86,6 +87,57 @@ private slots:
QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
}
+ void testConcurrentExtractWithCompetingData()
+ {
+ // Suppress warnings about already deleted installerResources file
+ qInstallMessageHandler(silentTestMessageHandler);
+
+ const QString testDirectory = generateTemporaryFileName()
+ + "/subdir1/subdir2/subdir3/subdir4/subdir5/";
+
+ QStringList created7zList;
+
+ OperationList operations;
+ for (int i = 0; i < 100; ++i) {
+ ExtractArchiveOperation *op = new ExtractArchiveOperation(nullptr);
+ // We add the same data multiple times, and extract to same directory.
+ // Can't open the same archive multiple times however so it needs to
+ // be copied to unique files.
+ const QString new7zPath = generateTemporaryFileName() + ".7z";
+ QFile old7z(":///data/subdirs.7z");
+ QVERIFY(old7z.copy(new7zPath));
+
+ op->setArguments(QStringList() << new7zPath << testDirectory);
+ operations.append(op);
+ }
+ ConcurrentOperationRunner runner(&operations, Operation::Backup);
+
+ const QHash<Operation *, bool> backupResults = runner.run();
+ const OperationList backupOperations = backupResults.keys();
+
+ for (auto *operation : backupOperations)
+ QVERIFY2((backupResults.value(operation) && operation->error() == Operation::NoError),
+ operation->errorString().toLatin1());
+
+ runner.setType(Operation::Perform);
+ const QHash<Operation *, bool> results = runner.run();
+ const OperationList performedOperations = results.keys();
+
+ for (auto *operation : performedOperations)
+ QVERIFY2((results.value(operation) && operation->error() == Operation::NoError),
+ operation->errorString().toLatin1());
+
+ for (auto *operation : operations)
+ QVERIFY(operation->undoOperation());
+
+ qDeleteAll(operations);
+
+ for (const QString &archive : created7zList)
+ QFile::remove(archive);
+
+ QDir().rmdir(testDirectory);
+ }
+
void testExtractArchiveFromXML()
{
m_testDirectory = QInstaller::generateTemporaryFileName();