summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--INSTALL2
-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--doc/installerfw-getting-started.qdoc2
-rw-r--r--doc/installerfw.qdoc12
-rw-r--r--doc/noninteractive.qdoc15
-rw-r--r--doc/scripting-api/gui.qdoc7
-rw-r--r--doc/scripting.qdoc24
-rw-r--r--installerfw.pri9
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp2
-rw-r--r--src/libs/3rdparty/libarchive/archive.h6
-rw-r--r--src/libs/3rdparty/libarchive/archive_digest.c16
-rw-r--r--src/libs/3rdparty/libarchive/archive_entry.c14
-rw-r--r--src/libs/3rdparty/libarchive/archive_entry.h4
-rw-r--r--src/libs/3rdparty/libarchive/archive_hmac.c29
-rw-r--r--src/libs/3rdparty/libarchive/archive_hmac_private.h7
-rw-r--r--src/libs/3rdparty/libarchive/archive_platform.h3
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_disk_posix.c7
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_disk_windows.c18
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c6
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c2
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c2
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c8
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_cab.c6
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c2
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_lha.c6
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c24
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_rar.c10
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c9
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_tar.c20
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_xar.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_string.c6
-rw-r--r--src/libs/3rdparty/libarchive/archive_write.c8
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_disk_posix.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_disk_windows.c6
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_pax.c2
-rw-r--r--src/libs/3rdparty/libarchive/filter_fork_posix.c2
-rw-r--r--src/libs/3rdparty/libarchive/qt_attribution.json2
-rw-r--r--src/libs/ifwtools/binarycreator.cpp14
-rw-r--r--src/libs/ifwtools/binarycreator.h2
-rw-r--r--src/libs/ifwtools/rcc/rcc.cpp12
-rw-r--r--src/libs/ifwtools/repositorygen.cpp87
-rw-r--r--src/libs/ifwtools/repositorygen.h3
-rw-r--r--src/libs/installer/abstracttask.h2
-rw-r--r--src/libs/installer/binaryformatengine.cpp16
-rw-r--r--src/libs/installer/commandlineparser.cpp2
-rw-r--r--src/libs/installer/component.cpp167
-rw-r--r--src/libs/installer/component.h13
-rw-r--r--src/libs/installer/component_p.cpp9
-rw-r--r--src/libs/installer/component_p.h6
-rw-r--r--src/libs/installer/componentmodel.cpp8
-rw-r--r--src/libs/installer/componentmodel.h4
-rw-r--r--src/libs/installer/componentselectionpage_p.cpp12
-rw-r--r--src/libs/installer/concurrentoperationrunner.cpp2
-rw-r--r--src/libs/installer/createdesktopentryoperation.cpp2
-rw-r--r--src/libs/installer/createlinkoperation.cpp2
-rw-r--r--src/libs/installer/elevatedexecuteoperation.cpp9
-rw-r--r--src/libs/installer/fileutils.cpp10
-rw-r--r--src/libs/installer/genericdatacache.cpp74
-rw-r--r--src/libs/installer/genericdatacache.h5
-rw-r--r--src/libs/installer/globals.cpp4
-rw-r--r--src/libs/installer/globals.h12
-rw-r--r--src/libs/installer/installer.pro5
-rw-r--r--src/libs/installer/installercalculator.cpp10
-rw-r--r--src/libs/installer/lib7z_create.h3
-rw-r--r--src/libs/installer/lib7z_facade.cpp2
-rw-r--r--src/libs/installer/libarchivearchive.cpp2
-rw-r--r--src/libs/installer/link.cpp2
-rw-r--r--src/libs/installer/loggingutils.cpp6
-rw-r--r--src/libs/installer/loggingutils.h2
-rw-r--r--src/libs/installer/metadata.cpp40
-rw-r--r--src/libs/installer/metadata.h4
-rw-r--r--src/libs/installer/metadatajob.cpp178
-rw-r--r--src/libs/installer/metadatajob.h9
-rw-r--r--src/libs/installer/metadatajob_p.h75
-rw-r--r--src/libs/installer/packagemanagercore.cpp57
-rw-r--r--src/libs/installer/packagemanagercore.h7
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp33
-rw-r--r--src/libs/installer/packagemanagercore_p.h4
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp6
-rw-r--r--src/libs/installer/packagemanagergui.cpp42
-rw-r--r--src/libs/installer/packagemanagergui.h1
-rw-r--r--src/libs/installer/performinstallationform.cpp6
-rw-r--r--src/libs/installer/permissionsettings.cpp8
-rw-r--r--src/libs/installer/qprocesswrapper.cpp3
-rw-r--r--src/libs/installer/qtpatch.cpp6
-rw-r--r--src/libs/installer/remoteclient_p.h5
-rw-r--r--src/libs/installer/remoteobject.h4
-rw-r--r--src/libs/installer/remoteserverconnection.cpp10
-rw-r--r--src/libs/installer/repository.cpp2
-rw-r--r--src/libs/installer/repositorycategory.cpp2
-rw-r--r--src/libs/installer/scriptengine.cpp15
-rw-r--r--src/libs/installer/scriptengine.h2
-rw-r--r--src/libs/installer/settings.cpp6
-rw-r--r--src/libs/installer/settings.h2
-rw-r--r--src/libs/installer/sysinfo_win.cpp2
-rw-r--r--src/libs/installer/utils.cpp4
-rw-r--r--src/libs/installer/utils.h2
-rw-r--r--src/libs/kdtools/kdsysinfo_win.cpp12
-rw-r--r--src/libs/kdtools/lockfile_win.cpp2
-rw-r--r--src/libs/kdtools/sysinfo_x11.cpp8
-rw-r--r--src/libs/kdtools/updatefinder.cpp6
-rw-r--r--src/libs/kdtools/updateoperation.cpp2
-rw-r--r--src/libs/kdtools/updatesinfo.cpp230
-rw-r--r--src/libs/kdtools/updatesinfodata_p.h10
-rw-r--r--src/sdk/commandlineinterface.cpp2
-rw-r--r--src/sdk/installerbase.cpp4
-rw-r--r--src/sdk/main.cpp12
-rw-r--r--src/sdk/sdk.pro2
-rw-r--r--src/sdk/sdkapp.h5
-rw-r--r--src/sdk/settingsdialog.cpp7
-rw-r--r--src/sdk/settingsdialog.h2
-rw-r--r--src/sdk/settingsdialog.ui36
-rw-r--r--src/sdk/tabcontroller.cpp26
-rw-r--r--tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp2
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml10
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7zbin0 -> 1010 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/settings.qrc2
-rw-r--r--tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp70
-rw-r--r--tests/auto/installer/componentmodel/data/updates.xml2
-rw-r--r--tests/auto/installer/componentmodel/tst_componentmodel.cpp14
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml28
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml27
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/settings.qrc6
-rw-r--r--tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp28
-rw-r--r--tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp10
-rw-r--r--tests/auto/installer/scriptengine/tst_scriptengine.cpp52
-rw-r--r--tools/repogen/repogen.cpp2
135 files changed, 1386 insertions, 615 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 4109ad569..37d46dd43 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,2 +1,2 @@
-VERSION=4.5.2
+VERSION=5.0.0
CONFIG=prepare_docs qt_docs_targets $$CONFIG
diff --git a/INSTALL b/INSTALL
index 412b5063a..39d0057c2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -37,7 +37,7 @@ nmake (or 'mingw32-make') module-qtbase module-qtdeclarative module-qttools modu
Recommended configuration options for Linux:
-configure -prefix $PWD/qtbase -release -static -accessibility -qt-zlib -qt-libpng -qt-libjpeg -qt-pcre -no-glib -no-cups -no-sql-sqlite -no-qml-debug -no-opengl -no-egl -no-xinput2 -no-sm -no-icu -nomake examples -nomake tests -no-libudev
+configure -prefix $PWD/qtbase -release -static -accessibility -qt-zlib -qt-libpng -qt-libjpeg -qt-pcre -no-glib -no-cups -no-sql-sqlite -no-feature-gssapi -no-qml-debug -no-opengl -no-egl -no-xinput2 -no-sm -no-icu -nomake examples -nomake tests -no-libudev
Build Qt:
make module-qtbase module-qtdeclarative module-qttools module-qttranslations
### macOS
diff --git a/coin/instructions/make_instructions.yaml b/coin/instructions/make_instructions.yaml
index 13bfe736a..8fb4fea5a 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.5.2.run"
+ command: "python3 {{.SourceDir}}/coin/create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir {{.SourceDir}}/IfwInstaller --target-name QtInstallerFramework-linux-x64-5.0.0.run"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to create ifw installer."
- type: Rename
- sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-linux-x64-4.5.2.run"
- targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-linux-x64-4.5.2.run"
+ sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-linux-x64-5.0.0.run"
+ targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-linux-x64-5.0.0.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.5.2.app"
+ command: "python3 {{.SourceDir}}/coin/create_ifw_installer.py --src-dir {{.SourceDir}} --bld-dir {{.SourceDir}} --target-dir {{.SourceDir}}/IfwInstaller --target-name QtInstallerFramework-macOS-x64-5.0.0.app"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to create ifw installer."
@@ -117,18 +117,18 @@ instructions:
maxTimeBetweenOutput: 600
userMessageOnFailure: "Failed to install Pipenv requirements"
- type: ExecuteCommand
- command: "python3 -m pipenv run python sign_installer.py mac --file={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.5.2.app"
+ command: "python3 -m pipenv run python sign_installer.py mac --file={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-5.0.0.app"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to sign the ifw installer"
- type: ExecuteCommand
- command: "python3 -m pipenv run python notarize.py --dmg={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.5.2.dmg"
+ command: "python3 -m pipenv run python notarize.py --dmg={{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-5.0.0.dmg"
maxTimeInSeconds: 36000
maxTimeBetweenOutput: 3600
userMessageOnFailure: "Failed to notarize the ifw installer"
- type: Rename
- sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-4.5.2.dmg"
- targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-macOS-x64-4.5.2.dmg"
+ sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-macOS-x64-5.0.0.dmg"
+ targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-macOS-x64-5.0.0.dmg"
userMessageOnFailure: "Failed to copy installer."
enable_if:
condition: and
@@ -142,7 +142,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.5.2"
+ 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-5.0.0"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
userMessageOnFailure: "Failed to create ifw installer."
@@ -163,8 +163,8 @@ instructions:
equals_value: Windows
- type: Rename
- sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-windows-x64-4.5.2.exe"
- targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-windows-x64-4.5.2.exe"
+ sourcePath: "{{.SourceDir}}/IfwInstaller/QtInstallerFramework-windows-x64-5.0.0.exe"
+ targetPath: "{{.InstallRoot}}/{{.AgentWorkingDir}}/QtInstallerFramework-windows-x64-5.0.0.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 eb838e1b3..ce8c45e0c 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.5.2</Version>
- <ReleaseDate>2022-01-13</ReleaseDate>
+ <Version>5.0.0</Version>
+ <ReleaseDate>2022-07-07</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 b0dd4ee57..278078e68 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.5.2</Version>
- <ReleaseDate>2022-01-13</ReleaseDate>
+ <Version>5.0.0</Version>
+ <ReleaseDate>2022-07-07</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/doc/installerfw-getting-started.qdoc b/doc/installerfw-getting-started.qdoc
index f3fe3f0d6..9da288694 100644
--- a/doc/installerfw-getting-started.qdoc
+++ b/doc/installerfw-getting-started.qdoc
@@ -91,7 +91,7 @@
We recommend that you use the following configuration options for Linux:
\code
- configure -prefix $PWD/qtbase -release -static -accessibility -qt-zlib -qt-libpng -qt-libjpeg -qt-pcre -no-glib -no-cups -no-sql-sqlite -no-qml-debug -no-opengl -no-egl -no-xinput2 -no-sm -no-icu -nomake examples -nomake tests -no-libudev
+ configure -prefix $PWD/qtbase -release -static -accessibility -qt-zlib -qt-libpng -qt-libjpeg -qt-pcre -no-glib -no-cups -no-sql-sqlite -no-feature-gssapi -no-qml-debug -no-opengl -no-egl -no-xinput2 -no-sm -no-icu -nomake examples -nomake tests -no-libudev
\endcode
Build Qt:
diff --git a/doc/installerfw.qdoc b/doc/installerfw.qdoc
index 652fcc65d..a0fb9d848 100644
--- a/doc/installerfw.qdoc
+++ b/doc/installerfw.qdoc
@@ -949,7 +949,15 @@
\row
\li Script
\li File name of a script being loaded. Optional.
- For more information, see \l{Adding Operations}.
+ Specifying the \c {postLoad="true"} attribute will cause the script
+ to be loaded only to the component that is selected for update or
+ install. With the attribute, the script is loaded right before the
+ component installation starts. This will speed up the installer
+ if there are large amounts of components with install scripts in the
+ repository. Make sure the script does not contain anything that needs
+ to be evaluated before the install tree view is shown.
+ For more information, see \l{Adding Operations} and
+ \l{Using postLoad in component script}.
\row
\li UserInterfaces
\li List of pages to load. To add several pages, add several
@@ -1877,7 +1885,7 @@
\section2 Getting the Maintenance Tool
The maintenance tool for Linux and Windows is the same as the \c installerbase
- executable located in your Qt Installer Framework's \c installation bin folder.
+ executable located in your Qt Installer Framework's installation \c bin folder.
For macOS the maintenance tool app bundle can be created using the \c binarycreator
tool with the command line switch \c --mt or \c --create-maintenancetool. The
name of the macOS app bundle can be configured in config.xml using
diff --git a/doc/noninteractive.qdoc b/doc/noninteractive.qdoc
index 5576f93f3..15c85d28a 100644
--- a/doc/noninteractive.qdoc
+++ b/doc/noninteractive.qdoc
@@ -80,6 +80,21 @@
For more information about the JavaScript global objects that you can use
in control scripts, see \l{Scripting API}.
+ In addition to the predefined global objects, the scripting API supports working
+ with other objects derived from \c QObject. In the above code example the
+ \c{gui.currentPageWidget()} method returns a widget of type \c QWidget.
+
+ The scripting API makes use of Qt's object trees. Widgets derived from \c QObject export
+ their named child objects as properties for the JavaScript object, where the name of the
+ property is the same as the child object's \c{QObject::objectName}. The default properties
+ and their access functions of objects derived from \c QObject can also be used in the scripts.
+
+ For example, in the above code the \c MessageLabel object from class \c QLabel is a child
+ of the \c widget. The \c setText() is the setter access function for its \c QLabel::text property.
+
+ In addition to properties, the signals and public slots of objects derived from \c QObject
+ can be used in both controller and component scripts.
+
\section1 Predefined Installer Pages
The QInstaller JavaScript object provides access to the following predefined
diff --git a/doc/scripting-api/gui.qdoc b/doc/scripting-api/gui.qdoc
index 7047cfe0e..63a76b60b 100644
--- a/doc/scripting-api/gui.qdoc
+++ b/doc/scripting-api/gui.qdoc
@@ -58,6 +58,13 @@
*/
/*!
+ \qmlsignal gui::aboutApplicationClicked()
+
+ This signal is emitted when the about application menu and dialog
+ on macOS are shown.
+*/
+
+/*!
\qmlsignal gui::settingsButtonClicked()
This signal is emitted when the \uicontrol Settings button is clicked.
diff --git a/doc/scripting.qdoc b/doc/scripting.qdoc
index bb547a0d6..8854442fa 100644
--- a/doc/scripting.qdoc
+++ b/doc/scripting.qdoc
@@ -375,4 +375,28 @@
\li ApplicationsDirX64
\li \c {C:\Program Files}
\endtable
+
+ \section1 Using postLoad in Component Script
+ By default, component scripts are evaluated before the install tree view
+ is shown. This can have performance cost if there is a huge amount of
+ components with component scripts. The \c postLoad attribute introduces a way
+ to evaluate the component script right before installation starts, only for
+ the components that are selected for installation or update:
+ \code
+ <Script postLoad="true">my_install_script.qs</Script>
+ \endcode
+ Whether \c postLoad can be set to \c true must be considered case by case,
+ depending on the contents of the script. For example, if the script contents
+ affect the install tree view, like setting \c <Default> to \c true, setting
+ new dependencies, or adding new wizard pages, \c postLoad must not be used or
+ it must be set to \c false. If the script contains only methods
+ that are run during the installation, \c postLoad can be set to \c true. For
+ example, all overridden \c operation functions are run during installation.
+ For more information, see \l {Adding Operations to Components}. If you are not
+ sure when to use \c postLoad, then don't use it. The performance cost is
+ huge only when there are thousands of scripts to be evaluated.
+
+ Both \c <Script postLoad="true"> and \c <Script> tags can be used at the same time.
+ This means that one component can have one script that is evaluated when the installation
+ starts and another script that is evaluated before the install tree view is shown.
*/
diff --git a/installerfw.pri b/installerfw.pri
index 0c8504060..66b66f9dc 100644
--- a/installerfw.pri
+++ b/installerfw.pri
@@ -3,9 +3,9 @@
}
IFW_PRI_INCLUDED = 1
-IFW_VERSION_STR = 4.5.2
-IFW_VERSION = 0x040502
-IFW_VERSION_WIN32 = 4,5,2,0
+IFW_VERSION_STR = 5.0.0
+IFW_VERSION = 0x050000
+IFW_VERSION_WIN32 = 5,0,0,0
IFW_VERSION_STR_WIN32 = $$IFW_VERSION_STR\0
@@ -136,8 +136,9 @@ macx:LIBS += -framework Carbon -framework Security
QT += uitools core-private
CONFIG(static, static|shared) {
- win32:QT += winextras
+ win32:lessThan(QT_MAJOR_VERSION, 6):QT += winextras
QT += concurrent network qml xml
+ greaterThan(QT_MAJOR_VERSION, 5):QT += core5compat
}
CONFIG += depend_includepath no_private_qt_headers_warning c++11
win32:CONFIG += console
diff --git a/src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
index 37f4fe991..e101db855 100644
--- a/src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
@@ -37,7 +37,7 @@ void SplitCommandLine(const UString &s, UStringVector &parts)
parts.Clear();
const QString cmdLine = QString::fromStdWString(static_cast<const wchar_t*>(s));
- const QStringList args = cmdLine.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
+ const QStringList args = cmdLine.simplified().split(QLatin1Char(' '), Qt::SkipEmptyParts);
foreach (const QString &arg, args)
parts.Add(arg.toStdWString().c_str());
}
diff --git a/src/libs/3rdparty/libarchive/archive.h b/src/libs/3rdparty/libarchive/archive.h
index 46041eb08..217ac1989 100644
--- a/src/libs/3rdparty/libarchive/archive.h
+++ b/src/libs/3rdparty/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3006001
+#define ARCHIVE_VERSION_NUMBER 3006002
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -120,6 +120,8 @@ typedef ssize_t la_ssize_t;
# define __LA_DECL __declspec(dllimport)
# endif
# endif
+#elif defined __LIBARCHIVE_ENABLE_VISIBILITY
+# define __LA_DECL __attribute__((visibility("default")))
#else
/* Static libraries or non-Windows needs no special declaration. */
# define __LA_DECL
@@ -155,7 +157,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.6.1"
+#define ARCHIVE_VERSION_ONLY_STRING "3.6.2"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
diff --git a/src/libs/3rdparty/libarchive/archive_digest.c b/src/libs/3rdparty/libarchive/archive_digest.c
index a7bd5f028..3361b19ad 100644
--- a/src/libs/3rdparty/libarchive/archive_digest.c
+++ b/src/libs/3rdparty/libarchive/archive_digest.c
@@ -49,16 +49,16 @@
* Initialize a Message digest.
*/
static int
-win_crypto_init(Digest_CTX *ctx, ALG_ID algId)
+win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId)
{
ctx->valid = 0;
if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ prov, CRYPT_VERIFYCONTEXT)) {
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
return (ARCHIVE_FAILED);
if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
- PROV_RSA_FULL, CRYPT_NEWKEYSET))
+ prov, CRYPT_NEWKEYSET))
return (ARCHIVE_FAILED);
}
@@ -276,7 +276,7 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
static int
__archive_md5init(archive_md5_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_MD5));
+ return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
}
static int
@@ -659,7 +659,7 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
static int
__archive_sha1init(archive_sha1_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA1));
+ return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
}
static int
@@ -919,7 +919,7 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
static int
__archive_sha256init(archive_sha256_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA_256));
+ return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
}
static int
@@ -1155,7 +1155,7 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
static int
__archive_sha384init(archive_sha384_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA_384));
+ return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
}
static int
@@ -1415,7 +1415,7 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
static int
__archive_sha512init(archive_sha512_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA_512));
+ return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
}
static int
diff --git a/src/libs/3rdparty/libarchive/archive_entry.c b/src/libs/3rdparty/libarchive/archive_entry.c
index ca7a4bdb5..ae6dc3336 100644
--- a/src/libs/3rdparty/libarchive/archive_entry.c
+++ b/src/libs/3rdparty/libarchive/archive_entry.c
@@ -568,6 +568,13 @@ archive_entry_nlink(struct archive_entry *entry)
return (entry->ae_stat.aest_nlink);
}
+/* Instead, our caller could have chosen a specific encoding
+ * (archive_mstring_get_mbs, archive_mstring_get_utf8,
+ * archive_mstring_get_wcs). So we should try multiple
+ * encodings. Try mbs first because of history, even though
+ * utf8 might be better for pathname portability.
+ * Also omit wcs because of type mismatch (char * versus wchar *)
+ */
const char *
archive_entry_pathname(struct archive_entry *entry)
{
@@ -575,6 +582,13 @@ archive_entry_pathname(struct archive_entry *entry)
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_pathname, &p) == 0)
return (p);
+#if HAVE_EILSEQ /*{*/
+ if (errno == EILSEQ) {
+ if (archive_mstring_get_utf8(
+ entry->archive, &entry->ae_pathname, &p) == 0)
+ return (p);
+ }
+#endif /*}*/
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
diff --git a/src/libs/3rdparty/libarchive/archive_entry.h b/src/libs/3rdparty/libarchive/archive_entry.h
index d5cb30de7..e579e9f33 100644
--- a/src/libs/3rdparty/libarchive/archive_entry.h
+++ b/src/libs/3rdparty/libarchive/archive_entry.h
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3006001
+#define ARCHIVE_VERSION_NUMBER 3006002
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -122,6 +122,8 @@ typedef ssize_t la_ssize_t;
# define __LA_DECL __declspec(dllimport)
# endif
# endif
+#elif defined __LIBARCHIVE_ENABLE_VISIBILITY
+# define __LA_DECL __attribute__((visibility("default")))
#else
/* Static libraries on all platforms and shared libraries on non-Windows. */
# define __LA_DECL
diff --git a/src/libs/3rdparty/libarchive/archive_hmac.c b/src/libs/3rdparty/libarchive/archive_hmac.c
index 2a9d04c8d..012fe1596 100644
--- a/src/libs/3rdparty/libarchive/archive_hmac.c
+++ b/src/libs/3rdparty/libarchive/archive_hmac.c
@@ -230,10 +230,23 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ OSSL_PARAM params[2];
+
+ EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ *ctx = EVP_MAC_CTX_new(mac);
+ if (*ctx == NULL)
+ return -1;
+ EVP_MAC_free(mac);
+ params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0);
+ params[1] = OSSL_PARAM_construct_end();
+ EVP_MAC_init(*ctx, key, key_len, params);
+#else
*ctx = HMAC_CTX_new();
if (*ctx == NULL)
return -1;
HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL);
+#endif
return 0;
}
@@ -241,22 +254,38 @@ static void
__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
size_t data_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_update(*ctx, data, data_len);
+#else
HMAC_Update(*ctx, data, data_len);
+#endif
}
static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ size_t len = *out_len;
+#else
unsigned int len = (unsigned int)*out_len;
+#endif
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_final(*ctx, out, &len, *out_len);
+#else
HMAC_Final(*ctx, out, &len);
+#endif
*out_len = len;
}
static void
__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_CTX_free(*ctx);
+#else
HMAC_CTX_free(*ctx);
+#endif
*ctx = NULL;
}
diff --git a/src/libs/3rdparty/libarchive/archive_hmac_private.h b/src/libs/3rdparty/libarchive/archive_hmac_private.h
index 13a67d495..50044a045 100644
--- a/src/libs/3rdparty/libarchive/archive_hmac_private.h
+++ b/src/libs/3rdparty/libarchive/archive_hmac_private.h
@@ -74,9 +74,16 @@ typedef mbedtls_md_context_t archive_hmac_sha1_ctx;
typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx;
#elif defined(HAVE_LIBCRYPTO)
+#include <openssl/opensslv.h>
+#include <openssl/hmac.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+typedef EVP_MAC_CTX *archive_hmac_sha1_ctx;
+
+#else
#include "archive_openssl_hmac_private.h"
typedef HMAC_CTX* archive_hmac_sha1_ctx;
+#endif
#else
diff --git a/src/libs/3rdparty/libarchive/archive_platform.h b/src/libs/3rdparty/libarchive/archive_platform.h
index 3426975de..1038932ac 100644
--- a/src/libs/3rdparty/libarchive/archive_platform.h
+++ b/src/libs/3rdparty/libarchive/archive_platform.h
@@ -195,8 +195,9 @@
/*
* glibc 2.24 deprecates readdir_r
+ * bionic c deprecates readdir_r too
*/
-#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
+#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) && (!defined(__ANDROID__))
#define USE_READDIR_R 1
#else
#undef USE_READDIR_R
diff --git a/src/libs/3rdparty/libarchive/archive_read_disk_posix.c b/src/libs/3rdparty/libarchive/archive_read_disk_posix.c
index 2b39e672b..5a94ec5d4 100644
--- a/src/libs/3rdparty/libarchive/archive_read_disk_posix.c
+++ b/src/libs/3rdparty/libarchive/archive_read_disk_posix.c
@@ -34,9 +34,6 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
-#ifdef HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -54,6 +51,8 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
+#elif HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
#endif
/*
* Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
@@ -2103,6 +2102,8 @@ tree_push(struct tree *t, const char *path, int filesystem_id,
struct tree_entry *te;
te = calloc(1, sizeof(*te));
+ if (te == NULL)
+ __archive_errx(1, "Out of memory");
te->next = t->stack;
te->parent = t->current;
if (te->parent)
diff --git a/src/libs/3rdparty/libarchive/archive_read_disk_windows.c b/src/libs/3rdparty/libarchive/archive_read_disk_windows.c
index ea32e2aac..f9d139557 100644
--- a/src/libs/3rdparty/libarchive/archive_read_disk_windows.c
+++ b/src/libs/3rdparty/libarchive/archive_read_disk_windows.c
@@ -418,8 +418,9 @@ la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype)
FILE_FLAG_OPEN_REPARSE_POINT;
int ret;
- h = CreateFileW(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, flag,
- NULL);
+ h = CreateFileW(path, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+ OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
return (-1);
@@ -1073,7 +1074,9 @@ next_entry(struct archive_read_disk *a, struct tree *t,
else
flags |= FILE_FLAG_SEQUENTIAL_SCAN;
t->entry_fh = CreateFileW(tree_current_access_path(t),
- GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, flags, NULL);
if (t->entry_fh == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
@@ -2046,7 +2049,8 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
if (sim_lstat && tree_current_is_physical_link(t))
flag |= FILE_FLAG_OPEN_REPARSE_POINT;
- h = CreateFileW(tree_current_access_path(t), 0, FILE_SHARE_READ, NULL,
+ h = CreateFileW(tree_current_access_path(t), 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
@@ -2275,7 +2279,8 @@ archive_read_disk_entry_from_file(struct archive *_a,
} else
desiredAccess = GENERIC_READ;
- h = CreateFileW(path, desiredAccess, FILE_SHARE_READ, NULL,
+ h = CreateFileW(path, desiredAccess,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
@@ -2337,7 +2342,8 @@ archive_read_disk_entry_from_file(struct archive *_a,
if (fd >= 0) {
h = (HANDLE)_get_osfhandle(fd);
} else {
- h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
+ h = CreateFileW(path, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c
index ae0b08003..1e99542d7 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c
@@ -450,7 +450,9 @@ lz4_filter_read_descriptor(struct archive_read_filter *self)
chsum = (chsum >> 8) & 0xff;
chsum_verifier = read_buf[descriptor_bytes-1] & 0xff;
if (chsum != chsum_verifier)
+#ifndef DONT_FAIL_ON_CRC_ERROR
goto malformed_error;
+#endif
__archive_read_filter_consume(self->upstream, descriptor_bytes);
@@ -521,7 +523,9 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
unsigned int chsum_block =
archive_le32dec(read_buf + 4 + compressed_size);
if (chsum != chsum_block)
+#ifndef DONT_FAIL_ON_CRC_ERROR
goto malformed_error;
+#endif
}
@@ -652,10 +656,12 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p)
state->xxh32_state);
state->xxh32_state = NULL;
if (checksum != checksum_stream) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC,
"lz4 stream checksum error");
return (ARCHIVE_FATAL);
+#endif
}
} else if (ret > 0)
__archive_xxhash.XXH32_update(state->xxh32_state,
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c
index afd2d4d0c..4ebdd3bf3 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c
@@ -283,7 +283,9 @@ consume_header(struct archive_read_filter *self)
else
checksum = adler32(adler32(0, NULL, 0), p, len);
if (archive_be32dec(p + len) != checksum)
+#ifndef DONT_FAIL_ON_CRC_ERROR
goto corrupted;
+#endif
__archive_read_filter_consume(self->upstream, len + 4);
if (flags & EXTRA_FIELD) {
/* Skip extra field */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c
index 32ae0be92..e313d39c0 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c
@@ -612,9 +612,11 @@ lzip_tail(struct archive_read_filter *self)
/* Check the crc32 value of the uncompressed data of the current
* member */
if (state->crc32 != archive_le32dec(f)) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
"Lzip: CRC32 error");
return (ARCHIVE_FAILED);
+#endif
}
/* Check the uncompressed size of the current member */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c b/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c
index 564ba514a..0ba4bee35 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c
@@ -776,7 +776,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
}
/* Set up a more descriptive format name. */
- sprintf(zip->format_name, "7-Zip");
+ snprintf(zip->format_name, sizeof(zip->format_name), "7-Zip");
a->archive.archive_format_name = zip->format_name;
return (ret);
@@ -2857,8 +2857,10 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
/* CRC check. */
if (crc32(0, (const unsigned char *)p + 12, 20)
!= archive_le32dec(p + 8)) {
+#ifdef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, -1, "Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
next_header_offset = archive_le64dec(p + 12);
@@ -2908,8 +2910,10 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
/* Check the EncodedHeader CRC.*/
if (r == 0 && zip->header_crc32 != next_header_crc) {
archive_set_error(&a->archive, -1,
+#ifndef DONT_FAIL_ON_CRC_ERROR
"Damaged 7-Zip archive");
r = -1;
+#endif
}
if (r == 0) {
if (zip->si.ci.folders[0].digest_defined)
@@ -2960,9 +2964,11 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
/* Check the Header CRC.*/
if (check_header_crc && zip->header_crc32 != next_header_crc) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, -1,
"Malformed 7-Zip archive");
return (ARCHIVE_FATAL);
+#endif
}
break;
default:
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c b/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c
index 950f3d254..4d5029b1b 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c
@@ -996,7 +996,7 @@ archive_read_format_cab_read_header(struct archive_read *a,
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
/* Set up a more descriptive format name. */
- sprintf(cab->format_name, "CAB %d.%d (%s)",
+ snprintf(cab->format_name, sizeof(cab->format_name), "CAB %d.%d (%s)",
hd->major, hd->minor, cab->entry_cffolder->compname);
a->archive.archive_format_name = cab->format_name;
@@ -1134,7 +1134,7 @@ cab_checksum_update(struct archive_read *a, size_t bytes)
}
if (sumbytes) {
int odd = sumbytes & 3;
- if (sumbytes - odd > 0)
+ if ((int)(sumbytes - odd) > 0)
cfdata->sum_calculated = cab_checksum_cfdata_4(
p, sumbytes - odd, cfdata->sum_calculated);
if (odd)
@@ -1171,12 +1171,14 @@ cab_checksum_finish(struct archive_read *a)
cfdata->sum_calculated = cab_checksum_cfdata(
cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated);
if (cfdata->sum_calculated != cfdata->sum) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes",
cab->entry_cffolder->cfdata_index -1,
cfdata->sum, cfdata->sum_calculated,
cfdata->compressed_size);
return (ARCHIVE_FAILED);
+#endif
}
return (ARCHIVE_OK);
}
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c b/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c
index cd7f92f46..33bf330cb 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c
@@ -1757,7 +1757,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
size_t name_len;
const unsigned char *rr_start, *rr_end;
const unsigned char *p;
- size_t dr_len;
+ size_t dr_len = 0;
uint64_t fsize, offset;
int32_t location;
int flags;
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c b/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c
index bff0f01f4..bcfd42e1d 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c
@@ -739,7 +739,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
if (lha->directory || lha->compsize == 0)
lha->end_of_entry = 1;
- sprintf(lha->format_name, "lha -%c%c%c-",
+ snprintf(lha->format_name, sizeof(lha->format_name), "lha -%c%c%c-",
lha->method[0], lha->method[1], lha->method[2]);
a->archive.archive_format_name = lha->format_name;
@@ -1039,9 +1039,11 @@ lha_read_file_header_2(struct archive_read *a, struct lha *lha)
}
if (header_crc != lha->header_crc) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"LHa header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
return (err);
}
@@ -1107,9 +1109,11 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha)
return (err);
if (header_crc != lha->header_crc) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"LHa header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
return (err);
invalid:
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c b/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c
index 4a2816325..2bc3ba066 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c
@@ -994,9 +994,11 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
struct mtree_entry *alt;
alt = (struct mtree_entry *)__archive_rb_tree_find_node(
&mtree->rbtree, entry->name);
- while (alt->next_dup)
- alt = alt->next_dup;
- alt->next_dup = entry;
+ if (alt != NULL) {
+ while (alt->next_dup)
+ alt = alt->next_dup;
+ alt->next_dup = entry;
+ }
}
}
@@ -1071,7 +1073,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
continue;
/* Non-printable characters are not allowed */
for (s = p;s < p + len - 1; s++) {
- if (!isprint((unsigned char)*s)) {
+ if (!isprint((unsigned char)*s) && *s != '\t') {
r = ARCHIVE_FATAL;
break;
}
@@ -1250,9 +1252,17 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
archive_entry_filetype(entry) == AE_IFDIR) {
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(mtree->fd);
- if (mtree->fd == -1 &&
- (errno != ENOENT ||
- archive_strlen(&mtree->contents_name) > 0)) {
+ if (mtree->fd == -1 && (
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /*
+ * On Windows, attempting to open a file with an
+ * invalid name result in EINVAL (Error 22)
+ */
+ (errno != ENOENT && errno != EINVAL)
+#else
+ errno != ENOENT
+#endif
+ || archive_strlen(&mtree->contents_name) > 0)) {
archive_set_error(&a->archive, errno,
"Can't open %s", path);
r = ARCHIVE_WARN;
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c b/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c
index f9cbe2a88..793e8e985 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c
@@ -1007,9 +1007,11 @@ archive_read_format_rar_read_header(struct archive_read *a,
crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
__archive_read_consume(a, skip);
break;
@@ -1065,9 +1067,11 @@ archive_read_format_rar_read_header(struct archive_read *a,
skip -= to_read;
}
if ((crc32_val & 0xffff) != crc32_expected) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
if (head_type == ENDARC_HEAD)
return (ARCHIVE_EOF);
@@ -1432,9 +1436,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
/* File Header CRC check. */
crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7));
if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
/* If no CRC error, Go on parsing File Header. */
p = h;
@@ -1952,9 +1958,11 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
*size = 0;
*offset = rar->offset;
if (rar->file_crc != rar->crc_calculated) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"File CRC error");
return (ARCHIVE_FATAL);
+#endif
}
rar->entry_eof = 1;
return (ARCHIVE_EOF);
@@ -2045,9 +2053,11 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*size = 0;
*offset = rar->offset;
if (rar->file_crc != rar->crc_calculated) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"File CRC error");
return (ARCHIVE_FATAL);
+#endif
}
rar->entry_eof = 1;
return (ARCHIVE_EOF);
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c b/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c
index a3cfa72e7..38979cbe9 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c
@@ -2821,11 +2821,13 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
^ (uint8_t) (*block_size >> 16);
if(calculated_cksum != hdr->block_cksum) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Block checksum error: got 0x%x, expected 0x%x",
hdr->block_cksum, calculated_cksum);
return ARCHIVE_FATAL;
+#endif
}
return ARCHIVE_OK;
@@ -3911,6 +3913,13 @@ static int do_unpack(struct archive_read* a, struct rar5* rar,
case GOOD:
/* fallthrough */
case BEST:
+ /* No data is returned here. But because a sparse-file aware
+ * caller (like archive_read_data_into_fd) may treat zero-size
+ * as a sparse file block, we need to update the offset
+ * accordingly. At this point the decoder doesn't have any
+ * pending uncompressed data blocks, so the current position in
+ * the output file should be last_write_ptr. */
+ if (offset) *offset = rar->cstate.last_write_ptr;
return uncompress_file(a);
default:
archive_set_error(&a->archive,
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c b/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c
index bfdad7f87..93c3fd585 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c
@@ -407,14 +407,13 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
/*
* Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
*/
- if (bid > 0 && (
- validate_number_field(header->mode, sizeof(header->mode)) == 0
+ if (validate_number_field(header->mode, sizeof(header->mode)) == 0
|| validate_number_field(header->uid, sizeof(header->uid)) == 0
|| validate_number_field(header->gid, sizeof(header->gid)) == 0
|| validate_number_field(header->mtime, sizeof(header->mtime)) == 0
|| validate_number_field(header->size, sizeof(header->size)) == 0
|| validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
- || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
+ || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0) {
bid = 0;
}
@@ -2108,6 +2107,21 @@ pax_attribute(struct archive_read *a, struct tar *tar,
/* "size" is the size of the data in the entry. */
tar->entry_bytes_remaining
= tar_atol10(value, strlen(value));
+ if (tar->entry_bytes_remaining < 0) {
+ tar->entry_bytes_remaining = 0;
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Tar size attribute is negative");
+ return (ARCHIVE_FATAL);
+ }
+ if (tar->entry_bytes_remaining == INT64_MAX) {
+ /* Note: tar_atol returns INT64_MAX on overflow */
+ tar->entry_bytes_remaining = 0;
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Tar size attribute overflow");
+ return (ARCHIVE_FATAL);
+ }
/*
* The "size" pax header keyword always overrides the
* "size" field in the tar header.
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c b/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c
index 503ff58b9..ec5b06eda 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c
@@ -624,7 +624,9 @@ read_toc(struct archive_read *a)
__archive_read_consume(a, xar->toc_chksum_size);
xar->offset += xar->toc_chksum_size;
if (r != ARCHIVE_OK)
+#ifndef DONT_FAIL_ON_CRC_ERROR
return (ARCHIVE_FATAL);
+#endif
}
/*
@@ -827,10 +829,12 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
xattr->a_sum.val, xattr->a_sum.len,
xattr->e_sum.val, xattr->e_sum.len);
if (r != ARCHIVE_OK) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Xattr checksum error");
r = ARCHIVE_WARN;
break;
+#endif
}
if (xattr->name.s == NULL) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
diff --git a/src/libs/3rdparty/libarchive/archive_string.c b/src/libs/3rdparty/libarchive/archive_string.c
index d7f2c46b2..69458e1a1 100644
--- a/src/libs/3rdparty/libarchive/archive_string.c
+++ b/src/libs/3rdparty/libarchive/archive_string.c
@@ -3988,10 +3988,10 @@ int
archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
const char **p, size_t *length, struct archive_string_conv *sc)
{
- int r, ret = 0;
-
- (void)r; /* UNUSED */
+ int ret = 0;
#if defined(_WIN32) && !defined(__CYGWIN__)
+ int r;
+
/*
* Internationalization programming on Windows must use Wide
* characters because Windows platform cannot make locale UTF-8.
diff --git a/src/libs/3rdparty/libarchive/archive_write.c b/src/libs/3rdparty/libarchive/archive_write.c
index 66592e826..27626b541 100644
--- a/src/libs/3rdparty/libarchive/archive_write.c
+++ b/src/libs/3rdparty/libarchive/archive_write.c
@@ -201,6 +201,10 @@ __archive_write_allocate_filter(struct archive *_a)
struct archive_write_filter *f;
f = calloc(1, sizeof(*f));
+
+ if (f == NULL)
+ return (NULL);
+
f->archive = _a;
f->state = ARCHIVE_WRITE_FILTER_STATE_NEW;
if (a->filter_first == NULL)
@@ -548,6 +552,10 @@ archive_write_open2(struct archive *_a, void *client_data,
a->client_data = client_data;
client_filter = __archive_write_allocate_filter(_a);
+
+ if (client_filter == NULL)
+ return (ARCHIVE_FATAL);
+
client_filter->open = archive_write_client_open;
client_filter->write = archive_write_client_write;
client_filter->close = archive_write_client_close;
diff --git a/src/libs/3rdparty/libarchive/archive_write_disk_posix.c b/src/libs/3rdparty/libarchive/archive_write_disk_posix.c
index dd7eb9a5e..09a5eef03 100644
--- a/src/libs/3rdparty/libarchive/archive_write_disk_posix.c
+++ b/src/libs/3rdparty/libarchive/archive_write_disk_posix.c
@@ -1996,6 +1996,8 @@ archive_write_disk_new(void)
free(a);
return (NULL);
}
+ a->path_safe.s[0] = 0;
+
#ifdef HAVE_ZLIB_H
a->decmpfs_compression_level = 5;
#endif
@@ -2793,7 +2795,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
char *tail;
char *head;
int last;
- char c;
+ char c = '\0';
int r;
struct stat st;
int chdir_fd;
diff --git a/src/libs/3rdparty/libarchive/archive_write_disk_windows.c b/src/libs/3rdparty/libarchive/archive_write_disk_windows.c
index 1b12a299c..88df3ce02 100644
--- a/src/libs/3rdparty/libarchive/archive_write_disk_windows.c
+++ b/src/libs/3rdparty/libarchive/archive_write_disk_windows.c
@@ -1370,6 +1370,7 @@ archive_write_disk_new(void)
free(a);
return (NULL);
}
+ a->path_safe.s[0] = 0;
return (&a->archive);
}
@@ -2154,6 +2155,8 @@ check_symlinks(struct archive_write_disk *a)
return (ARCHIVE_FAILED);
}
}
+ if (!c)
+ break;
pn[0] = c;
pn++;
}
@@ -2258,6 +2261,9 @@ cleanup_pathname(struct archive_write_disk *a, wchar_t *name)
return (ARCHIVE_FAILED);
} else
p += 4;
+ /* Network drive path like "\\<server-name>\<share-name>\file" */
+ } else if (p[0] == L'\\' && p[1] == L'\\') {
+ p += 2;
}
/* Skip leading drive letter from archives created
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c b/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c
index 52911491f..cf1f4770e 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c
@@ -1717,7 +1717,7 @@ build_pax_attribute_name(char *dest, const char *src)
* to having clients override it.
*/
#if HAVE_GETPID && 0 /* Disable this for now; see above comment. */
- sprintf(buff, "PaxHeader.%d", getpid());
+ snprintf(buff, sizeof(buff), "PaxHeader.%d", getpid());
#else
/* If the platform can't fetch the pid, don't include it. */
strcpy(buff, "PaxHeader");
diff --git a/src/libs/3rdparty/libarchive/filter_fork_posix.c b/src/libs/3rdparty/libarchive/filter_fork_posix.c
index ac255c4f8..62085a709 100644
--- a/src/libs/3rdparty/libarchive/filter_fork_posix.c
+++ b/src/libs/3rdparty/libarchive/filter_fork_posix.c
@@ -76,7 +76,7 @@ int
__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
pid_t *out_child)
{
- pid_t child;
+ pid_t child = -1;
int stdin_pipe[2], stdout_pipe[2], tmp;
#if HAVE_POSIX_SPAWNP
posix_spawn_file_actions_t actions;
diff --git a/src/libs/3rdparty/libarchive/qt_attribution.json b/src/libs/3rdparty/libarchive/qt_attribution.json
index 336051d47..df03d1702 100644
--- a/src/libs/3rdparty/libarchive/qt_attribution.json
+++ b/src/libs/3rdparty/libarchive/qt_attribution.json
@@ -5,7 +5,7 @@
"Description": "Multi-format archive and compression library.",
"QtUsage": "Used for reading and writing archive files in Qt Installer Framework",
"Homepage": "https://www.libarchive.org",
- "Version": "3.6.1",
+ "Version": "3.6.2",
"License": "BSD 2-clause \"Simplified\" License",
"LicenseId": "BSD-2-Clause",
"LicenseFile": "COPYING",
diff --git a/src/libs/ifwtools/binarycreator.cpp b/src/libs/ifwtools/binarycreator.cpp
index d7adc2a52..52603cad5 100644
--- a/src/libs/ifwtools/binarycreator.cpp
+++ b/src/libs/ifwtools/binarycreator.cpp
@@ -43,7 +43,7 @@
#include <QDirIterator>
#include <QDomDocument>
#include <QProcess>
-#include <QRegExp>
+#include <QRegularExpression>
#include <QSettings>
#include <QTemporaryFile>
#include <QTemporaryDir>
@@ -637,8 +637,8 @@ void QInstallerTools::copyConfigData(const QString &configFile, const QString &t
continue;
}
- QString newName = domElement.text().replace(QRegExp(QLatin1String("\\\\|/|\\.|:")),
- QLatin1String("_"));
+ static const QRegularExpression regex(QLatin1String("\\\\|/|\\.|:"));
+ QString newName = domElement.text().replace(regex, QLatin1String("_"));
QString targetFile;
QFileInfo elementFileInfo;
@@ -704,13 +704,13 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
// Begin check arguments
foreach (const QString &packageDir, args.packagesDirectories) {
- if (!QFileInfo(packageDir).exists()) {
+ if (!QFileInfo::exists(packageDir)) {
argumentError = QString::fromLatin1("Error: Package directory not found at the specified location.");
return EXIT_FAILURE;
}
}
foreach (const QString &repositoryDir, args.repositoryDirectories) {
- if (!QFileInfo(repositoryDir).exists()) {
+ if (!QFileInfo::exists(repositoryDir)) {
argumentError = QString::fromLatin1("Error: Only local filesystem repositories now supported.");
return EXIT_FAILURE;
}
@@ -721,12 +721,12 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
"contain any components apart from the root component.");
return EXIT_FAILURE;
}
- if (!QFileInfo(args.templateBinary).exists()) {
+ if (!QFileInfo::exists(args.templateBinary)) {
#ifdef Q_OS_WIN
if (!args.templateBinary.endsWith(suffix))
args.templateBinary = args.templateBinary + suffix;
// Try again with added executable suffix
- if (!QFileInfo(args.templateBinary).exists()) {
+ if (!QFileInfo::exists(args.templateBinary)) {
argumentError = QString::fromLatin1("Error: Template base binary not found at the specified location.");
return EXIT_FAILURE;
}
diff --git a/src/libs/ifwtools/binarycreator.h b/src/libs/ifwtools/binarycreator.h
index 779725660..387195742 100644
--- a/src/libs/ifwtools/binarycreator.h
+++ b/src/libs/ifwtools/binarycreator.h
@@ -77,7 +77,7 @@ public:
explicit BundleBackup(const QString &bundle = QString())
: bundle(bundle)
{
- if (!bundle.isEmpty() && QFileInfo(bundle).exists()) {
+ if (!bundle.isEmpty() && QFileInfo::exists(bundle)) {
backup = QInstaller::generateTemporaryFileName(bundle);
QFile::rename(bundle, backup);
}
diff --git a/src/libs/ifwtools/rcc/rcc.cpp b/src/libs/ifwtools/rcc/rcc.cpp
index 16203e2cd..caef84433 100644
--- a/src/libs/ifwtools/rcc/rcc.cpp
+++ b/src/libs/ifwtools/rcc/rcc.cpp
@@ -36,7 +36,7 @@
#include <QtCore/QFile>
#include <QtCore/QIODevice>
#include <QtCore/QLocale>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
#include <QtCore/QStack>
#include <QXmlStreamReader>
@@ -664,7 +664,7 @@ QStringList RCCResourceLibrary::dataFiles() const
pending.push(m_root);
while (!pending.isEmpty()) {
RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
+ for (QMultiHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
it != file->m_children.end(); ++it) {
RCCFileInfo *child = it.value();
if (child->m_flags & RCCFileInfo::Directory)
@@ -678,7 +678,7 @@ QStringList RCCResourceLibrary::dataFiles() const
// Determine map of resource identifier (':/newPrefix/images/p1.png') to file via recursion
static void resourceDataFileMapRecursion(const RCCFileInfo *m_root, const QString &path, RCCResourceLibrary::ResourceDataFileMap &m)
{
- typedef QHash<QString, RCCFileInfo*>::const_iterator ChildConstIterator;
+ typedef QMultiHash<QString, RCCFileInfo*>::const_iterator ChildConstIterator;
const QChar slash = QLatin1Char('/');
const ChildConstIterator cend = m_root->m_children.constEnd();
for (ChildConstIterator it = m_root->m_children.constBegin(); it != cend; ++it) {
@@ -815,7 +815,7 @@ bool RCCResourceLibrary::writeDataBlobs()
QString errorMessage;
while (!pending.isEmpty()) {
RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
+ for (QMultiHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
it != file->m_children.end(); ++it) {
RCCFileInfo *child = it.value();
if (child->m_flags & RCCFileInfo::Directory)
@@ -851,7 +851,7 @@ bool RCCResourceLibrary::writeDataNames()
qint64 offset = 0;
while (!pending.isEmpty()) {
RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
+ for (QMultiHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
it != file->m_children.end(); ++it) {
RCCFileInfo *child = it.value();
if (child->m_flags & RCCFileInfo::Directory)
@@ -958,7 +958,7 @@ bool RCCResourceLibrary::writeInitializer()
QString initName = m_initName;
if (!initName.isEmpty()) {
initName.prepend(QLatin1Char('_'));
- initName.replace(QRegExp(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
+ initName.replace(QRegularExpression(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
}
//init
diff --git a/src/libs/ifwtools/repositorygen.cpp b/src/libs/ifwtools/repositorygen.cpp
index 5bd9fd334..c54fb846b 100644
--- a/src/libs/ifwtools/repositorygen.cpp
+++ b/src/libs/ifwtools/repositorygen.cpp
@@ -43,7 +43,7 @@
#include "updater.h"
#include <QtCore/QDirIterator>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
#include <QtXml/QDomDocument>
#include <QTemporaryDir>
@@ -188,7 +188,7 @@ static bool findMetaFile(const QString &repositoryDir, const QDomElement &packag
const QDomNodeList c1 = packageUpdate.childNodes();
for (int i = 0; i < c1.count(); ++i) {
const QDomElement e1 = c1.at(i).toElement();
- for (const QString &meta : *scMetaElements) {
+ for (const QString &meta : qAsConst(*scMetaElements)) {
if (e1.tagName() == meta) {
metaElementFound = true;
break;
@@ -367,39 +367,8 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
root.appendChild(update);
- // copy script file
- const QString script = package.firstChildElement(QLatin1String("Script")).text();
- if (!script.isEmpty()) {
- QFile scriptFile(QString::fromLatin1("%1/meta/%2").arg(info.directory, script));
- if (!scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot open component script at \"%1\".")
- .arg(QDir::toNativeSeparators(scriptFile.fileName())));
- }
-
- const QString scriptContent = QLatin1String("(function() {")
- + QString::fromUtf8(scriptFile.readAll())
- + QLatin1String(";"
- " if (typeof Component == \"undefined\")"
- " throw \"Missing Component constructor. Please check your script.\";"
- "})();");
-
- // if the user isn't aware of the downloadable archives value we will add it automatically later
- foundDownloadableArchives |= scriptContent.contains(QLatin1String("addDownloadableArchive"))
- || scriptContent.contains(QLatin1String("removeDownloadableArchive"));
-
- static QInstaller::ScriptEngine testScriptEngine;
- const QJSValue value = testScriptEngine.evaluate(scriptContent, scriptFile.fileName());
- if (value.isError()) {
- throw QInstaller::Error(QString::fromLatin1("Exception while loading component "
- "script at \"%1\": %2").arg(QDir::toNativeSeparators(scriptFile.fileName()),
- value.toString().isEmpty() ? QString::fromLatin1("Unknown error.") :
- value.toString() + QStringLiteral(" on line number: ") +
- value.property(QStringLiteral("lineNumber")).toString()));
- }
-
- const QString toLocation(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, script));
- copyWithException(scriptFile.fileName(), toLocation, QInstaller::scScript);
- }
+ // copy script files
+ copyScriptFiles(childNodes, info, foundDownloadableArchives, targetDir);
// write DownloadableArchives tag if that is missed by the user
if (!foundDownloadableArchives && !info.copiedFiles.isEmpty()) {
@@ -600,8 +569,8 @@ PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packa
info.version = packageElement.firstChildElement(QLatin1String("Version")).text();
// Version cannot start with comparison characters, be an empty string
// or have whitespaces at the beginning or at the end
- if (!QRegExp(QLatin1String("(?![<=>\\s]+)(.+)")).exactMatch(info.version) ||
- (info.version != info.version.trimmed())) {
+ static const QRegularExpression regex(QLatin1String("^(?![<=>\\s]+)(.+)$"));
+ if (!regex.match(info.version).hasMatch() || (info.version != info.version.trimmed())) {
if (ignoreInvalidPackages)
continue;
throw QInstaller::Error(QString::fromLatin1("Component version for \"%1\" is invalid! <Version>%2</Version>")
@@ -977,6 +946,50 @@ void QInstallerTools::splitMetadata(const QStringList &entryList, const QString
}
}
+void QInstallerTools::copyScriptFiles(const QDomNodeList &childNodes, const PackageInfo &info, bool &foundDownloadableArchives, const QString &targetDir)
+{
+ for (int i = 0; i < childNodes.count(); ++i) {
+ const QDomNode node = childNodes.at(i);
+ const QString key = node.nodeName();
+
+ if (key != QLatin1String("Script"))
+ continue;
+ const QString script = node.toElement().text();
+ if (script.isEmpty())
+ continue;
+
+ QFile scriptFile(QString::fromLatin1("%1/meta/%2").arg(info.directory, script));
+ if (!scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ throw QInstaller::Error(QString::fromLatin1("Cannot open component script at \"%1\".")
+ .arg(QDir::toNativeSeparators(scriptFile.fileName())));
+ }
+
+ const QString scriptContent = QLatin1String("(function() {")
+ + QString::fromUtf8(scriptFile.readAll())
+ + QLatin1String(";"
+ " if (typeof Component == \"undefined\")"
+ " throw \"Missing Component constructor. Please check your script.\";"
+ "})();");
+
+ // if the user isn't aware of the downloadable archives value we will add it automatically later
+ foundDownloadableArchives |= scriptContent.contains(QLatin1String("addDownloadableArchive"))
+ || scriptContent.contains(QLatin1String("removeDownloadableArchive"));
+
+ static QInstaller::ScriptEngine testScriptEngine;
+ const QJSValue value = testScriptEngine.evaluate(scriptContent, scriptFile.fileName());
+ if (value.isError()) {
+ throw QInstaller::Error(QString::fromLatin1("Exception while loading component "
+ "script at \"%1\": %2").arg(QDir::toNativeSeparators(scriptFile.fileName()),
+ value.toString().isEmpty() ? QString::fromLatin1("Unknown error.") :
+ value.toString() + QStringLiteral(" on line number: ") +
+ value.property(QStringLiteral("lineNumber")).toString()));
+ }
+
+ const QString toLocation(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, script));
+ copyWithException(scriptFile.fileName(), toLocation, QInstaller::scScript);
+ }
+}
+
void QInstallerTools::copyComponentData(const QStringList &packageDirs, const QString &repoDir,
PackageInfoVector *const infos, const QString &archiveSuffix, Compression compression)
{
diff --git a/src/libs/ifwtools/repositorygen.h b/src/libs/ifwtools/repositorygen.h
index 054c023f4..7ad3dd073 100644
--- a/src/libs/ifwtools/repositorygen.h
+++ b/src/libs/ifwtools/repositorygen.h
@@ -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.
@@ -88,6 +88,7 @@ void IFWTOOLS_EXPORT compressMetaDirectories(const QString &repoDir, const QStri
QStringList unifyMetadata(const QString &repoDir, const QString &existingRepoDir, QDomDocument doc);
void splitMetadata(const QStringList &entryList, const QString &repoDir, QDomDocument doc,
const QHash<QString, QString> &versionMapping);
+void copyScriptFiles(const QDomNodeList &childNodes, const PackageInfo &info, bool &foundDownloadableArchives, const QString &targetDir);
void IFWTOOLS_EXPORT copyMetaData(const QString &outDir, const QString &dataDir, const PackageInfoVector &packages,
const QString &appName, const QString& appVersion, const QStringList &uniteMetadatas);
diff --git a/src/libs/installer/abstracttask.h b/src/libs/installer/abstracttask.h
index 7daff848f..5ee23bef5 100644
--- a/src/libs/installer/abstracttask.h
+++ b/src/libs/installer/abstracttask.h
@@ -31,7 +31,9 @@
#include "runextensions.h"
+#include <QException>
#include <QFutureInterface>
+#include <QVariant>
namespace QInstaller {
diff --git a/src/libs/installer/binaryformatengine.cpp b/src/libs/installer/binaryformatengine.cpp
index ec6926031..681e6db79 100644
--- a/src/libs/installer/binaryformatengine.cpp
+++ b/src/libs/installer/binaryformatengine.cpp
@@ -28,7 +28,7 @@
#include "binaryformatengine.h"
-#include <QRegExp>
+#include <QRegularExpression>
namespace {
@@ -263,15 +263,17 @@ QStringList BinaryFormatEngine::entryList(QDir::Filters filters, const QStringLi
if (filterNames.isEmpty())
return result;
- QList<QRegExp> regexps;
- foreach (const QString &i, filterNames)
- regexps.append(QRegExp(i, Qt::CaseInsensitive, QRegExp::Wildcard));
+ QList<QRegularExpression> regexps;
+ for (const QString &i : filterNames) {
+ regexps.append(QRegularExpression(QRegularExpression::wildcardToRegularExpression(i),
+ QRegularExpression::CaseInsensitiveOption));
+ }
QStringList entries;
- foreach (const QString &i, result) {
+ for (const QString &i : qAsConst(result)) {
bool matched = false;
- foreach (const QRegExp &reg, regexps) {
- matched = reg.exactMatch(i);
+ for (const QRegularExpression &reg : qAsConst(regexps)) {
+ matched = reg.match(i).hasMatch();
if (matched)
break;
}
diff --git a/src/libs/installer/commandlineparser.cpp b/src/libs/installer/commandlineparser.cpp
index 937c966ba..a91ab0128 100644
--- a/src/libs/installer/commandlineparser.cpp
+++ b/src/libs/installer/commandlineparser.cpp
@@ -201,7 +201,7 @@ CommandLineParser::CommandLineParser()
QLatin1String("[CLI] Automatically sets the QFileDialog values getExistingDirectory() or getOpenFileName() "
"requested by install script. "
"Several identifier=value pairs can be given separated with comma, "
- "for example --file-query filedialog.id=C:\Temp,filedialog.id2=C:\Temp2"),
+ "for example --file-query filedialog.id=C:/Temp,filedialog.id2=C:/Temp2"),
QLatin1String("identifier=value")), CommandLineOnly);
addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scConfirmCommandShort
<< CommandLineOptions::scConfirmCommandLong, QLatin1String("[CLI] Confirms starting of "
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index 77a4775c4..32f3fefc6 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -43,7 +43,6 @@
#include <productkeycheck.h>
#include <QtCore/QDirIterator>
-#include <QtCore/QRegExp>
#include <QtCore/QTranslator>
#include <QtCore/QRegularExpression>
@@ -75,6 +74,9 @@ static const QLatin1String scCheckable("Checkable");
static const QLatin1String scExpandedByDefault("ExpandedByDefault");
static const QLatin1String scUnstable("Unstable");
+static const char *scClearCacheHint = QT_TR_NOOP(
+ "Clearing the cache directory and restarting the application may solve this.");
+
/*!
\enum QInstaller::Component::UnstableError
@@ -345,8 +347,7 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scUpdateText, package.data(scUpdateText).toString());
setValue(scNewComponent, package.data(scNewComponent).toString());
setValue(scRequiresAdminRights, package.data(scRequiresAdminRights).toString());
-
- setValue(scScriptTag, package.data(scScriptTag).toString());
+ d->m_scriptHash = package.data(QLatin1String(scScriptTag)).toHash();
setValue(scReplaces, package.data(scReplaces).toString());
setValue(scReleaseDate, package.data(scReleaseDate).toString());
setValue(scCheckable, package.data(scCheckable).toString());
@@ -599,38 +600,47 @@ bool Component::treeNameMoveChildren() const
}
/*!
- Loads the component script into the script engine.
+ Loads the component script into the script engine. Call this method with
+ \a postLoad \c true to a list of components that are updated or installed
+ to improve performance if the amount of components is huge and there are no script
+ functions that need to be called before the installation starts.
*/
-void Component::loadComponentScript()
+void Component::loadComponentScript(const bool postLoad)
{
- const QString script = d->m_vars.value(scScriptTag);
- if (!localTempPath().isEmpty() && !script.isEmpty())
- loadComponentScript(QString::fromLatin1("%1/%2/%3").arg(localTempPath(), name(), script));
+ const QString installScript(!postLoad ? d->m_scriptHash.value(QLatin1String("installScript")).toString()
+ : d->m_scriptHash.value(QLatin1String("postLoadScript")).toString());
+
+ if (!localTempPath().isEmpty() && !installScript.isEmpty()) {
+ evaluateComponentScript(QString::fromLatin1("%1/%2/%3").arg(localTempPath(), name()
+ , installScript), postLoad);
+ }
}
/*!
- Loads the script at \a fileName into the script engine. The installer and all its
- components as well as other useful things are being exported into the script.
- For more information, see \l{Component Scripting}.
-
- Throws an error when either the script at \a fileName could not be opened, or QScriptEngine
- could not evaluate the script.
+ \internal
*/
-void Component::loadComponentScript(const QString &fileName)
+void Component::evaluateComponentScript(const QString &fileName, const bool postScriptContent)
{
// introduce the component object as javascript value and call the name to check that it
// was successful
try {
- d->m_scriptContext = d->scriptEngine()->loadInContext(QLatin1String("Component"), fileName,
- QString::fromLatin1("var component = installer.componentByName('%1'); component.name;")
- .arg(name()));
- } catch (const Error &error) {
- if (packageManagerCore()->settings().allowUnstableComponents()) {
- setUnstable(Component::UnstableError::ScriptLoadingFailed, error.message());
- qCWarning(QInstaller::lcDeveloperBuild) << error.message();
+ if (postScriptContent) {
+ d->m_postScriptContext = d->scriptEngine()->loadInContext(QLatin1String("Component"), fileName,
+ QString::fromLatin1("var component = installer.componentByName('%1'); component.name;")
+ .arg(name()));
} else {
- throw error;
+ d->m_scriptContext = d->scriptEngine()->loadInContext(QLatin1String("Component"), fileName,
+ QString::fromLatin1("var component = installer.componentByName('%1'); component.name;")
+ .arg(name()));
}
+ } catch (const Error &error) {
+ qCWarning(QInstaller::lcDeveloperBuild) << error.message();
+ setUnstable(Component::UnstableError::ScriptLoadingFailed, error.message());
+ // evaluateComponentScript is called with postScriptContent after we have selected components
+ // and are about to install. Do not allow install if unstable components are allowed
+ // as we then end up installing a component which has invalid script.
+ if (!packageManagerCore()->settings().allowUnstableComponents() || postScriptContent)
+ throw error;
}
emit loaded();
@@ -644,7 +654,7 @@ void Component::loadComponentScript(const QString &fileName)
*/
void Component::languageChanged()
{
- d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("retranslateUi"));
+ callScriptMethod(QLatin1String("retranslateUi"));
}
/*!
@@ -693,8 +703,8 @@ void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis
while (it.hasNext()) {
QFile file(it.next());
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Cannot open the requested UI file \"%1\": %2").arg(
- it.fileName(), file.errorString()));
+ throw Error(tr("Cannot open the requested UI file \"%1\": %2.\n\n%3").arg(
+ it.fileName(), file.errorString(), tr(scClearCacheHint)));
}
static QUiLoader loader;
@@ -702,8 +712,8 @@ void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis
loader.setLanguageChangeEnabled(true);
QWidget *const widget = loader.load(&file, 0);
if (!widget) {
- throw Error(tr("Cannot load the requested UI file \"%1\": %2").arg(
- it.fileName(), loader.errorString()));
+ throw Error(tr("Cannot load the requested UI file \"%1\": %2.\n\n%3").arg(
+ it.fileName(), loader.errorString(), tr(scClearCacheHint)));
}
d->scriptEngine()->newQObject(widget);
d->m_userInterfaces.insert(widget->objectName(), widget);
@@ -748,8 +758,8 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
QFile file(fileInfo.filePath());
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Cannot open the requested license file \"%1\": %2").arg(
- file.fileName(), file.errorString()));
+ throw Error(tr("Cannot open the requested license file \"%1\": %2.\n\n%3").arg(
+ file.fileName(), file.errorString(), tr(scClearCacheHint)));
}
QTextStream stream(&file);
stream.setCodec("UTF-8");
@@ -764,7 +774,7 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
*/
void Component::loadXMLOperations()
{
- for (auto operation: m_operationsList) {
+ for (auto operation: qAsConst(m_operationsList)) {
if (operation.first != QLatin1String("Extract"))
addOperation(operation.first, operation.second.toStringList());
}
@@ -776,7 +786,7 @@ void Component::loadXMLOperations()
*/
void Component::loadXMLExtractOperations()
{
- for (auto operation: m_operationsList) {
+ for (auto &operation: qAsConst(m_operationsList)) {
if (operation.first == QLatin1String("Extract")) {
// Create hash for Extract operations. Operation has a mandatory extract folder as
// first argument and optional archive name as second argument.
@@ -845,10 +855,8 @@ void Component::createOperationsForPath(const QString &path)
return;
// the script can override this method
- if (!d->scriptEngine()->callScriptMethod(d->m_scriptContext,
- QLatin1String("createOperationsForPath"), QJSValueList() << path).isUndefined()) {
- return;
- }
+ if (!callScriptMethod(QLatin1String("createOperationsForPath"), QJSValueList() << path).isUndefined())
+ return;
QString target;
static const QString prefix = QString::fromLatin1("installer://");
@@ -891,10 +899,8 @@ void Component::createOperationsForArchive(const QString &archive)
return;
// the script can override this method
- if (!d->scriptEngine()->callScriptMethod(d->m_scriptContext,
- QLatin1String("createOperationsForArchive"), QJSValueList() << archive).isUndefined()) {
- return;
- }
+ if (!callScriptMethod(QLatin1String("createOperationsForArchive"), QJSValueList() << archive).isUndefined())
+ return;
QScopedPointer<AbstractArchive> archiveFile(ArchiveFactory::instance().create(archive));
const bool isZip = (archiveFile && archiveFile->open(QIODevice::ReadOnly) && archiveFile->isSupported());
@@ -916,7 +922,7 @@ void Component::createOperationsForArchive(const QString &archive)
void Component::beginInstallation()
{
// the script can override this method
- d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("beginInstallation"));
+ callScriptMethod(QLatin1String("beginInstallation"));
}
/*!
@@ -926,10 +932,9 @@ void Component::beginInstallation()
void Component::createOperations()
{
// the script can override this method
- if (!d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("createOperations"))
- .isUndefined()) {
- d->m_operationsCreated = true;
- return;
+ if (!callScriptMethod(QLatin1String("createOperations")).isUndefined()) {
+ d->m_operationsCreated = true;
+ return;
}
loadXMLExtractOperations();
foreach (const QString &archive, archives())
@@ -969,7 +974,7 @@ QStringList Component::archives() const
QString pathString = QString::fromLatin1("installer://%1/").arg(name());
QStringList archivesNameList = QDir(pathString).entryList();
//RegExp "^" means line beginning
- archivesNameList.replaceInStrings(QRegExp(QLatin1String("^")), pathString);
+ archivesNameList.replaceInStrings(QRegularExpression(QLatin1String("^")), pathString);
return archivesNameList;
}
@@ -989,6 +994,15 @@ void Component::addDownloadableArchive(const QString &path)
}
/*!
+ \internal
+*/
+void Component::addDownloadableArchives(const QString& archives)
+{
+ Q_ASSERT(isFromOnlineRepository());
+ d->m_downloadableArchivesVariable = archives;
+}
+
+/*!
Removes the archive \a path previously added via addDownloadableArchive() from this component.
This can only be called if this component was downloaded from an online repository.
@@ -1003,9 +1017,15 @@ void Component::removeDownloadableArchive(const QString &path)
/*!
Returns the archives to be downloaded from the online repository before installation.
+ Should be called only once when the installation starts.
*/
-QStringList Component::downloadableArchives() const
+QStringList Component::downloadableArchives()
{
+ const QStringList downloadableArchives = d->m_downloadableArchivesVariable
+ .split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
+ foreach (const QString downloadableArchive, downloadableArchives)
+ addDownloadableArchive(downloadableArchive);
+
return d->m_downloadableArchives;
}
@@ -1196,6 +1216,21 @@ void Component::markComponentUnstable(Component::UnstableError error, const QStr
setValue(scUnstable, scTrue);
QMetaEnum metaEnum = QMetaEnum::fromType<Component::UnstableError>();
emit packageManagerCore()->unstableComponentFound(QLatin1String(metaEnum.valueToKey(error)), errorMessage, this->name());
+
+ // Update the description and tooltip texts to contain
+ // information about the unstable error.
+ updateModelData(scDescription, QString());
+}
+
+QJSValue Component::callScriptMethod(const QString &methodName, const QJSValueList &arguments) const
+{
+ QJSValue scriptContext;
+ if (!d->m_postScriptContext.isUndefined() && d->m_postScriptContext.property(methodName).isCallable())
+ scriptContext = d->m_postScriptContext;
+ else
+ scriptContext = d->m_scriptContext;
+ return d->scriptEngine()->callScriptMethod(scriptContext,
+ methodName, arguments);
}
namespace {
@@ -1355,7 +1390,7 @@ void Component::setValidatorCallbackName(const QString &name)
bool Component::validatePage()
{
if (!validatorCallbackName.isEmpty())
- return d->scriptEngine()->callScriptMethod(d->m_scriptContext, validatorCallbackName).toBool();
+ return callScriptMethod(validatorCallbackName).toBool();
return true;
}
@@ -1500,8 +1535,7 @@ bool Component::isDefault() const
if (d->m_vars.value(scDefault).compare(scScript, Qt::CaseInsensitive) == 0) {
QJSValue valueFromScript;
try {
- valueFromScript = d->scriptEngine()->callScriptMethod(d->m_scriptContext,
- QLatin1String("isDefault"));
+ valueFromScript = callScriptMethod(QLatin1String("isDefault"));
} catch (const Error &error) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("isDefaultError"), tr("Cannot resolve isDefault in %1").arg(name()),
@@ -1735,23 +1769,26 @@ void Component::updateModelData(const QString &key, const QString &data)
setData(humanReadableSize(size), UncompressedSize);
}
- QString tooltipText;
- const QString &updateInfo = d->m_vars.value(scUpdateText);
- if (!d->m_core->isUpdater() || updateInfo.isEmpty()) {
- tooltipText = QString::fromLatin1("<html><body>%1</body></html>").arg(d->m_vars.value(scDescription));
- } else {
- tooltipText = d->m_vars.value(scDescription) + QLatin1String("<br><br>")
- + tr("Update Info: ") + updateInfo;
- }
- if (isUnstable()) {
- tooltipText += QLatin1String("<br>") + tr("There was an error loading the selected component. "
+ if (key == scUpdateText || key == scDescription) {
+ QString tooltipText;
+ const QString &updateInfo = d->m_vars.value(scUpdateText);
+ if (!d->m_core->isUpdater() || updateInfo.isEmpty()) {
+ tooltipText = QString::fromLatin1("<html><body>%1</body></html>").arg(d->m_vars.value(scDescription));
+ } else {
+ tooltipText = d->m_vars.value(scDescription) + QLatin1String("<br><br>")
+ + tr("Update Info: ") + updateInfo;
+ }
+ if (isUnstable()) {
+ tooltipText += QLatin1String("<br>") + tr("There was an error loading the selected component. "
"This component cannot be installed.");
- }
- // replace {external-link}='' fields in component description with proper link tags
- tooltipText.replace(QRegularExpression(QLatin1String("{external-link}='(.*?)'")),
- QLatin1String("<a href=\"\\1\">\\1</a>"));
+ }
+ static const QRegularExpression externalLinkRegexp(QLatin1String("{external-link}='(.*?)'"));
+ static const QLatin1String externalLinkElement(QLatin1String("<a href=\"\\1\">\\1</a>"));
+ // replace {external-link}='' fields in component description with proper link tags
+ tooltipText.replace(externalLinkRegexp, externalLinkElement);
- setData(tooltipText, Qt::ToolTipRole);
+ setData(tooltipText, Qt::ToolTipRole);
+ }
}
/*!
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index 35b0ea0b2..8f17b2d98 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -32,7 +32,6 @@
#include "constants.h"
#include "component_p.h"
#include "qinstallerglobal.h"
-#include "packagemanagercore.h"
#include <QtCore/QDir>
#include <QtCore/QMetaType>
@@ -44,6 +43,8 @@ QT_FORWARD_DECLARE_CLASS(QQmlV4Function)
namespace QInstaller {
+class PackageManagerCore;
+
class INSTALLER_EXPORT Component : public QObject, public ComponentModelHelper
{
Q_OBJECT
@@ -118,10 +119,9 @@ public:
void removeComponent(Component *component);
QList<Component*> descendantComponents() const;
- void loadComponentScript();
+ void loadComponentScript(const bool postLoad = false);
+ void evaluateComponentScript(const QString &fileName, const bool postScriptContext = false);
- //move this to private
- void loadComponentScript(const QString &fileName);
void loadTranslations(const QDir &directory, const QStringList &qms);
void loadUserInterfaces(const QDir &directory, const QStringList &uis);
void loadLicenses(const QString &directory, const QHash<QString, QVariant> &hash);
@@ -150,9 +150,10 @@ public:
Q_INVOKABLE bool addElevatedOperation(QQmlV4Function *args);
bool addElevatedOperation(const QString &operation, const QStringList &parameters);
- QStringList downloadableArchives() const;
+ QStringList downloadableArchives();
Q_INVOKABLE void addDownloadableArchive(const QString &path);
Q_INVOKABLE void removeDownloadableArchive(const QString &path);
+ void addDownloadableArchives(const QString& archives);
QStringList stopProcessForUpdateRequests() const;
Q_INVOKABLE void addStopProcessForUpdateRequest(const QString &process);
@@ -237,6 +238,8 @@ private:
Operation *createOperation(const QString &operationName, const QStringList &parameters);
void markComponentUnstable(const Component::UnstableError error, const QString &errorMessage);
+ QJSValue callScriptMethod(const QString &methodName, const QJSValueList &arguments = QJSValueList()) const;
+
private:
QString validatorCallbackName;
ComponentPrivate *d;
diff --git a/src/libs/installer/component_p.cpp b/src/libs/installer/component_p.cpp
index 4030d266e..7cf47c925 100644
--- a/src/libs/installer/component_p.cpp
+++ b/src/libs/installer/component_p.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 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.
@@ -55,6 +55,9 @@ ComponentPrivate::ComponentPrivate(PackageManagerCore *core, Component *qq)
, m_operationsCreatedSuccessfully(true)
, m_updateIsAvailable(false)
, m_treeNameMoveChildren(false)
+ , m_postLoadScript(false)
+ , m_scriptContext(QJSValue::UndefinedValue)
+ , m_postScriptContext(QJSValue::UndefinedValue)
{
}
@@ -150,7 +153,7 @@ void ComponentModelHelper::setEnabled(bool enabled)
*/
bool ComponentModelHelper::isTristate() const
{
- return (flags() & Qt::ItemIsTristate) != 0;
+ return (flags() & Qt::ItemIsAutoTristate) != 0;
}
/*!
@@ -161,7 +164,7 @@ bool ComponentModelHelper::isTristate() const
*/
void ComponentModelHelper::setTristate(bool tristate)
{
- changeFlags(tristate, Qt::ItemIsTristate);
+ changeFlags(tristate, Qt::ItemIsAutoTristate);
}
/*!
diff --git a/src/libs/installer/component_p.h b/src/libs/installer/component_p.h
index bdc67898d..dea2d4935 100644
--- a/src/libs/installer/component_p.h
+++ b/src/libs/installer/component_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 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.
@@ -64,17 +64,21 @@ public:
bool m_operationsCreatedSuccessfully;
bool m_updateIsAvailable;
bool m_treeNameMoveChildren;
+ bool m_postLoadScript;
QString m_componentName;
QUrl m_repositoryUrl;
QString m_localTempPath;
QJSValue m_scriptContext;
+ QJSValue m_postScriptContext;
QHash<QString, QString> m_vars;
QList<Component*> m_childComponents;
QList<Component*> m_allChildComponents;
QStringList m_downloadableArchives;
+ QString m_downloadableArchivesVariable;
QStringList m_stopProcessForUpdateRequests;
QHash<QString, QPointer<QWidget> > m_userInterfaces;
+ QHash<QString, QVariant> m_scriptHash;
// < display name, < file name, file content > >
QHash<QString, QVariantMap> m_licenses;
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index 23e8680f6..dbb80f2f6 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -47,6 +47,8 @@ namespace QInstaller {
This enum value holds the checked state of the components available for
installation.
+ \value Empty
+ The model does not contain any components.
\value AllChecked
All components are checked.
\value AllUnchecked
@@ -392,7 +394,7 @@ void ComponentModel::reset(QList<Component *> rootComponents)
m_uncheckable.clear();
m_indexByNameCache.clear();
m_rootComponentList.clear();
- m_modelState = DefaultChecked;
+ m_modelState = !rootComponents.isEmpty() ? DefaultChecked : Empty;
// Initialize these with an empty set for every possible state, cause we compare the hashes later in
// updateAndEmitModelState(). The comparison than might lead to wrong results if one of the checked
@@ -481,6 +483,10 @@ void ComponentModel::postModelReset()
void ComponentModel::updateAndEmitModelState()
{
+ if (m_rootComponentList.isEmpty()) {
+ m_modelState = ComponentModel::Empty;
+ return;
+ }
m_modelState = ComponentModel::DefaultChecked;
if (m_initialCheckedState != m_currentCheckedState)
m_modelState = ComponentModel::PartiallyChecked;
diff --git a/src/libs/installer/componentmodel.h b/src/libs/installer/componentmodel.h
index 26cd888a3..1e8a2d297 100644
--- a/src/libs/installer/componentmodel.h
+++ b/src/libs/installer/componentmodel.h
@@ -31,6 +31,8 @@
#include "qinstallerglobal.h"
+#include "component.h"
+
#include <QtCore/QAbstractItemModel>
#include <QtCore/QList>
#include <QtCore/QSet>
@@ -38,7 +40,6 @@
namespace QInstaller {
-class Component;
class PackageManagerCore;
class INSTALLER_EXPORT ComponentModel : public QAbstractItemModel
@@ -49,6 +50,7 @@ class INSTALLER_EXPORT ComponentModel : public QAbstractItemModel
public:
enum ModelStateFlag {
+ Empty = -0x01,
AllChecked = 0x01,
AllUnchecked = 0x02,
DefaultChecked = 0x04,
diff --git a/src/libs/installer/componentselectionpage_p.cpp b/src/libs/installer/componentselectionpage_p.cpp
index 1cb10336c..84a8915a0 100644
--- a/src/libs/installer/componentselectionpage_p.cpp
+++ b/src/libs/installer/componentselectionpage_p.cpp
@@ -464,6 +464,11 @@ void ComponentSelectionPagePrivate::updateWidgetVisibility(bool show)
if (QAbstractButton *bspButton = q->gui()->button(QWizard::CustomButton2))
bspButton->setEnabled(!show);
+ if (show) {
+ q->gui()->button(QWizard::NextButton)->setEnabled(false);
+ q->gui()->button(QWizard::BackButton)->setEnabled(false);
+ }
+
// In macOS 10.12 the widgets are not hidden if those are not updated immediately
#ifdef Q_OS_MACOS
q->repaint();
@@ -546,6 +551,13 @@ void ComponentSelectionPagePrivate::selectDefault()
void ComponentSelectionPagePrivate::onModelStateChanged(QInstaller::ComponentModel::ModelState state)
{
+ if (state.testFlag(ComponentModel::Empty)) {
+ m_checkAll->setEnabled(false);
+ m_uncheckAll->setEnabled(false);
+ m_checkDefault->setEnabled(false);
+ return;
+ }
+
m_componentsResolved = m_core->recalculateAllComponents();
if (!m_componentsResolved) {
const QString error = !m_core->componentsToInstallError().isEmpty()
diff --git a/src/libs/installer/concurrentoperationrunner.cpp b/src/libs/installer/concurrentoperationrunner.cpp
index dfcae44dd..b0eb5f582 100644
--- a/src/libs/installer/concurrentoperationrunner.cpp
+++ b/src/libs/installer/concurrentoperationrunner.cpp
@@ -156,7 +156,7 @@ QHash<Operation *, bool> ConcurrentOperationRunner::run()
this, &ConcurrentOperationRunner::onOperationfinished);
futureWatcher->setFuture(QtConcurrent::run(m_threadPool,
- this, &ConcurrentOperationRunner::runOperation, operation));
+ [this, operation] { return runOperation(operation); }));
}
if (!m_operationWatchers.isEmpty()) {
diff --git a/src/libs/installer/createdesktopentryoperation.cpp b/src/libs/installer/createdesktopentryoperation.cpp
index 6c92cc178..c3988a8ec 100644
--- a/src/libs/installer/createdesktopentryoperation.cpp
+++ b/src/libs/installer/createdesktopentryoperation.cpp
@@ -158,7 +158,7 @@ bool CreateDesktopEntryOperation::performOperation()
// Type=Application\nExec=qtcreator\nPath=...
const QStringList pairs = values.split(QLatin1Char('\n'));
for (QStringList::const_iterator it = pairs.begin(); it != pairs.end(); ++it)
- stream << *it << endl;
+ stream << *it << Qt::endl;
return true;
}
diff --git a/src/libs/installer/createlinkoperation.cpp b/src/libs/installer/createlinkoperation.cpp
index 3f29367b6..65ff8fc5d 100644
--- a/src/libs/installer/createlinkoperation.cpp
+++ b/src/libs/installer/createlinkoperation.cpp
@@ -88,7 +88,7 @@ bool CreateLinkOperation::undoOperation()
return false;
}
- return !QFileInfo(linkPath).exists();
+ return !QFileInfo::exists(linkPath);
}
bool CreateLinkOperation::testOperation()
diff --git a/src/libs/installer/elevatedexecuteoperation.cpp b/src/libs/installer/elevatedexecuteoperation.cpp
index 5db0c887a..6f2393799 100644
--- a/src/libs/installer/elevatedexecuteoperation.cpp
+++ b/src/libs/installer/elevatedexecuteoperation.cpp
@@ -35,7 +35,7 @@
#include <QtCore/QDebug>
#include <QtCore/QProcessEnvironment>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
#include <QtCore/QThread>
using namespace QInstaller;
@@ -137,9 +137,10 @@ int ElevatedExecuteOperation::Private::run(QStringList &arguments, const Operati
QList< int > allowedExitCodes;
- QRegExp re(QLatin1String("^\\{((-?\\d+,)*-?\\d+)\\}$"));
- if (re.exactMatch(args.first())) {
- const QStringList numbers = re.cap(1).split(QLatin1Char(','));
+ static const QRegularExpression re(QLatin1String("^\\{((-?\\d+,)*-?\\d+)\\}$"));
+ const QRegularExpressionMatch match = re.match(args.first());
+ if (match.hasMatch()) {
+ const QStringList numbers = match.captured(1).split(QLatin1Char(','));
for(QStringList::const_iterator it = numbers.constBegin(); it != numbers.constEnd(); ++it)
allowedExitCodes.push_back(it->toInt());
args.pop_front();
diff --git a/src/libs/installer/fileutils.cpp b/src/libs/installer/fileutils.cpp
index 7b9d568f2..2147a8978 100644
--- a/src/libs/installer/fileutils.cpp
+++ b/src/libs/installer/fileutils.cpp
@@ -89,7 +89,7 @@ TempPathDeleter::~TempPathDeleter()
QStringList TempPathDeleter::paths() const
{
- return m_paths.toList();
+ return m_paths.values();
}
void TempPathDeleter::add(const QString &path)
@@ -371,7 +371,7 @@ bool QInstaller::setDefaultFilePermissions(QFile *file, DefaultFilePermissions p
void QInstaller::copyDirectoryContents(const QString &sourceDir, const QString &targetDir)
{
Q_ASSERT(QFileInfo(sourceDir).isDir());
- Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
+ Q_ASSERT(!QFileInfo::exists(targetDir) || QFileInfo(targetDir).isDir());
if (!QDir().mkpath(targetDir)) {
throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\".")
.arg(QDir::toNativeSeparators(targetDir)));
@@ -402,7 +402,7 @@ void QInstaller::copyDirectoryContents(const QString &sourceDir, const QString &
void QInstaller::moveDirectoryContents(const QString &sourceDir, const QString &targetDir)
{
Q_ASSERT(QFileInfo(sourceDir).isDir());
- Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
+ Q_ASSERT(!QFileInfo::exists(targetDir) || QFileInfo(targetDir).isDir());
if (!QDir().mkpath(targetDir)) {
throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\".")
.arg(QDir::toNativeSeparators(targetDir)));
@@ -864,8 +864,8 @@ void QInstaller::copyConfigChildElements(QDomDocument &dom, const QDomNodeList &
// Filename may also contain a path relative to source directory but we
// copy it strictly into target directory without extra paths
- const QString newName = domElement.text()
- .replace(QRegExp(QLatin1String("\\\\|/|\\.|:")), QLatin1String("_"));
+ static const QRegularExpression regex(QLatin1String("\\\\|/|\\.|:"));
+ const QString newName = domElement.text().replace(regex, QLatin1String("_"));
const QString targetFile = targetDir + QDir::separator() + newName;
const QFileInfo elementFileInfo = QFileInfo(sourceDir, domElement.text());
diff --git a/src/libs/installer/genericdatacache.cpp b/src/libs/installer/genericdatacache.cpp
index 683c945dc..fd264ce63 100644
--- a/src/libs/installer/genericdatacache.cpp
+++ b/src/libs/installer/genericdatacache.cpp
@@ -174,6 +174,7 @@ GenericDataCache<T>::~GenericDataCache()
template<typename T>
void GenericDataCache<T>::setType(const QString &type)
{
+ QMutexLocker _(&m_mutex);
m_type = type;
}
@@ -186,6 +187,7 @@ void GenericDataCache<T>::setType(const QString &type)
template<typename T>
void GenericDataCache<T>::setVersion(const QString &version)
{
+ QMutexLocker _(&m_mutex);
m_version = version;
}
@@ -200,6 +202,7 @@ void GenericDataCache<T>::setVersion(const QString &version)
template <typename T>
bool GenericDataCache<T>::initialize()
{
+ QMutexLocker _(&m_mutex);
Q_ASSERT(m_items.isEmpty());
if (m_path.isEmpty()) {
@@ -247,6 +250,7 @@ bool GenericDataCache<T>::initialize()
template <typename T>
bool GenericDataCache<T>::clear()
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot clear invalidated cache."));
@@ -286,6 +290,7 @@ bool GenericDataCache<T>::clear()
template<typename T>
bool GenericDataCache<T>::sync()
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot synchronize invalidated cache."));
@@ -303,6 +308,7 @@ bool GenericDataCache<T>::sync()
template<typename T>
bool GenericDataCache<T>::isValid() const
{
+ QMutexLocker _(&m_mutex);
return !m_invalidated;
}
@@ -314,6 +320,7 @@ bool GenericDataCache<T>::isValid() const
template<typename T>
QString GenericDataCache<T>::errorString() const
{
+ QMutexLocker _(&m_mutex);
return m_error;
}
@@ -325,6 +332,7 @@ QString GenericDataCache<T>::errorString() const
template <typename T>
QString GenericDataCache<T>::path() const
{
+ QMutexLocker _(&m_mutex);
return m_path;
}
@@ -337,6 +345,7 @@ QString GenericDataCache<T>::path() const
template <typename T>
void GenericDataCache<T>::setPath(const QString &path)
{
+ QMutexLocker _(&m_mutex);
if (!m_invalidated)
toDisk();
@@ -352,6 +361,7 @@ void GenericDataCache<T>::setPath(const QString &path)
template <typename T>
QList<T *> GenericDataCache<T>::items() const
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot retrieve items from invalidated cache."));
@@ -369,6 +379,7 @@ QList<T *> GenericDataCache<T>::items() const
template <typename T>
T *GenericDataCache<T>::itemByChecksum(const QByteArray &checksum) const
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot retrieve item from invalidated cache."));
@@ -387,6 +398,7 @@ T *GenericDataCache<T>::itemByChecksum(const QByteArray &checksum) const
template <typename T>
T *GenericDataCache<T>::itemByPath(const QString &path) const
{
+ QMutexLocker _(&m_mutex);
auto it = std::find_if(m_items.constBegin(), m_items.constEnd(),
[&](T *item) {
return (QDir::fromNativeSeparators(path) == QDir::fromNativeSeparators(item->path()));
@@ -413,6 +425,7 @@ T *GenericDataCache<T>::itemByPath(const QString &path) const
template <typename T>
bool GenericDataCache<T>::registerItem(T *item, bool replace)
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot register item to invalidated cache."));
@@ -430,7 +443,7 @@ bool GenericDataCache<T>::registerItem(T *item, bool replace)
}
if (m_items.contains(item->checksum())) {
if (replace) {// replace existing item including contents on disk
- removeItem(item->checksum());
+ remove(item->checksum());
} else {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot register item with checksum %1. An item with the same checksum "
@@ -470,26 +483,8 @@ bool GenericDataCache<T>::registerItem(T *item, bool replace)
template <typename T>
bool GenericDataCache<T>::removeItem(const QByteArray &checksum)
{
- if (m_invalidated) {
- setErrorString(QCoreApplication::translate("GenericDataCache",
- "Cannot remove item from invalidated cache."));
- return false;
- }
- QScopedPointer<T> item(m_items.take(checksum));
- if (!item) {
- setErrorString(QCoreApplication::translate("GenericDataCache",
- "Cannot remove item specified by checksum %1: no such item exists.").arg(QLatin1String(checksum)));
- return false;
- }
-
- try {
- QInstaller::removeDirectory(item->path());
- } catch (const Error &e) {
- setErrorString(QCoreApplication::translate("GenericDataCache",
- "Error while removing directory \"%1\": %2").arg(item->path(), e.message()));
- return false;
- }
- return true;
+ QMutexLocker _(&m_mutex);
+ return remove(checksum);
}
/*!
@@ -500,6 +495,7 @@ bool GenericDataCache<T>::removeItem(const QByteArray &checksum)
template<typename T>
QList<T *> GenericDataCache<T>::obsoleteItems() const
{
+ QMutexLocker _(&m_mutex);
const QList<T *> obsoletes = QtConcurrent::blockingFiltered(m_items.values(),
[&](T *item1) {
if (item1->isActive()) // We can skip the iteration for active entries
@@ -516,7 +512,7 @@ QList<T *> GenericDataCache<T>::obsoleteItems() const
}
/*!
- \fn template <typename T> QInstaller::GenericDataCache<T>::invalidate()
+ \internal
Marks the cache invalid and clears all items. The contents
on disk are not deleted. Releases the lock file of the cache.
@@ -536,7 +532,7 @@ void GenericDataCache<T>::invalidate()
}
/*!
- \fn template <typename T> QInstaller::GenericDataCache<T>::setErrorString(const QString &error) const
+ \internal
Sets the current error string to \a error and prints it as a warning to the console.
*/
@@ -548,7 +544,7 @@ void GenericDataCache<T>::setErrorString(const QString &error) const
}
/*!
- \fn template <typename T> QInstaller::GenericDataCache<T>::fromDisk()
+ \internal
Reads the manifest file of the cache if one exists, and populates the internal
hash from the file contents. Returns \c true if the manifests was read successfully
@@ -602,7 +598,7 @@ bool GenericDataCache<T>::fromDisk()
}
/*!
- \fn template <typename T> QInstaller::GenericDataCache<T>::toDisk()
+ \internal
Writes the manifest file with the contents of the internal item hash.
Returns \c true on success, \c false otherwise.
@@ -638,6 +634,34 @@ bool GenericDataCache<T>::toDisk()
return true;
}
+/*!
+ \internal
+*/
+template<typename T>
+bool GenericDataCache<T>::remove(const QByteArray &checksum)
+{
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot remove item from invalidated cache."));
+ return false;
+ }
+ QScopedPointer<T> item(m_items.take(checksum));
+ if (!item) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot remove item specified by checksum %1: no such item exists.").arg(QLatin1String(checksum)));
+ return false;
+ }
+
+ try {
+ QInstaller::removeDirectory(item->path());
+ } catch (const Error &e) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Error while removing directory \"%1\": %2").arg(item->path(), e.message()));
+ return false;
+ }
+ return true;
+}
+
template class GenericDataCache<Metadata>;
} // namespace QInstaller
diff --git a/src/libs/installer/genericdatacache.h b/src/libs/installer/genericdatacache.h
index 5042ed9a4..2bdf6697e 100644
--- a/src/libs/installer/genericdatacache.h
+++ b/src/libs/installer/genericdatacache.h
@@ -33,6 +33,7 @@
#include "lockfile.h"
#include <QHash>
+#include <QMutex>
#include <QScopedPointer>
namespace QInstaller {
@@ -96,8 +97,12 @@ private:
bool fromDisk();
bool toDisk();
+ bool remove(const QByteArray &checksum);
+
private:
QScopedPointer<KDUpdater::LockFile> m_lock;
+ mutable QMutex m_mutex;
+
QHash<QByteArray, T *> m_items;
QString m_path;
QString m_type;
diff --git a/src/libs/installer/globals.cpp b/src/libs/installer/globals.cpp
index adf1d2f6e..bea299696 100644
--- a/src/libs/installer/globals.cpp
+++ b/src/libs/installer/globals.cpp
@@ -77,12 +77,12 @@ QStringList loggingCategories()
}
-Q_GLOBAL_STATIC_WITH_ARGS(QRegExp, staticCommaRegExp, (QLatin1String("(, |,)")));
+Q_GLOBAL_STATIC_WITH_ARGS(QRegularExpression, staticCommaRegExp, (QLatin1String("(, |,)")));
/*!
\internal
*/
-QRegExp commaRegExp()
+QRegularExpression commaRegExp()
{
return *staticCommaRegExp();
}
diff --git a/src/libs/installer/globals.h b/src/libs/installer/globals.h
index b22331e2c..3450c0dad 100644
--- a/src/libs/installer/globals.h
+++ b/src/libs/installer/globals.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 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.
@@ -30,7 +30,7 @@
#include "installer_global.h"
-#include <QRegExp>
+#include <QRegularExpression>
#include <QLoggingCategory>
namespace QInstaller {
@@ -43,11 +43,17 @@ INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcDeveloperBuild)
QStringList INSTALLER_EXPORT loggingCategories();
-QRegExp INSTALLER_EXPORT commaRegExp();
+QRegularExpression INSTALLER_EXPORT commaRegExp();
QString htmlToString(const QString &html);
QString enumToString(const QMetaObject& metaObject, const char *enumerator, int key);
+template <typename T, template<typename> typename C>
+QSet<T> toQSet(const C<T> &container)
+{
+ return QSet<T>(container.begin(), container.end());
+}
+
} // QInstaller
#endif // GLOBALS_H
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro
index 316d2abfd..0de80b064 100644
--- a/src/libs/installer/installer.pro
+++ b/src/libs/installer/installer.pro
@@ -39,7 +39,10 @@ QT += \
widgets \
core-private \
qml-private
-win32:QT += winextras
+
+win32:lessThan(QT_MAJOR_VERSION, 6):QT += winextras
+
+greaterThan(QT_MAJOR_VERSION, 5):QT += core5compat
HEADERS += packagemanagercore.h \
aspectratiolabel.h \
diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp
index 4eb65f1ad..77989e3f8 100644
--- a/src/libs/installer/installercalculator.cpp
+++ b/src/libs/installer/installercalculator.cpp
@@ -181,11 +181,13 @@ bool InstallerCalculator::appendComponentToInstall(Component *component, const Q
PackageManagerCore::parseNameAndVersion(dependencyComponentName, &requiredName, &requiredVersion);
if (!requiredVersion.isEmpty() &&
!dependencyComponent->value(scInstalledVersion).isEmpty()) {
- QRegExp compEx(QLatin1String("([<=>]+)(.*)"));
- const QString installedVersion = compEx.exactMatch(dependencyComponent->value(scInstalledVersion)) ?
- compEx.cap(2) : dependencyComponent->value(scInstalledVersion);
+ static const QRegularExpression compEx(QLatin1String("^([<=>]+)(.*)$"));
+ QRegularExpressionMatch match = compEx.match(dependencyComponent->value(scInstalledVersion));
+ const QString installedVersion = match.hasMatch()
+ ? match.captured(2) : dependencyComponent->value(scInstalledVersion);
- requiredVersion = compEx.exactMatch(requiredVersion) ? compEx.cap(2) : requiredVersion;
+ match = compEx.match(requiredVersion);
+ requiredVersion = match.hasMatch() ? match.captured(2) : requiredVersion;
if (KDUpdater::compareVersion(requiredVersion, installedVersion) >= 1 ) {
isUpdateRequired = true;
diff --git a/src/libs/installer/lib7z_create.h b/src/libs/installer/lib7z_create.h
index 9e920aa55..b908b028f 100644
--- a/src/libs/installer/lib7z_create.h
+++ b/src/libs/installer/lib7z_create.h
@@ -35,9 +35,10 @@
#include <Common/MyCom.h>
#include <7zip/UI/Common/Update.h>
+#include <QStringList>
+
QT_BEGIN_NAMESPACE
class QFileDevice;
-class QStringList;
QT_END_NAMESPACE
namespace Lib7z
diff --git a/src/libs/installer/lib7z_facade.cpp b/src/libs/installer/lib7z_facade.cpp
index bd08c68c5..e0d8a53e4 100644
--- a/src/libs/installer/lib7z_facade.cpp
+++ b/src/libs/installer/lib7z_facade.cpp
@@ -363,7 +363,7 @@ static quint32 getUInt32Property(IInArchive *archive, int index, int propId, qui
static QFile::Permissions getPermissions(IInArchive *archive, int index, bool *hasPermissions)
{
quint32 attributes = getUInt32Property(archive, index, kpidAttrib, 0);
- QFile::Permissions permissions = nullptr;
+ QFile::Permissions permissions = QFile::Permissions();
if (attributes & FILE_ATTRIBUTE_UNIX_EXTENSION) {
if (hasPermissions != nullptr)
*hasPermissions = true;
diff --git a/src/libs/installer/libarchivearchive.cpp b/src/libs/installer/libarchivearchive.cpp
index 4102518f4..233a4c28b 100644
--- a/src/libs/installer/libarchivearchive.cpp
+++ b/src/libs/installer/libarchivearchive.cpp
@@ -832,7 +832,7 @@ QVector<ArchiveEntry> LibArchiveArchive::list()
ArchiveEntry archiveEntry;
archiveEntry.path = ArchiveEntryPaths::callWithSystemLocale<QString>(ArchiveEntryPaths::pathname, entry);
- archiveEntry.utcTime = QDateTime::fromTime_t(archive_entry_mtime(entry));
+ archiveEntry.utcTime = QDateTime::fromSecsSinceEpoch(archive_entry_mtime(entry));
archiveEntry.isDirectory = (archive_entry_filetype(entry) == AE_IFDIR);
archiveEntry.isSymbolicLink = (archive_entry_filetype(entry) == AE_IFLNK);
archiveEntry.uncompressedSize = archive_entry_size(entry);
diff --git a/src/libs/installer/link.cpp b/src/libs/installer/link.cpp
index ff9f49696..027dac232 100644
--- a/src/libs/installer/link.cpp
+++ b/src/libs/installer/link.cpp
@@ -263,7 +263,7 @@ QString Link::targetPath() const
#ifdef Q_OS_WIN
return readWindowsSymLink(m_path);
#else
- return QFileInfo(m_path).readLink();
+ return QFileInfo(m_path).symLinkTarget();
#endif
}
diff --git a/src/libs/installer/loggingutils.cpp b/src/libs/installer/loggingutils.cpp
index 8c542a1d1..42bbc0117 100644
--- a/src/libs/installer/loggingutils.cpp
+++ b/src/libs/installer/loggingutils.cpp
@@ -31,6 +31,7 @@
#include "component.h"
#include "globals.h"
#include "fileutils.h"
+#include "packagemanagercore.h"
#include "remoteclient.h"
#include "remotefileengine.h"
@@ -110,6 +111,7 @@ public:
*/
LoggingHandler::LoggingHandler()
: m_verbLevel(VerbosityLevel::Silent)
+ , m_outputRedirected(false)
{
#if defined(Q_OS_UNIX)
m_outputRedirected = !isatty(fileno(stdout));
@@ -251,7 +253,7 @@ bool LoggingHandler::outputRedirected() const
/*!
Prints update information from \a components.
*/
-void LoggingHandler::printUpdateInformation(const QList<Component *> components) const
+void LoggingHandler::printUpdateInformation(const QList<Component *> &components) const
{
QString output;
QXmlStreamWriter stream(&output);
@@ -441,7 +443,7 @@ VerboseWriter *VerboseWriter::instance()
*/
void VerboseWriter::appendLine(const QString &msg)
{
- m_stream << msg << endl;
+ m_stream << msg << Qt::endl;
}
/*!
diff --git a/src/libs/installer/loggingutils.h b/src/libs/installer/loggingutils.h
index f41a18663..8bd4217ee 100644
--- a/src/libs/installer/loggingutils.h
+++ b/src/libs/installer/loggingutils.h
@@ -64,7 +64,7 @@ public:
VerbosityLevel verboseLevel() const;
bool outputRedirected() const;
- void printUpdateInformation(const QList<Component *> components) const;
+ void printUpdateInformation(const QList<Component *> &components) const;
void printLocalPackageInformation(const QList<KDUpdater::LocalPackage> &packages) const;
void printPackageInformation(const PackagesList &matchedPackages, const LocalPackagesMap &installedPackages) const;
diff --git a/src/libs/installer/metadata.cpp b/src/libs/installer/metadata.cpp
index b74ffc3f1..9ae817127 100644
--- a/src/libs/installer/metadata.cpp
+++ b/src/libs/installer/metadata.cpp
@@ -36,6 +36,7 @@
#include <QDir>
#include <QDomDocument>
#include <QFile>
+#include <QByteArrayMatcher>
namespace QInstaller {
@@ -122,15 +123,14 @@ QDomDocument Metadata::updatesDocument() const
/*!
Returns \c true if the \c Updates.xml document of this metadata
- exists and can be opened for reading, \c false otherwise.
+ exists, \c false otherwise.
*/
bool Metadata::isValid() const
{
- QFile updateFile(path() + QLatin1String("/Updates.xml"));
- if (!updateFile.open(QIODevice::ReadOnly)) {
+ const QString updateFile(path() + QLatin1String("/Updates.xml"));
+ if (!QFileInfo::exists(updateFile)) {
qCWarning(QInstaller::lcInstallerInstallLog)
- << "Cannot open" << updateFile.fileName()
- << "for reading:" << updateFile.errorString();
+ << "File" << updateFile << "does not exist.";
return false;
}
return true;
@@ -189,7 +189,7 @@ Repository Metadata::repository() const
is already set, the new one will override the previous one. The metadata becomes
associated with the set repository even if it was fetched from another one.
*/
-void Metadata::setRepository(Repository repository)
+void Metadata::setRepository(const Repository &repository)
{
m_repository = repository;
}
@@ -254,4 +254,32 @@ QString Metadata::persistentRepositoryPath()
return m_persistentRepositoryPath;
}
+/*!
+ Returns true if the updates document of this metadata contains the repository
+ update element, which can include actions to \c add, \c remove, and \c replace
+ repositories.
+
+ \note This function does not check that the repository updates are actually
+ valid, only that the updates document contains the \c RepositoryUpdate element.
+*/
+bool Metadata::containsRepositoryUpdates() const
+{
+ QFile updateFile(path() + QLatin1String("/Updates.xml"));
+ if (!updateFile.open(QIODevice::ReadOnly)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open" << updateFile.fileName()
+ << "for reading:" << updateFile.errorString();
+ return false;
+ }
+
+ static const auto matcher = qMakeStaticByteArrayMatcher("<RepositoryUpdate>");
+ while (!updateFile.atEnd()) {
+ const QByteArray line = updateFile.readLine().simplified();
+ if (matcher.indexIn(line) != -1)
+ return true;
+ }
+
+ return false;
+}
+
} // namespace QInstaller
diff --git a/src/libs/installer/metadata.h b/src/libs/installer/metadata.h
index c2afe7df6..3063be829 100644
--- a/src/libs/installer/metadata.h
+++ b/src/libs/installer/metadata.h
@@ -53,7 +53,7 @@ public:
bool obsoletes(CacheableItem *other) override;
Repository repository() const;
- void setRepository(Repository repository);
+ void setRepository(const Repository &repository);
bool isAvailableFromDefaultRepository() const;
void setAvailableFromDefaultRepository(bool defaultRepository);
@@ -61,6 +61,8 @@ public:
void setPersistentRepositoryPath(const QUrl &url);
QString persistentRepositoryPath();
+ bool containsRepositoryUpdates() const;
+
private:
Repository m_repository;
QString m_persistentRepositoryPath;
diff --git a/src/libs/installer/metadatajob.cpp b/src/libs/installer/metadatajob.cpp
index 4bb2b99de..3bb47ca8b 100644
--- a/src/libs/installer/metadatajob.cpp
+++ b/src/libs/installer/metadatajob.cpp
@@ -100,6 +100,7 @@ MetadataJob::MetadataJob(QObject *parent)
connect(&m_xmlTask, &QFutureWatcherBase::finished, this, &MetadataJob::xmlTaskFinished);
connect(&m_metadataTask, &QFutureWatcherBase::finished, this, &MetadataJob::metadataTaskFinished);
connect(&m_metadataTask, &QFutureWatcherBase::progressValueChanged, this, &MetadataJob::progressChanged);
+ connect(&m_updateCacheTask, &QFutureWatcherBase::finished, this, &MetadataJob::updateCacheTaskFinished);
}
MetadataJob::~MetadataJob()
@@ -337,47 +338,15 @@ void MetadataJob::startUnzipRepositoryTask(const Repository &repo)
watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
}
-bool MetadataJob::updateCache()
+void MetadataJob::startUpdateCacheTask()
{
const int toRegisterCount = m_fetchedMetadata.count();
if (toRegisterCount > 0)
emit infoMessage(this, tr("Updating local cache with %n new items...",
nullptr, toRegisterCount));
- // Register items from current run to cache
- QStringList registeredKeys;
- bool success = true;
- for (auto *meta : qAsConst(m_fetchedMetadata)) {
- if (!m_metaFromCache.registerItem(meta, true)) {
- success = false;
- break;
- }
- meta->setPersistentRepositoryPath(meta->repository().url());
- registeredKeys.append(m_fetchedMetadata.key(meta));
- }
- // Remove items whose ownership was transferred to cache
- for (auto &key : qAsConst(registeredKeys))
- m_fetchedMetadata.remove(key);
-
- // Bail out if there was error while registering items
- if (!success) {
- emitFinishedWithError(QInstaller::CacheError, m_metaFromCache.errorString() + u' '
- + tr("Clearing the cache directory and restarting the application may solve this."));
- m_metaFromCache.sync();
- return false;
- }
-
- // ...and clean up obsolete cached items
- const QList<Metadata *> obsolete = m_metaFromCache.obsoleteItems();
- for (auto *meta : obsolete)
- m_metaFromCache.removeItem(meta->checksum());
-
- if (!m_metaFromCache.sync()) {
- emitFinishedWithError(QInstaller::CacheError, m_metaFromCache.errorString() + u' '
- + tr("Clearing the cache directory and restarting the application may solve this."));
- return false;
- }
- return true;
+ UpdateCacheTask *task = new UpdateCacheTask(m_metaFromCache, m_fetchedMetadata);
+ m_updateCacheTask.setFuture(QtConcurrent::run(&UpdateCacheTask::doTask, task));
}
/*
@@ -499,7 +468,7 @@ void MetadataJob::xmlTaskFinished()
temporaries.insert(replacement);
s.addTemporaryRepositories(temporaries, true);
} else {
- QHash<QString, QPair<Repository, Repository> > update;
+ QMultiHash<QString, QPair<Repository, Repository> > update;
update.insert(QLatin1String("replace"), qMakePair(original, replacement));
if (s.updateRepositoryCategories(update) == Settings::UpdatesApplied)
@@ -544,12 +513,10 @@ void MetadataJob::xmlTaskFinished()
if (!fetchMetaDataPackages()) {
// No new metadata packages to fetch, still need to update the cache
// for refreshed repositories.
- if (updateCache())
- emitFinished();
+ startUpdateCacheTask();
}
} else {
- if (updateCache())
- emitFinished();
+ startUpdateCacheTask();
}
} else if (status == XmlDownloadRetry) {
QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
@@ -579,13 +546,8 @@ void MetadataJob::unzipTaskFinished()
m_unzipTasks.remove(watcher);
delete watcher;
- if (m_unzipTasks.isEmpty()) {
- if (!updateCache())
- return;
-
- setProcessedAmount(100);
- emitFinished();
- }
+ if (m_unzipTasks.isEmpty())
+ startUpdateCacheTask();
}
void MetadataJob::progressChanged(int progress)
@@ -628,8 +590,7 @@ void MetadataJob::metadataTaskFinished()
watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
}
} else {
- if (updateCache())
- emitFinished();
+ startUpdateCacheTask();
}
}
} catch (const TaskException &e) {
@@ -644,6 +605,25 @@ void MetadataJob::metadataTaskFinished()
}
}
+void MetadataJob::updateCacheTaskFinished()
+{
+ try {
+ m_updateCacheTask.waitForFinished();
+ } catch (const CacheTaskException &e) {
+ emitFinishedWithError(QInstaller::CacheError, e.message());
+ } catch (const QUnhandledException &e) {
+ emitFinishedWithError(QInstaller::CacheError, QLatin1String(e.what()));
+ } catch (...) {
+ emitFinishedWithError(QInstaller::CacheError, tr("Unknown exception during updating cache."));
+ }
+
+ if (error() != Job::NoError)
+ return;
+
+ setProcessedAmount(100);
+ emitFinished();
+}
+
// -- private
@@ -759,43 +739,14 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
hash.addData(&file);
const QByteArray updatesChecksum = hash.result().toHex();
- Metadata *cachedMetadata = m_metaFromCache.itemByChecksum(updatesChecksum);
- if (cachedMetadata) {
- const Repository repository = item.value(TaskRole::UserRole).value<Repository>();
- if (cachedMetadata->isValid() && !repository.isCompressed()) {
- // Refresh repository information to cache. Same repository may appear in multiple
- // categories and the metadata may be available from default repositories simultaneously.
- cachedMetadata->setRepository(repository);
- if (!repository.categoryname().isEmpty())
- m_fetchedCategorizedRepositories.insert(repository); // For faster lookups
- else
- cachedMetadata->setAvailableFromDefaultRepository(true);
-
- // Refresh also persistent information, the url of the repository may have changed
- // from the last fetch.
- cachedMetadata->setPersistentRepositoryPath(repository.url());
-
- // search for additional repositories that we might need to check
- QDomDocument doc = cachedMetadata->updatesDocument();
- const MetadataJob::Status status
- = parseRepositoryUpdates(doc.documentElement(), result, cachedMetadata);
- if (status == XmlDownloadRetry) {
- // The repository update may have removed or replaced current repositories,
- // clear repository information from cached items and refresh on next fetch run.
- resetCacheRepositories();
- return status;
- }
+ bool refreshed;
+ Status status = refreshCacheItem(result, updatesChecksum, &refreshed);
+ if (status != XmlDownloadSuccess)
+ return status;
+
+ if (refreshed) // Found existing metadata
+ continue;
- continue;
- }
- // Missing or corrupted files, or compressed repository which takes priority
- // over remote repository. We will re-download and uncompress
- // the metadata. Remove broken item from the cache.
- if (!m_metaFromCache.removeItem(updatesChecksum)) {
- qCWarning(lcInstallerInstallLog) << m_metaFromCache.errorString();
- return XmlDownloadFailure;
- }
- }
metadata->setChecksum(updatesChecksum);
file.seek(0);
@@ -870,7 +821,7 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
m_fetchedMetadata.insert(metadataPath, metadata.take());
// search for additional repositories that we might need to check
- const MetadataJob::Status status = parseRepositoryUpdates(root, result, metadataPtr);
+ status = parseRepositoryUpdates(root, result, metadataPtr);
if (status == XmlDownloadRetry) {
// The repository update may have removed or replaced current repositories,
// clear repository information from cached items and refresh on next fetch run.
@@ -885,13 +836,62 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
return XmlDownloadSuccess;
}
+MetadataJob::Status MetadataJob::refreshCacheItem(const FileTaskResult &result,
+ const QByteArray &checksum, bool *refreshed)
+{
+ Q_ASSERT(refreshed);
+ *refreshed = false;
+
+ Metadata *cachedMetadata = m_metaFromCache.itemByChecksum(checksum);
+ if (!cachedMetadata)
+ return XmlDownloadSuccess;
+
+ const FileTaskItem item = result.value(TaskRole::TaskItem).value<FileTaskItem>();
+ const Repository repository = item.value(TaskRole::UserRole).value<Repository>();
+ if (cachedMetadata->isValid() && !repository.isCompressed()) {
+ // Refresh repository information to cache. Same repository may appear in multiple
+ // categories and the metadata may be available from default repositories simultaneously.
+ cachedMetadata->setRepository(repository);
+ if (!repository.categoryname().isEmpty())
+ m_fetchedCategorizedRepositories.insert(repository); // For faster lookups
+ else
+ cachedMetadata->setAvailableFromDefaultRepository(true);
+
+ // Refresh also persistent information, the url of the repository may have changed
+ // from the last fetch.
+ cachedMetadata->setPersistentRepositoryPath(repository.url());
+
+ // search for additional repositories that we might need to check
+ if (cachedMetadata->containsRepositoryUpdates()) {
+ QDomDocument doc = cachedMetadata->updatesDocument();
+ const Status status = parseRepositoryUpdates(doc.documentElement(), result, cachedMetadata);
+ if (status == XmlDownloadRetry) {
+ // The repository update may have removed or replaced current repositories,
+ // clear repository information from cached items and refresh on next fetch run.
+ resetCacheRepositories();
+ return status;
+ }
+ }
+ *refreshed = true;
+ return XmlDownloadSuccess;
+ }
+ // Missing or corrupted files, or compressed repository which takes priority
+ // over remote repository. We will re-download and uncompress
+ // the metadata. Remove broken item from the cache.
+ if (!m_metaFromCache.removeItem(checksum)) {
+ qCWarning(lcInstallerInstallLog) << m_metaFromCache.errorString();
+ return XmlDownloadFailure;
+ }
+ return XmlDownloadSuccess;
+}
+
MetadataJob::Status MetadataJob::parseRepositoryUpdates(const QDomElement &root,
const FileTaskResult &result, Metadata *metadata)
{
MetadataJob::Status status = XmlDownloadSuccess;
const QDomNode repositoryUpdate = root.firstChildElement(QLatin1String("RepositoryUpdate"));
if (!repositoryUpdate.isNull()) {
- const QHash<QString, QPair<Repository, Repository> > repositoryUpdates
+ const QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates
= searchAdditionalRepositories(repositoryUpdate, result, *metadata);
if (!repositoryUpdates.isEmpty())
status = setAdditionalRepositories(repositoryUpdates, result, *metadata);
@@ -964,7 +964,7 @@ bool MetadataJob::parsePackageUpdate(const QDomNodeList &c2, QString &packageNam
return metaFound;
}
-QHash<QString, QPair<Repository, Repository> > MetadataJob::searchAdditionalRepositories
+QMultiHash<QString, QPair<Repository, Repository> > MetadataJob::searchAdditionalRepositories
(const QDomNode &repositoryUpdate, const FileTaskResult &result, const Metadata &metadata)
{
QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates;
@@ -1013,7 +1013,7 @@ QHash<QString, QPair<Repository, Repository> > MetadataJob::searchAdditionalRepo
return repositoryUpdates;
}
-MetadataJob::Status MetadataJob::setAdditionalRepositories(QHash<QString, QPair<Repository, Repository> > repositoryUpdates,
+MetadataJob::Status MetadataJob::setAdditionalRepositories(QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates,
const FileTaskResult &result, const Metadata& metadata)
{
MetadataJob::Status status = XmlDownloadSuccess;
diff --git a/src/libs/installer/metadatajob.h b/src/libs/installer/metadatajob.h
index c0412b9cd..d2207ea38 100644
--- a/src/libs/installer/metadatajob.h
+++ b/src/libs/installer/metadatajob.h
@@ -83,6 +83,7 @@ private slots:
void xmlTaskFinished();
void unzipTaskFinished();
void metadataTaskFinished();
+ void updateCacheTaskFinished();
void progressChanged(int progress);
void setProgressTotalAmount(int maximum);
void unzipRepositoryTaskFinished();
@@ -91,20 +92,21 @@ private slots:
private:
bool fetchMetaDataPackages();
void startUnzipRepositoryTask(const Repository &repo);
- bool updateCache();
+ void startUpdateCacheTask();
void resetCacheRepositories();
void reset();
void resetCompressedFetch();
Status parseUpdatesXml(const QList<FileTaskResult> &results);
+ Status refreshCacheItem(const FileTaskResult &result, const QByteArray &checksum, bool *refreshed);
Status parseRepositoryUpdates(const QDomElement &root, const FileTaskResult &result, Metadata *metadata);
QSet<Repository> getRepositories();
void addFileTaskItem(const QString &source, const QString &target, Metadata *metadata,
const QString &sha1, const QString &packageName);
static bool parsePackageUpdate(const QDomNodeList &c2, QString &packageName, QString &packageVersion,
QString &packageHash, bool online, bool testCheckSum);
- QHash<QString, QPair<Repository, Repository> > searchAdditionalRepositories(const QDomNode &repositoryUpdate,
+ QMultiHash<QString, QPair<Repository, Repository> > searchAdditionalRepositories(const QDomNode &repositoryUpdate,
const FileTaskResult &result, const Metadata &metadata);
- MetadataJob::Status setAdditionalRepositories(QHash<QString, QPair<Repository, Repository> > repositoryUpdates,
+ MetadataJob::Status setAdditionalRepositories(QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates,
const FileTaskResult &result, const Metadata& metadata);
private:
@@ -117,6 +119,7 @@ private:
TempPathDeleter m_tempDirDeleter;
QFutureWatcher<FileTaskResult> m_xmlTask;
QFutureWatcher<FileTaskResult> m_metadataTask;
+ QFutureWatcher<void> m_updateCacheTask;
QHash<QFutureWatcher<void> *, QObject*> m_unzipTasks;
QHash<QFutureWatcher<void> *, QObject*> m_unzipRepositoryTasks;
DownloadType m_downloadType;
diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h
index ef18b2982..7dcb0b34c 100644
--- a/src/libs/installer/metadatajob_p.h
+++ b/src/libs/installer/metadatajob_p.h
@@ -103,6 +103,81 @@ private:
bool m_removeArchive;
};
+class CacheTaskException : public QException
+{
+public:
+ CacheTaskException() {}
+ explicit CacheTaskException(const QString &message)
+ : m_message(message)
+ {}
+ ~CacheTaskException() {}
+
+ void raise() const override { throw *this; }
+ QString message() const { return m_message; }
+ CacheTaskException *clone() const override { return new CacheTaskException(*this); }
+
+private:
+ QString m_message;
+};
+
+class UpdateCacheTask : public AbstractTask<void>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(UpdateCacheTask)
+
+public:
+ UpdateCacheTask(GenericDataCache<Metadata> &cache, QHash<QString, Metadata *> &updates)
+ : m_cache(&cache)
+ , m_updates(&updates)
+ {}
+
+ void doTask(QFutureInterface<void> &fi) override
+ {
+ fi.reportStarted();
+ fi.setExpectedResultCount(1);
+
+ // Register items from current run to cache
+ QStringList registeredKeys;
+ bool success = true;
+ for (auto *meta : qAsConst(*m_updates)) {
+ if (!m_cache->registerItem(meta, true)) {
+ success = false;
+ break;
+ }
+ meta->setPersistentRepositoryPath(meta->repository().url());
+ registeredKeys.append(m_updates->key(meta));
+ }
+ // Remove items whose ownership was transferred to cache
+ for (auto &key : qAsConst(registeredKeys))
+ m_updates->remove(key);
+
+ // Bail out if there was error while registering items
+ if (!success) {
+ fi.reportException(UnzipArchiveException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ m_cache->sync();
+ fi.reportFinished();
+ return;
+ }
+
+ // ...and clean up obsolete cached items
+ const QList<Metadata *> obsolete = m_cache->obsoleteItems();
+ for (auto *meta : obsolete)
+ m_cache->removeItem(meta->checksum());
+
+ if (!m_cache->sync()) {
+ fi.reportException(UnzipArchiveException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ }
+
+ fi.reportFinished();
+ }
+
+private:
+ GenericDataCache<Metadata> *const m_cache;
+ QHash<QString, Metadata *> *const m_updates;
+};
+
} // namespace QInstaller
#endif // METADATAJOB_P_H
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index db6c692e2..2f69c20c8 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -54,7 +54,6 @@
#include <QtConcurrentRun>
#include <QtCore/QMutex>
-#include <QtCore/QRegExp>
#include <QtCore/QSettings>
#include <QtCore/QTemporaryFile>
#include <QtCore/QTextCodec>
@@ -601,6 +600,18 @@ bool PackageManagerCore::clearLocalCache(QString *error)
}
/*!
+ \internal
+ */
+template <typename T>
+bool PackageManagerCore::loadComponentScripts(const T &components, const bool postScript)
+{
+ return d->loadComponentScripts(components, postScript);
+}
+
+template bool PackageManagerCore::loadComponentScripts<QList<Component *>>(const QList<Component *> &, const bool);
+template bool PackageManagerCore::loadComponentScripts<QHash<QString, Component *>>(const QHash<QString, Component *> &, const bool);
+
+/*!
\deprecated [4.5] Use recalculateAllComponents() instead.
\sa {installer::componentsToInstallNeedsRecalculation}{installer.componentsToInstallNeedsRecalculation}
@@ -989,7 +1000,7 @@ bool PackageManagerCore::isFileExtensionRegistered(const QString &extension) con
*/
bool PackageManagerCore::fileExists(const QString &filePath) const
{
- return QFileInfo(filePath).exists();
+ return QFileInfo::exists(filePath);
}
/*!
@@ -1256,6 +1267,10 @@ PackageManagerCore::PackageManagerCore()
Creates and initializes a remote client. Requests administrator's rights for
QFile, QSettings, and QProcess operations. Calls \c init() with \a socketName, \a key,
and \a mode to set the server side authorization key.
+
+ The \a datFileName contains the corresponding .dat file name for the running
+ \c maintenance tool binary. \a datFileName can be empty if \c maintenance tool
+ fails to find it or if \c installer is run instead of \c maintenance tool.
*/
PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationBlob> &operations,
const QString &datFileName,
@@ -1292,8 +1307,8 @@ PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationB
QSet<QString> packagesWithoutOperation = installedPackages - operationPackages;
QSet<QString> orphanedOperations = operationPackages - installedPackages;
if (!packagesWithoutOperation.isEmpty() || !orphanedOperations.isEmpty()) {
- qCritical() << "Operations missing for installed packages" << packagesWithoutOperation.toList();
- qCritical() << "Orphaned operations" << orphanedOperations.toList();
+ qCritical() << "Operations missing for installed packages" << packagesWithoutOperation.values();
+ qCritical() << "Orphaned operations" << orphanedOperations.values();
qCritical() << "Your installation seems to be corrupted. Please consider re-installing from scratch, "
"remove the packages from components.xml which operations are missing, "
"or reinstall the packages.";
@@ -2044,7 +2059,7 @@ QList<Component *> PackageManagerCore::components(ComponentTypes mask, const QSt
QRegularExpression re(regexp);
QList<Component*>::iterator iter = components.begin();
while (iter != components.end()) {
- if (!re.match(iter.i->t()->name()).hasMatch())
+ if (!re.match((*iter)->name()).hasMatch())
iter = components.erase(iter);
else
iter++;
@@ -2304,7 +2319,7 @@ bool PackageManagerCore::calculateComponentsToUninstall() const
*/
QList<Component *> PackageManagerCore::componentsToUninstall() const
{
- return d->uninstallerCalculator()->componentsToUninstall().toList();
+ return d->uninstallerCalculator()->componentsToUninstall().values();
}
/*!
@@ -3376,9 +3391,10 @@ bool PackageManagerCore::performOperation(const QString &name, const QStringList
*/
bool PackageManagerCore::versionMatches(const QString &version, const QString &requirement)
{
- QRegExp compEx(QLatin1String("([<=>]+)(.*)"));
- const QString comparator = compEx.exactMatch(requirement) ? compEx.cap(1) : QLatin1String("=");
- const QString ver = compEx.exactMatch(requirement) ? compEx.cap(2) : requirement;
+ static const QRegularExpression compEx(QLatin1String("^([<=>]+)(.*)$"));
+ const QRegularExpressionMatch match = compEx.match(requirement);
+ const QString comparator = match.hasMatch() ? match.captured(1) : QLatin1String("=");
+ const QString ver = match.hasMatch() ? match.captured(2) : requirement;
const bool allowEqual = comparator.contains(QLatin1Char('='));
const bool allowLess = comparator.contains(QLatin1Char('<'));
@@ -3976,9 +3992,9 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
if (settings().allowUnstableComponents()) {
// Check if there are sha checksum mismatch. Component will still show in install tree
// but is unselectable.
- foreach (const QString packageName, d->m_metadataJob.shaMismatchPackages()) {
- if (packageName == component->name()) {
- const QString errorString = QLatin1String("SHA mismatch detected for component ") + packageName;
+ foreach (const QString pkgName, d->m_metadataJob.shaMismatchPackages()) {
+ if (pkgName == component->name()) {
+ const QString errorString = QLatin1String("SHA mismatch detected for component ") + pkgName;
d->m_pendingUnstableComponents.insert(component->name(),
QPair<Component::UnstableError, QString>(Component::ShaMismatch, errorString));
}
@@ -4002,14 +4018,8 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
component->setValue(QLatin1String("password"), repo.password());
}
- // add downloadable archive from xml
- const QStringList downloadableArchives = data.package->data(scDownloadableArchives).toString()
- .split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
-
- if (component->isFromOnlineRepository()) {
- foreach (const QString downloadableArchive, downloadableArchives)
- component->addDownloadableArchive(downloadableArchive);
- }
+ if (component->isFromOnlineRepository())
+ component->addDownloadableArchives(data.package->data(scDownloadableArchives).toString());
const QStringList componentsToReplace = data.package->data(scReplaces).toString()
.split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
@@ -4350,7 +4360,8 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
}
// store all components that got a replacement, but do not modify the components list
- storeReplacedComponents(localReplaceMes.unite(components), data);
+ localReplaceMes.insert(components);
+ storeReplacedComponents(localReplaceMes, data);
if (!components.isEmpty()) {
// append all components w/o parent to the direct list
@@ -4454,8 +4465,8 @@ void PackageManagerCore::createAutoTreeNames(QHash<QString, Component *> &compon
if (!(parent && parent->treeNameMoveChildren()))
continue; // TreeName only applied to parent
- if (newName.split(QLatin1Char('.'), QString::SkipEmptyParts).count()
- > name.split(QLatin1Char('.'), QString::SkipEmptyParts).count()) {
+ if (newName.split(QLatin1Char('.'), Qt::SkipEmptyParts).count()
+ > name.split(QLatin1Char('.'), Qt::SkipEmptyParts).count()) {
continue;
}
newName = name;
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index fb1eee160..c63447543 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -29,6 +29,7 @@
#define PACKAGEMANAGERCORE_H
#include "binaryformat.h"
+#include "component.h"
#include "protocol.h"
#include "repository.h"
#include "qinstallerglobal.h"
@@ -38,12 +39,12 @@
#include <QtCore/QHash>
#include <QtCore/QObject>
#include <QtCore/QStringList>
-#include <QtCore/QVector>
+#include <QtCore/QList>
#include <QSettings>
+#include <QModelIndex>
namespace QInstaller {
-class Component;
class ComponentModel;
class ScriptEngine;
class PackageManagerCorePrivate;
@@ -352,6 +353,8 @@ public:
bool resetLocalCache(bool init = false);
bool clearLocalCache(QString *error = nullptr);
+ template <typename T>
+ bool loadComponentScripts(const T &components, const bool postScript = false);
public Q_SLOTS:
bool runInstaller();
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 6d56791a0..7313a2761 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -431,7 +431,7 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
}
template <typename T>
-bool PackageManagerCorePrivate::loadComponentScripts(const T &components)
+bool PackageManagerCorePrivate::loadComponentScripts(const T &components, const bool postScript)
{
infoMessage(nullptr, tr("Loading component scripts..."));
@@ -440,7 +440,7 @@ bool PackageManagerCorePrivate::loadComponentScripts(const T &components)
if (statusCanceledOrFailed())
return false;
- component->loadComponentScript();
+ component->loadComponentScript(postScript);
++loadedComponents;
const int currentProgress = qRound(double(loadedComponents) / components.count() * 100);
@@ -450,8 +450,8 @@ bool PackageManagerCorePrivate::loadComponentScripts(const T &components)
return true;
}
-template bool PackageManagerCorePrivate::loadComponentScripts<QList<Component *>>(const QList<Component *> &);
-template bool PackageManagerCorePrivate::loadComponentScripts<QHash<QString, Component *>>(const QHash<QString, Component *> &);
+template bool PackageManagerCorePrivate::loadComponentScripts<QList<Component *>>(const QList<Component *> &, const bool);
+template bool PackageManagerCorePrivate::loadComponentScripts<QHash<QString, Component *>>(const QHash<QString, Component *> &, const bool);
void PackageManagerCorePrivate::cleanUpComponentEnvironment()
{
@@ -494,6 +494,7 @@ void PackageManagerCorePrivate::clearAllComponentLists()
m_deletedReplacedComponents.clear();
m_componentsToReplaceAllMode.clear();
+ m_foundEssentialUpdate = false;
qDeleteAll(toDelete);
cleanUpComponentEnvironment();
@@ -501,8 +502,10 @@ void PackageManagerCorePrivate::clearAllComponentLists()
void PackageManagerCorePrivate::clearUpdaterComponentLists()
{
- QSet<Component*> usedComponents =
- QSet<Component*>::fromList(m_updaterComponents + m_updaterComponentsDeps);
+
+ QSet<Component*> usedComponents(m_updaterComponents.begin(), m_updaterComponents.end());
+ usedComponents.unite(QSet<Component*>(m_updaterComponentsDeps.begin(),
+ m_updaterComponentsDeps.end()));
const QList<QPair<Component*, Component*> > list = m_componentsToReplaceUpdaterMode.values();
for (int i = 0; i < list.count(); ++i) {
@@ -518,6 +521,7 @@ void PackageManagerCorePrivate::clearUpdaterComponentLists()
m_updaterDependencyReplacements.clear();
m_componentsToReplaceUpdaterMode.clear();
+ m_foundEssentialUpdate = false;
qDeleteAll(usedComponents);
cleanUpComponentEnvironment();
@@ -957,7 +961,7 @@ void PackageManagerCorePrivate::readMaintenanceConfigFiles(const QString &target
case QXmlStreamReader::StartElement: {
if (reader.name() == QLatin1String("Network")) {
while (reader.readNextStartElement()) {
- const QStringRef name = reader.name();
+ const QStringView name = reader.name();
if (name == QLatin1String("Ftp")) {
m_data.settings().setFtpProxy(readProxy(reader));
} else if (name == QLatin1String("Http")) {
@@ -1332,6 +1336,8 @@ void PackageManagerCorePrivate::writeMaintenanceToolAppBundle(OperationList &per
<< (targetAppDirPath + QLatin1String("/../plugins")));
performOperationThreaded(op);
}
+#else
+ Q_UNUSED(performedOperations);
#endif
}
@@ -1384,7 +1390,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
bool newBinaryWritten = false;
QString mtName = maintenanceToolName();
const QString installerBaseBinary = replaceVariables(m_installerBaseBinaryUnreplaced);
- if (!installerBaseBinary.isEmpty() && QFileInfo(installerBaseBinary).exists()) {
+ if (!installerBaseBinary.isEmpty() && QFileInfo::exists(installerBaseBinary)) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Got a replacement installer base binary:"
<< installerBaseBinary;
if (QInstaller::isInBundle(installerBaseBinary)) {
@@ -1435,7 +1441,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
}
}
m_installerBaseBinaryUnreplaced.clear();
- } else if (!installerBaseBinary.isEmpty() && !QFileInfo(installerBaseBinary).exists()) {
+ } else if (!installerBaseBinary.isEmpty() && !QFileInfo::exists(installerBaseBinary)) {
qCWarning(QInstaller::lcInstallerInstallLog) << "The current maintenance tool could not be updated."
<< installerBaseBinary << "does not exist. Please fix the \"setInstallerBaseBinary"
"(<temp_installer_base_binary_path>)\" call in your script.";
@@ -2157,7 +2163,7 @@ bool PackageManagerCorePrivate::runOfflineGenerator()
m_core->downloadNeededArchives(double(1));
const QString installerBaseReplacement = replaceVariables(m_offlineBaseBinaryUnreplaced);
- if (!installerBaseReplacement.isEmpty() && QFileInfo(installerBaseReplacement).exists()) {
+ if (!installerBaseReplacement.isEmpty() && QFileInfo::exists(installerBaseReplacement)) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Got a replacement installer base binary:"
<< offlineBinaryTempName;
@@ -3051,9 +3057,16 @@ QStringList PackageManagerCorePrivate::runningInstallerProcesses(const QStringLi
bool PackageManagerCorePrivate::calculateComponentsAndRun()
{
bool componentsOk = m_core->recalculateAllComponents();
+
if (statusCanceledOrFailed()) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Installation canceled.";
} else if (componentsOk && acceptLicenseAgreements()) {
+ try {
+ loadComponentScripts(installerCalculator()->orderedComponentsToInstall(), true);
+ } catch (const Error &error) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << error.message();
+ return false;
+ }
qCDebug(QInstaller::lcInstallerInstallLog).noquote()
<< htmlToString(m_core->componentResolveReasons());
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index aaf9e27be..f6e2b34dd 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -108,7 +108,7 @@ public:
bool buildComponentTree(QHash<QString, Component*> &components, bool loadScript);
template <typename T>
- bool loadComponentScripts(const T &components);
+ bool loadComponentScripts(const T &components, const bool postScript = false);
void cleanUpComponentEnvironment();
ScriptEngine *componentScriptEngine() const;
@@ -291,7 +291,7 @@ private:
qint64 m_magicBinaryMarker;
int m_magicMarkerSupplement;
- bool m_foundEssentialUpdate;;
+ bool m_foundEssentialUpdate;
mutable ScriptEngine *m_componentScriptEngine;
mutable ScriptEngine *m_controlScriptEngine;
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index fa3440a72..1d5b9f713 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -34,7 +34,7 @@
#include <QDesktopServices>
#include <QDir>
-#include <QRegExp>
+#include <QRegularExpression>
#include <QSettings>
#ifdef Q_OS_WIN
@@ -250,7 +250,7 @@ QVariant PackageManagerCoreData::value(const QString &key, const QVariant &_defa
#ifdef Q_OS_WIN
if (!m_variables.contains(key)) {
- static const QRegExp regex(QLatin1String("\\\\|/"));
+ static const QRegularExpression regex(QLatin1String("\\\\|/"));
const QString filename = key.section(regex, 0, -2);
const QString regKey = key.section(regex, -1);
const QSettingsWrapper registry(filename, format);
@@ -293,7 +293,7 @@ QString PackageManagerCoreData::replaceVariables(const QString &str) const
QByteArray PackageManagerCoreData::replaceVariables(const QByteArray &ba) const
{
- static const QChar at = QLatin1Char('@');
+ static const char at = '@';
QByteArray res;
int pos = 0;
while (true) {
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 9cdea0356..b91526663 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -80,13 +80,15 @@
#include <QShowEvent>
#include <QFileDialog>
#include <QGroupBox>
-#include <QDesktopWidget>
+#include <QScreen>
#ifdef Q_OS_WIN
# include <qt_windows.h>
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
# include <QWinTaskbarButton>
# include <QWinTaskbarProgress>
#endif
+#endif
using namespace KDUpdater;
using namespace QInstaller;
@@ -283,6 +285,11 @@ public:
*/
/*!
+ \fn void QInstaller::PackageManagerGui::aboutApplicationClicked()
+ \sa {gui::aboutApplicationClicked}{gui.aboutApplicationClicked}
+*/
+
+/*!
\fn void QInstaller::PackageManagerGui::packageManagerCore() const
Returns the package manager core.
@@ -446,7 +453,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
*/
void PackageManagerGui::setMaxSize()
{
- QSize size = qApp->desktop()->availableGeometry(this).size();
+ QSize size = this->screen()->availableGeometry().size();
int windowFrameHeight = frameGeometry().height() - geometry().height();
int availableHeight = size.height() - windowFrameHeight;
@@ -1543,6 +1550,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_updateComponents->setEnabled(!m_offlineMaintenanceTool && ProductKeyCheck::instance()->hasValidKey());
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
m_taskButton = new QWinTaskbarButton(this);
connect(core, &PackageManagerCore::metaJobProgress,
@@ -1551,6 +1559,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_taskButton = nullptr;
}
#endif
+#endif
}
/*!
@@ -1596,6 +1605,7 @@ bool IntroductionPage::validatePage()
}
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0 ,0)
if (m_taskButton) {
if (!m_taskButton->window()) {
if (QWidget *widget = QApplication::activeWindow())
@@ -1607,6 +1617,7 @@ bool IntroductionPage::validatePage()
m_taskButton->progress()->setVisible(true);
}
#endif
+#endif
// fetch updater packages
if (core->isUpdater()) {
@@ -1671,9 +1682,11 @@ bool IntroductionPage::validatePage()
gui()->setSettingsButtonEnabled(true);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton)
m_taskButton->progress()->setVisible(!isComplete());
#endif
+#endif
return isComplete();
}
@@ -1794,11 +1807,13 @@ void IntroductionPage::setErrorMessage(const QString &error)
m_errorLabel->setPalette(palette);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton) {
m_taskButton->progress()->stop();
m_taskButton->progress()->setValue(100);
}
#endif
+#endif
}
/*!
@@ -2231,6 +2246,29 @@ void ComponentSelectionPage::showEvent(QShowEvent *event)
}
/*!
+ Called when \c ComponentSelectionPage is validated.
+ Tries to load \c component scripts for components about to be installed.
+ Returns \c true if the script loading succeeded and the next page is shown.
+*/
+bool ComponentSelectionPage::validatePage()
+{
+ PackageManagerCore *core = packageManagerCore();
+ try {
+ core->loadComponentScripts(core->orderedComponentsToInstall(), true);
+ } catch (const Error &error) {
+ // As component script loading failed, there is error in the script and component is
+ // marked as unselected. Recalculate so that unselected component is removed from install.
+ // User is then able to select other components for install.
+ core->clearComponentsToInstallCalculated();
+ core->calculateComponentsToInstall();
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"),
+ tr("Error"), error.message());
+ return false;
+ }
+ return true;
+}
+
+/*!
Selects all components in the component tree.
*/
void ComponentSelectionPage::selectAll()
diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h
index 0b804e934..a25329b9c 100644
--- a/src/libs/installer/packagemanagergui.h
+++ b/src/libs/installer/packagemanagergui.h
@@ -336,6 +336,7 @@ protected:
void entering() override;
void leaving() override;
void showEvent(QShowEvent *event) override;
+ bool validatePage() override;
private Q_SLOTS:
void setModified(bool modified);
diff --git a/src/libs/installer/performinstallationform.cpp b/src/libs/installer/performinstallationform.cpp
index d8d1e3dcb..0e4c561f6 100644
--- a/src/libs/installer/performinstallationform.cpp
+++ b/src/libs/installer/performinstallationform.cpp
@@ -49,9 +49,11 @@
#include <QtCore/QTimer>
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
# include <QWinTaskbarButton>
# include <QWinTaskbarProgress>
#endif
+#endif
using namespace QInstaller;
@@ -96,6 +98,7 @@ PerformInstallationForm::PerformInstallationForm(PackageManagerCore *core, QObje
, m_core(core)
{
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
m_taskButton = new QWinTaskbarButton(this);
m_taskButton->progress()->setVisible(true);
@@ -103,6 +106,7 @@ PerformInstallationForm::PerformInstallationForm(PackageManagerCore *core, QObje
m_taskButton = nullptr;
}
#endif
+#endif
}
/*!
@@ -204,12 +208,14 @@ void PerformInstallationForm::updateProgress()
m_progressBar->setValue(progressPercentage);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton) {
if (!m_taskButton->window() && QApplication::activeWindow())
m_taskButton->setWindow(QApplication::activeWindow()->windowHandle());
m_taskButton->progress()->setValue(progressPercentage);
}
#endif
+#endif
static QString lastLabelText;
if (lastLabelText == progressCoordninator->labelText())
diff --git a/src/libs/installer/permissionsettings.cpp b/src/libs/installer/permissionsettings.cpp
index 235c6667b..68e4ab427 100644
--- a/src/libs/installer/permissionsettings.cpp
+++ b/src/libs/installer/permissionsettings.cpp
@@ -40,25 +40,33 @@ using namespace QInstaller;
PermissionSettings::PermissionSettings(const QString &organization, const QString &application, QObject *parent)
: QSettings(organization, application, parent)
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
setIniCodec("UTF-8"); // to workaround QTBUG-102334
+#endif
}
PermissionSettings::PermissionSettings(Scope scope, const QString &organization, const QString &application, QObject *parent)
: QSettings(scope, organization, application, parent)
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
setIniCodec("UTF-8"); // QTBUG-102334
+#endif
}
PermissionSettings::PermissionSettings(Format format, Scope scope, const QString &organization, const QString &application, QObject *parent)
: QSettings(format, scope, organization, application, parent)
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
setIniCodec("UTF-8"); // QTBUG-102334
+#endif
}
PermissionSettings::PermissionSettings(const QString &fileName, Format format, QObject *parent)
: QSettings(fileName, format, parent)
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
setIniCodec("UTF-8"); // QTBUG-102334
+#endif
}
PermissionSettings::~PermissionSettings()
diff --git a/src/libs/installer/qprocesswrapper.cpp b/src/libs/installer/qprocesswrapper.cpp
index f37d65b29..6f34e36da 100644
--- a/src/libs/installer/qprocesswrapper.cpp
+++ b/src/libs/installer/qprocesswrapper.cpp
@@ -32,6 +32,7 @@
#include "utils.h"
#include <QDir>
+#include <QVariant>
namespace QInstaller {
@@ -356,7 +357,7 @@ void QProcessWrapper::start(const QString &param1, QIODevice::OpenMode param2)
callRemoteMethod(QLatin1String(Protocol::QProcessStart2Arg), param1, param2);
m_lock.unlock();
} else {
- process.start(param1, param2);
+ process.start(param1, {}, param2);
}
}
diff --git a/src/libs/installer/qtpatch.cpp b/src/libs/installer/qtpatch.cpp
index f72e67867..a29e99f94 100644
--- a/src/libs/installer/qtpatch.cpp
+++ b/src/libs/installer/qtpatch.cpp
@@ -67,11 +67,11 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA
QFileInfo qmake(qmakePath);
if (!qmake.exists()) {
- qmakeOutput->append(QString::fromLatin1("%1 is not existing").arg(qmakePath));
+ qmakeOutput->append(QString::fromLatin1("%1 is not existing").arg(qmakePath).toUtf8());
return qmakeValueHash;
}
if (!qmake.isExecutable()) {
- qmakeOutput->append(QString::fromLatin1("%1 is not executable").arg(qmakePath));
+ qmakeOutput->append(QString::fromLatin1("%1 is not executable").arg(qmakePath).toUtf8());
return qmakeValueHash;
}
@@ -88,7 +88,7 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA
, QString::fromLatin1("Standard output: \"%1\".").arg(QLatin1String(output))
, QString::fromLatin1("Error output: \"%1\".").arg(QLatin1String(process.readAllStandardError()))
};
- qmakeOutput->append(detailedOutput.join(QLatin1Char('\n')));
+ qmakeOutput->append(detailedOutput.join(QLatin1Char('\n')).toUtf8());
return qmakeValueHash;
}
qmakeOutput->append(output);
diff --git a/src/libs/installer/remoteclient_p.h b/src/libs/installer/remoteclient_p.h
index e1809e0af..3dec97c95 100644
--- a/src/libs/installer/remoteclient_p.h
+++ b/src/libs/installer/remoteclient_p.h
@@ -40,8 +40,8 @@
#include <QCoreApplication>
#include <QDeadlineTimer>
+#include <QRecursiveMutex>
#include <QTimer>
-#include <QMutex>
#include <QThread>
namespace QInstaller {
@@ -55,7 +55,6 @@ public:
RemoteClientPrivate(RemoteClient *parent)
: RemoteObject(QLatin1String("RemoteClientPrivate"))
, q_ptr(parent)
- , m_mutex(QMutex::Recursive)
, m_startServerAs(Protocol::StartAs::User)
, m_serverStarted(false)
, m_active(false)
@@ -201,7 +200,7 @@ public:
private:
RemoteClient *q_ptr;
- QMutex m_mutex;
+ QRecursiveMutex m_mutex;
QString m_socketName;
Protocol::StartAs m_startServerAs;
bool m_serverStarted;
diff --git a/src/libs/installer/remoteobject.h b/src/libs/installer/remoteobject.h
index 4dce2a218..c423de943 100644
--- a/src/libs/installer/remoteobject.h
+++ b/src/libs/installer/remoteobject.h
@@ -35,8 +35,10 @@
#include <QCoreApplication>
#include <QDataStream>
-#include <QObject>
#include <QLocalSocket>
+#include <QObject>
+#include <QVariant>
+
namespace QInstaller {
diff --git a/src/libs/installer/remoteserverconnection.cpp b/src/libs/installer/remoteserverconnection.cpp
index 05446ec19..ed3d343fe 100644
--- a/src/libs/installer/remoteserverconnection.cpp
+++ b/src/libs/installer/remoteserverconnection.cpp
@@ -278,7 +278,7 @@ void RemoteServerConnection::handleQProcess(RemoteServerReply *reply, const QStr
qint64 pid = -1;
bool success = QInstaller::startDetached(program, arguments, workingDirectory, &pid);
- reply->send(qMakePair< bool, qint64>(success, pid));
+ reply->send(QPair<bool, qint64>(success, pid));
} else if (command == QLatin1String(Protocol::QProcessStartDetached2)) {
QString program;
QStringList arguments;
@@ -289,7 +289,7 @@ void RemoteServerConnection::handleQProcess(RemoteServerReply *reply, const QStr
qint64 pid = -1;
bool success = QProcess::startDetached(program, arguments, workingDirectory, &pid);
- reply->send(qMakePair< bool, qint64>(success, pid));
+ reply->send(QPair<bool, qint64>(success, pid));
} else if (command == QLatin1String(Protocol::QProcessSetWorkingDirectory)) {
QString dir;
data >> dir;
@@ -313,7 +313,7 @@ void RemoteServerConnection::handleQProcess(RemoteServerReply *reply, const QStr
qint32 mode;
data >> program;
data >> mode;
- m_process->start(program, static_cast<QIODevice::OpenMode> (mode));
+ m_process->start(program, {}, static_cast<QIODevice::OpenMode> (mode));
} else if (command == QLatin1String(Protocol::QProcessState)) {
reply->send(static_cast<qint32> (m_process->state()));
} else if (command == QLatin1String(Protocol::QProcessTerminate)) {
@@ -517,13 +517,13 @@ void RemoteServerConnection::handleQFSFileEngine(RemoteServerReply *reply, const
data >> maxlen;
QByteArray byteArray(maxlen, '\0');
const qint64 r = m_engine->read(byteArray.data(), maxlen);
- reply->send(qMakePair<qint64, QByteArray>(r, byteArray));
+ reply->send(QPair<qint64, QByteArray>(r, byteArray));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineReadLine)) {
qint64 maxlen;
data >> maxlen;
QByteArray byteArray(maxlen, '\0');
const qint64 r = m_engine->readLine(byteArray.data(), maxlen);
- reply->send(qMakePair<qint64, QByteArray>(r, byteArray));
+ reply->send(QPair<qint64, QByteArray>(r, byteArray));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRemove)) {
reply->send(m_engine->remove());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRename)) {
diff --git a/src/libs/installer/repository.cpp b/src/libs/installer/repository.cpp
index ddbf3b382..e8df4e433 100644
--- a/src/libs/installer/repository.cpp
+++ b/src/libs/installer/repository.cpp
@@ -270,7 +270,9 @@ const Repository &Repository::operator=(const Repository &other)
void Repository::registerMetaType()
{
qRegisterMetaType<Repository>("Repository");
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
qRegisterMetaTypeStreamOperators<Repository>("Repository");
+#endif
}
/*!
diff --git a/src/libs/installer/repositorycategory.cpp b/src/libs/installer/repositorycategory.cpp
index e651b7f0c..6be292330 100644
--- a/src/libs/installer/repositorycategory.cpp
+++ b/src/libs/installer/repositorycategory.cpp
@@ -75,7 +75,9 @@ RepositoryCategory::RepositoryCategory(const RepositoryCategory &other)
void RepositoryCategory::registerMetaType()
{
qRegisterMetaType<RepositoryCategory>("RepositoryCategory");
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
qRegisterMetaTypeStreamOperators<RepositoryCategory>("RepositoryCategory");
+#endif
}
/*!
diff --git a/src/libs/installer/scriptengine.cpp b/src/libs/installer/scriptengine.cpp
index 009215909..bcd475d54 100644
--- a/src/libs/installer/scriptengine.cpp
+++ b/src/libs/installer/scriptengine.cpp
@@ -95,7 +95,7 @@ QJSValue InstallerProxy::components(const QString &regexp) const
QJSValue InstallerProxy::componentByName(const QString &componentName)
{
if (m_core)
- return m_engine->newQObject(m_core->componentByName(componentName));
+ return m_engine->newQObject(m_core->componentByName(componentName), false);
return QJSValue();
}
@@ -418,9 +418,9 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core) :
/*!
Creates a JavaScript object that wraps the given QObject \a object.
- Signals and slots, properties and children of \a object are
- available as properties of the created QJSValue. In addition some helper methods and properties
- are added:
+ Signals and slots, properties and children of \a object are available as properties
+ of the created QJSValue. If \a qtScriptCompat is set to \c true (default), some helper
+ methods and properties from the legacy \c QtScript module are added:
\list
\li findChild(), findChildren() recursively search for child objects with the given
@@ -429,7 +429,7 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core) :
names.
\endlist
*/
-QJSValue ScriptEngine::newQObject(QObject *object)
+QJSValue ScriptEngine::newQObject(QObject *object, bool qtScriptCompat)
{
QJSValue jsValue = m_engine.newQObject(object);
if (!jsValue.isQObject())
@@ -437,6 +437,9 @@ QJSValue ScriptEngine::newQObject(QObject *object)
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
+ if (!qtScriptCompat) // skip adding the extra properties
+ return jsValue;
+
// add findChild(), findChildren() methods known from QtScript
QJSValue findChild = m_engine.evaluate(
QLatin1String("(function() { return gui.findChild(this, arguments[0]); })"));
@@ -654,7 +657,7 @@ QJSValue ScriptEngine::generateDesktopServicesObject()
SETPROPERTY(desktopServices, PicturesLocation, QStandardPaths)
SETPROPERTY(desktopServices, TempLocation, QStandardPaths)
SETPROPERTY(desktopServices, HomeLocation, QStandardPaths)
- SETPROPERTY(desktopServices, DataLocation, QStandardPaths)
+ SETPROPERTY(desktopServices, AppDataLocation, QStandardPaths)
SETPROPERTY(desktopServices, CacheLocation, QStandardPaths)
SETPROPERTY(desktopServices, GenericDataLocation, QStandardPaths)
SETPROPERTY(desktopServices, RuntimeLocation, QStandardPaths)
diff --git a/src/libs/installer/scriptengine.h b/src/libs/installer/scriptengine.h
index ae3cdd04f..a7c0ef253 100644
--- a/src/libs/installer/scriptengine.h
+++ b/src/libs/installer/scriptengine.h
@@ -48,7 +48,7 @@ public:
explicit ScriptEngine(PackageManagerCore *core = 0);
QJSValue globalObject() const { return m_engine.globalObject(); }
- QJSValue newQObject(QObject *object);
+ QJSValue newQObject(QObject *object, bool qtScriptCompat = true);
QJSValue newArray(uint length = 0);
QJSValue evaluate(const QString &program, const QString &fileName = QString(),
int lineNumber = 1);
diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp
index df7d5f8cc..ae1adbedb 100644
--- a/src/libs/installer/settings.cpp
+++ b/src/libs/installer/settings.cpp
@@ -745,7 +745,7 @@ Settings::Update Settings::updateRepositoryCategories(const RepoHash &updates)
return update ? Settings::UpdatesApplied : Settings::NoUpdatesApplied;
}
-static bool apply(const RepoHash &updates, QHash<QUrl, Repository> *reposToUpdate)
+static bool apply(const RepoHash &updates, QMultiHash<QUrl, Repository> *reposToUpdate)
{
bool update = false;
QList<QPair<Repository, Repository> > values = updates.values(QLatin1String("replace"));
@@ -783,7 +783,7 @@ Settings::Update Settings::updateDefaultRepositories(const RepoHash &updates)
if (updates.isEmpty())
return Settings::NoUpdatesApplied;
- QHash <QUrl, Repository> defaultRepos;
+ QMultiHash <QUrl, Repository> defaultRepos;
foreach (const QVariant &variant, d->m_data.values(scRepositories)) {
const Repository repository = variant.value<Repository>();
defaultRepos.insert(repository.url(), repository);
@@ -837,7 +837,7 @@ Settings::Update Settings::updateUserRepositories(const RepoHash &updates)
if (updates.isEmpty())
return Settings::NoUpdatesApplied;
- QHash <QUrl, Repository> reposToUpdate;
+ QMultiHash <QUrl, Repository> reposToUpdate;
foreach (const QVariant &variant, d->m_data.values(scUserRepositories)) {
const Repository repository = variant.value<Repository>();
reposToUpdate.insert(repository.url(), repository);
diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h
index ebb65a382..f98319110 100644
--- a/src/libs/installer/settings.h
+++ b/src/libs/installer/settings.h
@@ -42,7 +42,7 @@
namespace QInstaller {
class Repository;
-typedef QHash<QString, QPair<Repository, Repository> > RepoHash;
+typedef QMultiHash<QString, QPair<Repository, Repository> > RepoHash;
class INSTALLER_EXPORT Settings
{
diff --git a/src/libs/installer/sysinfo_win.cpp b/src/libs/installer/sysinfo_win.cpp
index e6c2a0be8..e74eb1d4e 100644
--- a/src/libs/installer/sysinfo_win.cpp
+++ b/src/libs/installer/sysinfo_win.cpp
@@ -150,7 +150,7 @@ QList<VolumeInfo> mountedVolumes()
bool pathIsOnLocalDevice(const QString &path)
{
- if (!QFileInfo(path).exists())
+ if (!QFileInfo::exists(path))
return false;
if (path.startsWith(QLatin1String("//")))
diff --git a/src/libs/installer/utils.cpp b/src/libs/installer/utils.cpp
index e9fb45f2a..154a66553 100644
--- a/src/libs/installer/utils.cpp
+++ b/src/libs/installer/utils.cpp
@@ -57,7 +57,7 @@
*/
void QInstaller::uiDetachedWait(int ms)
{
- QTime timer;
+ QElapsedTimer timer;
timer.start();
do {
QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
@@ -139,7 +139,7 @@ QStringList QInstaller::localeCandidates(const QString &locale_)
at least one mutually exclusive pair of options set. Otherwise returns an empty
\c QStringList. The options considered mutual are provided with \a options.
*/
-QStringList QInstaller::checkMutualOptions(CommandLineParser &parser, const QStringList &options)
+QStringList QInstaller::checkMutualOptions(const CommandLineParser &parser, const QStringList &options)
{
QStringList mutual;
foreach (const QString &option, options) {
diff --git a/src/libs/installer/utils.h b/src/libs/installer/utils.h
index 2bf997835..068490cc2 100644
--- a/src/libs/installer/utils.h
+++ b/src/libs/installer/utils.h
@@ -69,7 +69,7 @@ namespace QInstaller {
QStringList INSTALLER_EXPORT localeCandidates(const QString &locale);
- QStringList INSTALLER_EXPORT checkMutualOptions(CommandLineParser &parser, const QStringList &options);
+ QStringList INSTALLER_EXPORT checkMutualOptions(const CommandLineParser &parser, const QStringList &options);
INSTALLER_EXPORT std::ostream& operator<<(std::ostream &os, const QString &string);
}
diff --git a/src/libs/kdtools/kdsysinfo_win.cpp b/src/libs/kdtools/kdsysinfo_win.cpp
index 465029252..d423ef01e 100644
--- a/src/libs/kdtools/kdsysinfo_win.cpp
+++ b/src/libs/kdtools/kdsysinfo_win.cpp
@@ -66,7 +66,13 @@ QList<ProcessInfo> runningProcesses()
QStringList deviceList;
const DWORD bufferSize = 1024;
char buffer[bufferSize + 1] = { 0 };
- if (QSysInfo::windowsVersion() <= QSysInfo::WV_5_2) {
+
+ // Qt6 does not support Win before 10
+ bool winVerLessEqual5_2 = false;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ winVerLessEqual5_2 = QSysInfo::windowsVersion() <= QSysInfo::WV_5_2;
+#endif
+ if (winVerLessEqual5_2) {
const DWORD size = GetLogicalDriveStringsA(bufferSize, buffer);
deviceList = QString::fromLatin1(buffer, size).split(QLatin1Char(char(0)), Qt::SkipEmptyParts);
}
@@ -85,7 +91,7 @@ QList<ProcessInfo> runningProcesses()
processStruct.dwSize = sizeof(PROCESSENTRY32);
bool foundProcess = Process32First(snapshot, &processStruct);
while (foundProcess) {
- HANDLE procHandle = OpenProcess(QSysInfo::windowsVersion() > QSysInfo::WV_5_2
+ HANDLE procHandle = OpenProcess(!winVerLessEqual5_2
? KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, false, processStruct
.th32ProcessID);
@@ -93,7 +99,7 @@ QList<ProcessInfo> runningProcesses()
QString executablePath;
DWORD bufferSize = 1024;
- if (QSysInfo::windowsVersion() > QSysInfo::WV_5_2) {
+ if (!winVerLessEqual5_2) {
succ = pQueryFullProcessImageNamePtr(procHandle, 0, buffer, &bufferSize);
executablePath = QString::fromLatin1(buffer);
} else if (pGetProcessImageFileNamePtr) {
diff --git a/src/libs/kdtools/lockfile_win.cpp b/src/libs/kdtools/lockfile_win.cpp
index 20961cc4e..7fc808d39 100644
--- a/src/libs/kdtools/lockfile_win.cpp
+++ b/src/libs/kdtools/lockfile_win.cpp
@@ -45,7 +45,7 @@ bool LockFile::Private::lock()
errorString.clear();
handle = CreateFile(filename.toStdWString().data(), GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ, NULL, QFileInfo(filename).exists() ? OPEN_EXISTING : CREATE_NEW,
+ FILE_SHARE_READ, NULL, QFileInfo::exists(filename) ? OPEN_EXISTING : CREATE_NEW,
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL);
if (handle == INVALID_HANDLE_VALUE) {
diff --git a/src/libs/kdtools/sysinfo_x11.cpp b/src/libs/kdtools/sysinfo_x11.cpp
index a59fd150b..24ef099ca 100644
--- a/src/libs/kdtools/sysinfo_x11.cpp
+++ b/src/libs/kdtools/sysinfo_x11.cpp
@@ -40,7 +40,7 @@
#include <QtCore/QTextStream>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
namespace KDUpdater {
@@ -124,9 +124,9 @@ QList<ProcessInfo> runningProcesses()
QList<ProcessInfo> processes;
QDir procDir(QLatin1String("/proc"));
const QFileInfoList procCont = procDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable);
- QRegExp validator(QLatin1String("[0-9]+"));
- Q_FOREACH (const QFileInfo &info, procCont) {
- if (validator.exactMatch(info.fileName())) {
+ static const QRegularExpression validator(QLatin1String("^[0-9]+$"));
+ for (const QFileInfo &info : procCont) {
+ if (validator.match(info.fileName()).hasMatch()) {
const QString linkPath = QDir(info.absoluteFilePath()).absoluteFilePath(QLatin1String("exe"));
const QFileInfo linkInfo(linkPath);
if (linkInfo.exists()) {
diff --git a/src/libs/kdtools/updatefinder.cpp b/src/libs/kdtools/updatefinder.cpp
index b1070c742..a45e9e3d0 100644
--- a/src/libs/kdtools/updatefinder.cpp
+++ b/src/libs/kdtools/updatefinder.cpp
@@ -39,7 +39,7 @@
#include <QCoreApplication>
#include <QFileInfo>
-#include <QRegExp>
+#include <QRegularExpression>
using namespace KDUpdater;
using namespace QInstaller;
@@ -589,8 +589,8 @@ int KDUpdater::compareVersion(const QString &v1, const QString &v2)
return 0;
// Split version components across ".", "-" or "_"
- QStringList v1_comps = v1.split(QRegExp(QLatin1String( "\\.|-|_")));
- QStringList v2_comps = v2.split(QRegExp(QLatin1String( "\\.|-|_")));
+ QStringList v1_comps = v1.split(QRegularExpression(QLatin1String( "\\.|-|_")));
+ QStringList v2_comps = v2.split(QRegularExpression(QLatin1String( "\\.|-|_")));
// Check each component of the version
int index = 0;
diff --git a/src/libs/kdtools/updateoperation.cpp b/src/libs/kdtools/updateoperation.cpp
index 81f456755..6a7e62f2b 100644
--- a/src/libs/kdtools/updateoperation.cpp
+++ b/src/libs/kdtools/updateoperation.cpp
@@ -652,7 +652,7 @@ bool UpdateOperation::fromXml(const QDomDocument &doc)
const QString value = v.text();
const QVariant::Type t = QVariant::nameToType(type.toLatin1().data());
- QVariant var = qVariantFromValue(value);
+ QVariant var = QVariant::fromValue(value);
if (t == QVariant::List || t == QVariant::StringList || !var.convert(t)) {
QDataStream stream(QByteArray::fromBase64( value.toLatin1()));
stream >> var;
diff --git a/src/libs/kdtools/updatesinfo.cpp b/src/libs/kdtools/updatesinfo.cpp
index 545931a55..fafeb4f18 100644
--- a/src/libs/kdtools/updatesinfo.cpp
+++ b/src/libs/kdtools/updatesinfo.cpp
@@ -28,13 +28,14 @@
#include "updatesinfo_p.h"
#include "utils.h"
+#include "constants.h"
-#include <QDomDocument>
#include <QFile>
#include <QLocale>
#include <QPair>
#include <QVector>
#include <QUrl>
+#include <QXmlStreamReader>
using namespace KDUpdater;
@@ -62,35 +63,24 @@ void UpdatesInfoData::parseFile(const QString &updateXmlFile)
return;
}
- QDomDocument doc;
- QString parseErrorMessage;
- int parseErrorLine, parseErrorColumn;
- if (!doc.setContent(&file, &parseErrorMessage, &parseErrorLine, &parseErrorColumn)) {
- error = UpdatesInfo::InvalidXmlError;
- errorMessage = tr("Parse error in %1 at %2, %3: %4").arg(updateXmlFile,
- QString::number(parseErrorLine), QString::number(parseErrorColumn), parseErrorMessage);
- return;
- }
-
- QDomElement rootE = doc.documentElement();
- if (rootE.tagName() != QLatin1String("Updates")) {
- setInvalidContentError(tr("Root element %1 unexpected, should be \"Updates\".").arg(rootE.tagName()));
- return;
- }
-
- QDomNodeList childNodes = rootE.childNodes();
- for(int i = 0; i < childNodes.count(); i++) {
- const QDomElement childE = childNodes.at(i).toElement();
- if (childE.isNull())
- continue;
-
- if (childE.tagName() == QLatin1String("ApplicationName"))
- applicationName = childE.text();
- else if (childE.tagName() == QLatin1String("ApplicationVersion"))
- applicationVersion = childE.text();
- else if (childE.tagName() == QLatin1String("PackageUpdate")) {
- if (!parsePackageUpdateElement(childE))
- return; //error handled in subroutine
+ QXmlStreamReader reader(&file);
+ if (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("Updates")) {
+ while (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("ApplicationName")) {
+ applicationName = reader.readElementText();
+ } else if (reader.name() == QLatin1String("ApplicationVersion")) {
+ applicationVersion = reader.readElementText();
+ } else if (reader.name() == QLatin1String("PackageUpdate")) {
+ if (!parsePackageUpdateElement(reader))
+ return; //error handled in subroutine
+ } else {
+ reader.skipCurrentElement();
+ }
+ }
+ } else {
+ setInvalidContentError(tr("Root element %1 unexpected, should be \"Updates\".").arg(reader.name()));
+ return;
}
}
@@ -108,74 +98,51 @@ void UpdatesInfoData::parseFile(const QString &updateXmlFile)
error = UpdatesInfo::NoError;
}
-bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE)
+bool UpdatesInfoData::parsePackageUpdateElement(QXmlStreamReader &reader)
{
- if (updateE.isNull())
- return false;
-
UpdateInfo info;
- QMap<QString, QString> localizedDescriptions;
- for (int i = 0; i < updateE.childNodes().count(); i++) {
- QDomElement childE = updateE.childNodes().at(i).toElement();
- if (childE.isNull())
+ QHash<QString, QVariant> scriptHash;
+ while (reader.readNext()) {
+ const QString elementName = reader.name().toString();
+ if ((reader.name() == QLatin1String("PackageUpdate"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
+ }
+ if (elementName.isEmpty() || reader.tokenType() == QXmlStreamReader::EndElement)
continue;
-
- if (childE.tagName() == QLatin1String("ReleaseNotes")) {
- info.data[childE.tagName()] = QUrl(childE.text());
- } else if (childE.tagName() == QLatin1String("Licenses")) {
- QHash<QString, QVariant> licenseHash;
- const QDomNodeList licenseNodes = childE.childNodes();
- for (int index = 0; index < licenseNodes.count(); ++index) {
- const QDomNode licenseNode = licenseNodes.at(index);
- if (licenseNode.nodeName() == QLatin1String("License")) {
- QDomElement element = licenseNode.toElement();
- QVariantMap attributes;
- attributes.insert(QLatin1String("file"), element.attributeNode(QLatin1String("file")).value());
- if (!element.attributeNode(QLatin1String("priority")).isNull())
- attributes.insert(QLatin1String("priority"), element.attributeNode(QLatin1String("priority")).value());
- else
- attributes.insert(QLatin1String("priority"), QLatin1String("0"));
- licenseHash.insert(element.attributeNode(QLatin1String("name")).value(), attributes);
- }
- }
- if (!licenseHash.isEmpty())
- info.data.insert(QLatin1String("Licenses"), licenseHash);
- } else if (childE.tagName() == QLatin1String("TreeName")) {
- const bool moveChildren = QVariant(childE.attribute(QLatin1String("moveChildren"))).toBool();
- const QPair<QString, bool> treeNamePair(childE.text(), moveChildren);
+ if (elementName == QLatin1String("Licenses")) {
+ parseLicenses(reader, info.data);
+ } else if (elementName == QLatin1String("TreeName")) {
+ const QXmlStreamAttributes attr = reader.attributes();
+ const bool moveChildren = attr.value(QLatin1String("moveChildren")).toString().toLower() == QInstaller::scTrue ? true : false;
+ const QPair<QString, bool> treeNamePair(reader.readElementText(), moveChildren);
info.data.insert(QLatin1String("TreeName"), QVariant::fromValue(treeNamePair));
- } else if (childE.tagName() == QLatin1String("Version")) {
+ } else if (elementName == QLatin1String("Version")) {
+ const QXmlStreamAttributes attr = reader.attributes();
info.data.insert(QLatin1String("inheritVersionFrom"),
- childE.attribute(QLatin1String("inheritVersionFrom")));
- info.data[childE.tagName()] = childE.text();
- } else if (childE.tagName() == QLatin1String("DisplayName")) {
- processLocalizedTag(childE, info.data);
- } else if (childE.tagName() == QLatin1String("Description")) {
- if (!childE.hasAttribute(QLatin1String("xml:lang")))
- info.data[QLatin1String("Description")] = childE.text();
- QString languageAttribute = childE.attribute(QLatin1String("xml:lang"), QLatin1String("en"));
- localizedDescriptions.insert(languageAttribute.toLower(), childE.text());
- } else if (childE.tagName() == QLatin1String("UpdateFile")) {
- info.data[QLatin1String("CompressedSize")] = childE.attribute(QLatin1String("CompressedSize"));
- info.data[QLatin1String("UncompressedSize")] = childE.attribute(QLatin1String("UncompressedSize"));
- } else if (childE.tagName() == QLatin1String("Operations")) {
- const QDomNodeList operationNodes = childE.childNodes();
- QVariant operationListVariant = parseOperations(childE.childNodes());
- info.data.insert(QLatin1String("Operations"), operationListVariant);
+ attr.value(QLatin1String("inheritVersionFrom")).toString());
+ info.data[elementName] = reader.readElementText();
+ } else if (elementName == QLatin1String("DisplayName")
+ || elementName == QLatin1String("Description")) {
+ processLocalizedTag(reader, info.data);
+ } else if (elementName == QLatin1String("UpdateFile")) {
+ info.data[QLatin1String("CompressedSize")] = reader.attributes().value(QLatin1String("CompressedSize")).toString();
+ info.data[QLatin1String("UncompressedSize")] = reader.attributes().value(QLatin1String("UncompressedSize")).toString();
+ } else if (elementName == QLatin1String("Operations")) {
+ parseOperations(reader, info.data);
+ } else if (elementName == QLatin1String("Script")) {
+ const QXmlStreamAttributes attr = reader.attributes();
+ const bool postLoad = attr.value(QLatin1String("postLoad")).toString().toLower() == QInstaller::scTrue ? true : false;
+ if (postLoad)
+ scriptHash.insert(QLatin1String("postLoadScript"), reader.readElementText());
+ else
+ scriptHash.insert(QLatin1String("installScript"), reader.readElementText());
} else {
- info.data[childE.tagName()] = childE.text();
- }
- }
-
- QStringList candidates;
- foreach (const QString &lang, QLocale().uiLanguages())
- candidates << QInstaller::localeCandidates(lang.toLower());
- foreach (const QString &candidate, candidates) {
- if (localizedDescriptions.contains(candidate)) {
- info.data[QLatin1String("Description")] = localizedDescriptions.value(candidate);
- break;
+ info.data[elementName] = reader.readElementText();
}
}
+ if (!scriptHash.isEmpty())
+ info.data.insert(QLatin1String("Script"), scriptHash);
if (!info.data.contains(QLatin1String("Name"))) {
setInvalidContentError(tr("PackageUpdate element without Name"));
@@ -194,44 +161,77 @@ bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE)
return true;
}
-void UpdatesInfoData::processLocalizedTag(const QDomElement &childE, QHash<QString, QVariant> &info) const
+void UpdatesInfoData::processLocalizedTag(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const
{
- QString languageAttribute = childE.attribute(QLatin1String("xml:lang")).toLower();
- if (!info.contains(childE.tagName()) && (languageAttribute.isEmpty()))
- info[childE.tagName()] = childE.text();
+ const QString languageAttribute = reader.attributes().value(QLatin1String("xml:lang")).toString().toLower();
+ const QString elementName = reader.name().toString();
+ if (!info.contains(elementName) && (languageAttribute.isEmpty()))
+ info[elementName] = reader.readElementText();
+ if (languageAttribute.isEmpty())
+ return;
// overwrite default if we have a language specific description
if (QLocale().name().startsWith(languageAttribute, Qt::CaseInsensitive))
- info[childE.tagName()] = childE.text();
+ info[elementName] = reader.readElementText();
}
-QVariant UpdatesInfoData::parseOperations(const QDomNodeList &operationNodes)
+void UpdatesInfoData::parseOperations(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const
{
- QVariant operationListVariant;
QList<QPair<QString, QVariant>> operationsList;
- for (int i = 0; i < operationNodes.count(); ++i) {
- const QDomNode operationNode = operationNodes.at(i);
- if (operationNode.nodeName() == QLatin1String("Operation")) {
- const QDomNodeList argumentNodes = operationNode.childNodes();
- QStringList attributes;
- for (int index = 0; index < argumentNodes.count(); ++index) {
- const QDomNode argumentNode = argumentNodes.at(index);
- if (argumentNode.nodeName() == QLatin1String("Argument")) {
- QDomElement argumentElement = argumentNode.toElement();
- attributes.append(argumentElement.text());
- }
+ while (reader.readNext()) {
+ const QString subElementName = reader.name().toString();
+ // End of parsing operations
+ if ((subElementName == QLatin1String("Operations"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
+ }
+ if (subElementName != QLatin1String("Operation") || reader.tokenType() == QXmlStreamReader::EndElement)
+ continue;
+ QStringList attributes;
+ const QXmlStreamAttributes attr = reader.attributes();
+ while (reader.readNext()) {
+ const QString subElementName2 = reader.name().toString();
+ // End of parsing single operation
+ if ((subElementName2 == QLatin1String("Operation"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
}
- QPair<QString, QVariant> pair;
- pair.first = operationNode.toElement().attributeNode(QLatin1String("name")).value();
- pair.second = attributes;
- operationsList.append(pair);
+ if (subElementName2 != QLatin1String("Argument") || reader.tokenType() == QXmlStreamReader::EndElement)
+ continue;
+ attributes.append(reader.readElementText());
}
+ QPair<QString, QVariant> pair;
+ pair.first = attr.value(QLatin1String("name")).toString();
+ pair.second = attributes;
+ operationsList.append(pair);
}
- operationListVariant.setValue(operationsList);
- return operationListVariant;
+ info.insert(QLatin1String("Operations"), QVariant::fromValue(operationsList));
}
-
+void UpdatesInfoData::parseLicenses(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const
+{
+ QHash<QString, QVariant> licenseHash;
+ while (reader.readNext()) {
+ const QString subElementName = reader.name().toString();
+ // End of parsing Licenses
+ if ((subElementName == QLatin1String("Licenses"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
+ }
+ if (subElementName != QLatin1String("License") || reader.tokenType() == QXmlStreamReader::EndElement)
+ continue;
+ const QXmlStreamAttributes attr = reader.attributes();
+ QVariantMap attributes;
+ attributes.insert(QLatin1String("file"), attr.value(QLatin1String("file")).toString());
+ if (!attr.value(QLatin1String("priority")).isNull())
+ attributes.insert(QLatin1String("priority"), attr.value(QLatin1String("priority")).toString());
+ else
+ attributes.insert(QLatin1String("priority"), QLatin1String("0"));
+ licenseHash.insert(attr.value(QLatin1String("name")).toString(), attributes);
+ }
+ if (!licenseHash.isEmpty())
+ info.insert(QLatin1String("Licenses"), licenseHash);
+}
//
// UpdatesInfo
//
diff --git a/src/libs/kdtools/updatesinfodata_p.h b/src/libs/kdtools/updatesinfodata_p.h
index 07da6fcf0..9c3c7dce0 100644
--- a/src/libs/kdtools/updatesinfodata_p.h
+++ b/src/libs/kdtools/updatesinfodata_p.h
@@ -32,8 +32,7 @@
#include <QCoreApplication>
#include <QSharedData>
-QT_FORWARD_DECLARE_CLASS(QDomElement)
-QT_FORWARD_DECLARE_CLASS(QDomNodeList)
+QT_FORWARD_DECLARE_CLASS(QXmlStreamReader)
namespace KDUpdater {
@@ -55,13 +54,14 @@ public:
QList<UpdateInfo> updateInfoList;
void parseFile(const QString &updateXmlFile);
- bool parsePackageUpdateElement(const QDomElement &updateE);
+ bool parsePackageUpdateElement(QXmlStreamReader &reader);
void setInvalidContentError(const QString &detail);
private:
- void processLocalizedTag(const QDomElement &childE, QHash<QString, QVariant> &info) const;
- QVariant parseOperations(const QDomNodeList &operationNodes);
+ void processLocalizedTag(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const;
+ void parseOperations(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const;
+ void parseLicenses(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const;
};
} // namespace KDUpdater
diff --git a/src/sdk/commandlineinterface.cpp b/src/sdk/commandlineinterface.cpp
index a1eea1f8d..afc5c2f42 100644
--- a/src/sdk/commandlineinterface.cpp
+++ b/src/sdk/commandlineinterface.cpp
@@ -303,7 +303,7 @@ QHash<QString, QString> CommandLineInterface::parsePackageFilters()
const QString element = filter.left(i).trimmed();
const QString value = filter.mid(i + 1).trimmed();
- if ((i == -1) || (filter.count(QLatin1Char('=') > 1))
+ if ((i == -1) || (filter.count(QLatin1Char('=')) > 1)
|| element.isEmpty() || value.isEmpty()) {
qCWarning(QInstaller::lcInstallerInstallLog).nospace() << "Ignoring unknown entry "
<< filter << "in package filter arguments. Please use syntax \"element=regex,...\".";
diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp
index dcbf15228..20a4f312b 100644
--- a/src/sdk/installerbase.cpp
+++ b/src/sdk/installerbase.cpp
@@ -104,8 +104,8 @@ int InstallerBase::run()
if (squishPort <= 0 || squishPort > maxSquishPortNumber) {
qWarning().noquote() << "Invalid Squish port:" << squishPort;
} else {
- Squish::allowAttaching(squishPort);
- qCDebug(QInstaller::lcDeveloperBuild) << "Attaching to squish port" << squishPort << "succeeded";
+ bool attachSucceeded = Squish::allowAttaching(squishPort);
+ qCDebug(QInstaller::lcDeveloperBuild) << "Attach to squish port" << squishPort << "succeeded: "<<attachSucceeded;
}
}
#endif
diff --git a/src/sdk/main.cpp b/src/sdk/main.cpp
index f7368883b..efaf44582 100644
--- a/src/sdk/main.cpp
+++ b/src/sdk/main.cpp
@@ -49,11 +49,12 @@
#include <QDateTime>
#include <QNetworkProxyFactory>
#include <QThread>
+#include <QThreadPool>
#include <QDeadlineTimer>
#include <iostream>
-#if defined(Q_OS_MACOS) or defined(Q_OS_UNIX)
+#if defined(Q_OS_MACOS) || defined(Q_OS_UNIX)
# include <unistd.h>
# include <sys/types.h>
#endif
@@ -111,8 +112,10 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
}
#if defined(Q_OS_WIN)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
#endif
+#endif
// increase maximum numbers of file descriptors
#if defined(Q_OS_MACOS)
QCoreApplication::setSetuidAllowed(true);
@@ -122,6 +125,13 @@ int main(int argc, char *argv[])
setrlimit(RLIMIT_NOFILE, &rl);
#endif
+ // Try to avoid running into situations where the application would hang due to "nested" blocking
+ // usage of the global threadpool that has only one thread available, i.e. main thread invokes
+ // QtConcurrent::run(&myFunction) and myFunction() calls QtConcurrent::blockingFiltered()
+ // for a container.
+ if (QThread::idealThreadCount() == 1)
+ QThreadPool::globalInstance()->setMaxThreadCount(2);
+
// We need to start either a command line application or a GUI application. Since we
// fail doing so at least on Linux while parsing the argument using a core application
// object and later starting the GUI application, we now parse the arguments first.
diff --git a/src/sdk/sdk.pro b/src/sdk/sdk.pro
index 4a47fb825..fac8f4f49 100644
--- a/src/sdk/sdk.pro
+++ b/src/sdk/sdk.pro
@@ -104,7 +104,7 @@ HEADERS += \
installerbase.h \
aboutapplicationdialog.h
-SOURCES = \
+SOURCES += \
main.cpp \
installerbase.cpp \
tabcontroller.cpp \
diff --git a/src/sdk/sdkapp.h b/src/sdk/sdkapp.h
index 7d39ee3cf..ba542691e 100644
--- a/src/sdk/sdkapp.h
+++ b/src/sdk/sdkapp.h
@@ -200,7 +200,8 @@ public:
const QStringList translations = m_core->settings().translations();
if (translations.isEmpty()) {
- foreach (const QLocale locale, QLocale().uiLanguages()) {
+ for (const QString &language : QLocale().uiLanguages()) {
+ const QLocale locale(language);
QScopedPointer<QTranslator> qtTranslator(new QTranslator(QCoreApplication::instance()));
bool qtLoaded = qtTranslator->load(locale, QLatin1String("qt"),
QLatin1String("_"), newDirectory);
@@ -597,7 +598,7 @@ public:
QString controlScript = QString();
if (m_parser.isSet(CommandLineOptions::scScriptLong)) {
controlScript = m_parser.value(CommandLineOptions::scScriptLong);
- if (!QFileInfo(controlScript).exists())
+ if (!QFileInfo::exists(controlScript))
qCDebug(QInstaller::lcInstallerInstallLog) << "Script file does not exist.";
} else if (!m_core->settings().controlScript().isEmpty()) {
diff --git a/src/sdk/settingsdialog.cpp b/src/sdk/settingsdialog.cpp
index b807deccd..acd364b2f 100644
--- a/src/sdk/settingsdialog.cpp
+++ b/src/sdk/settingsdialog.cpp
@@ -257,6 +257,13 @@ SettingsDialog::SettingsDialog(PackageManagerCore *core, QWidget *parent)
}
m_ui->m_cachePathLineEdit->setText(settings.localCachePath());
+ showClearCacheProgress(false);
+}
+
+void SettingsDialog::showClearCacheProgress(bool show)
+{
+ m_ui->m_clearCacheProgressLabel->setVisible(show);
+ m_ui->m_clearCacheProgressBar->setVisible(show);
}
void SettingsDialog::accept()
diff --git a/src/sdk/settingsdialog.h b/src/sdk/settingsdialog.h
index bc618d6b7..5f5c017a8 100644
--- a/src/sdk/settingsdialog.h
+++ b/src/sdk/settingsdialog.h
@@ -104,6 +104,8 @@ class SettingsDialog : public QDialog
public:
explicit SettingsDialog(QInstaller::PackageManagerCore *core, QWidget *parent = 0);
+ void showClearCacheProgress(bool show);
+
public slots:
void accept();
diff --git a/src/sdk/settingsdialog.ui b/src/sdk/settingsdialog.ui
index 0254abd98..9d4ba9577 100644
--- a/src/sdk/settingsdialog.ui
+++ b/src/sdk/settingsdialog.ui
@@ -304,6 +304,42 @@
</layout>
</item>
<item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_clearCacheProgressLabel">
+ <property name="text">
+ <string>Clearing cache...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="m_clearCacheProgressBar">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximum">
+ <number>0</number>
+ </property>
+ <property name="value">
+ <number>-1</number>
+ </property>
+ <property name="format">
+ <string>%p%</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/sdk/tabcontroller.cpp b/src/sdk/tabcontroller.cpp
index cb3242841..089bd8468 100644
--- a/src/sdk/tabcontroller.cpp
+++ b/src/sdk/tabcontroller.cpp
@@ -38,6 +38,7 @@
#include <QtCore/QTimer>
#include <QtWidgets/QMessageBox>
+#include <QtConcurrent>
using namespace QInstaller;
@@ -198,10 +199,31 @@ void TabController::onAboutApplicationClicked()
void TabController::onClearCacheClicked()
{
- QDialog *settingsDialog = static_cast<QDialog *>(sender());
+ SettingsDialog *settingsDialog = static_cast<SettingsDialog *>(sender());
+ settingsDialog->setEnabled(false);
+ settingsDialog->showClearCacheProgress(true);
QString errorMessage;
- const bool success = d->m_core->clearLocalCache(&errorMessage);
+ bool success = true;
+
+ // Clearing might take some time, run in a separate thread
+ QEventLoop loop;
+ QFutureWatcher<bool> futureWatcher;
+
+ connect(&futureWatcher, &QFutureWatcher<bool>::finished, this, [&]() {
+ success = futureWatcher.future().result();
+ if (loop.isRunning())
+ loop.quit();
+ });
+
+ futureWatcher.setFuture(QtConcurrent::run(d->m_core,
+ &PackageManagerCore::clearLocalCache, &errorMessage));
+
+ if (!futureWatcher.isFinished())
+ loop.exec();
+
+ settingsDialog->setEnabled(true);
+ settingsDialog->showClearCacheProgress(false);
QMessageBox msgBox(settingsDialog);
msgBox.setWindowModality(Qt::WindowModal);
diff --git a/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp
index afa11d707..9fbc12c41 100644
--- a/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp
+++ b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp
@@ -125,7 +125,7 @@ private slots:
const QString debugMessage = QString("Exception while loading the component script");
const QRegularExpression re(debugMessage);
QTest::ignoreMessage(QtWarningMsg, re);
- invalidScriptComponent->loadComponentScript(":///data/broken_script.qs");
+ invalidScriptComponent->evaluateComponentScript(":///data/broken_script.qs");
model->reset(components);
testModelState(model, m_checkedComponentsWithBrokenScript, m_partiallyCheckedComponentsWithBrokenScript, m_uncheckedComponentsWithBrokenScript);
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml
index 81831ed5b..3b5e22cc0 100644
--- a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml
@@ -170,4 +170,14 @@
<DownloadableArchives>content.7z</DownloadableArchives>
<Virtual>true</Virtual>
</PackageUpdate>
+ <PackageUpdate>
+ <Name>componentJ</Name>
+ <DisplayName>component J</DisplayName>
+ <Description>This component has post install script.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Script postLoad="True">postLoadscript.js</Script>
+ </PackageUpdate>
</Updates>
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z
new file mode 100644
index 000000000..58ff52baa
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z
new file mode 100644
index 000000000..be99410a8
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/settings.qrc b/tests/auto/installer/commandlineinstall/settings.qrc
index 824517e1e..992dbfd58 100644
--- a/tests/auto/installer/commandlineinstall/settings.qrc
+++ b/tests/auto/installer/commandlineinstall/settings.qrc
@@ -14,6 +14,8 @@
<file>data/installPackagesRepository/componentG/1.0.0content.7z</file>
<file>data/installPackagesRepository/componentH/1.0.0content.7z</file>
<file>data/installPackagesRepository/componentI/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentJ/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentJ/1.0.0meta.7z</file>
<file>data/installPackagesRepository/componentG/1.0.0meta.7z</file>
<file>data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z</file>
<file>data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z</file>
diff --git a/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp b/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp
index 1e269b7ff..a986234c8 100644
--- a/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp
+++ b/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp
@@ -47,19 +47,32 @@ class tst_CommandLineInstall : public QObject
{
Q_OBJECT
+public:
+ void ignoreAvailablePackagesMissingMessages()
+ {
+ QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Searching packages with regular expression:"));
+ QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
+ QTest::ignoreMessage(QtDebugMsg, "Loading component scripts...");
+ QTest::ignoreMessage(QtDebugMsg, "No matching packages found.");
+ }
+
+ void ignoreInstallPackageFailsMessages(const QRegularExpression &regExp)
+ {
+ QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
+ QTest::ignoreMessage(QtDebugMsg, "Loading component scripts...");
+ QTest::ignoreMessage(QtDebugMsg, regExp);
+ }
+
private slots:
void testListAvailablePackages()
{
QString loggingRules = (QLatin1String("ifw.* = false\n"));
- QTest::ignoreMessage(QtDebugMsg, "Operations sanity check succeeded.");
-
+ QLoggingCategory::setFilterRules(loggingRules);
QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager
(m_installDir, ":///data/repository"));
- QLoggingCategory::setFilterRules(loggingRules);
auto func = &PackageManagerCore::listAvailablePackages;
-
verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
"<availablepackages>\n"
" <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n"
@@ -113,13 +126,11 @@ private slots:
" <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n"
"</availablepackages>\n"), func, QString(), searchHash);
- // Need to change rules here to catch messages
QLoggingCategory::setFilterRules("ifw.* = true\n");
-
- QTest::ignoreMessage(QtDebugMsg, "No matching packages found.");
+ ignoreAvailablePackagesMissingMessages();
core->listAvailablePackages(QLatin1String("C.virt"));
- QTest::ignoreMessage(QtDebugMsg, "No matching packages found.");
+ ignoreAvailablePackagesMissingMessages();
core->listAvailablePackages(QLatin1String("C.virt.subcomponent"));
}
@@ -128,37 +139,33 @@ private slots:
QString loggingRules = (QLatin1String("ifw.* = false\n"
"ifw.installer.installlog = true\n"));
+ QLoggingCategory::setFilterRules(loggingRules);
+ QTest::ignoreMessage(QtDebugMsg, "Operations sanity check succeeded.");
+ QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Using metadata cache from "));
QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager
(m_installDir, ":///data/uninstallableComponentsRepository"));
- QLoggingCategory::setFilterRules(loggingRules);
-
- QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
- QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install component A. Component "
- "is installed only as automatic dependency to autoDep.\n"));
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install component A. Component "
+ "is installed only as automatic dependency to autoDep.\n"));
QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
<< QLatin1String("A")));
- QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
- QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install component AB. Component "
- "is not checkable, meaning you have to select one of the subcomponents.\n"));
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install component AB. Component "
+ "is not checkable, meaning you have to select one of the subcomponents.\n"));
QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
<< QLatin1String("AB")));
- QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
- QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install B. Component is virtual.\n"));
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install B. Component is virtual.\n"));
QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
<< QLatin1String("B")));
- QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
- QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install B.subcomponent. Component "
- "is a descendant of a virtual component B.\n"));
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install B.subcomponent. Component "
+ "is a descendant of a virtual component B.\n"));
QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
<< QLatin1String("B.subcomponent")));
- QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
- QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install MissingComponent. "
- "Component not found.\n"));
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install MissingComponent. "
+ "Component not found.\n"));
QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
<< QLatin1String("MissingComponent")));
QCOMPARE(PackageManagerCore::Canceled, core->status());
@@ -722,6 +729,21 @@ private slots:
QVERIFY(file.remove());
}
+ void testPostScript()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << QLatin1String("componentJ")));
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentJ", "1.0.0content.txt"); //Selected
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt"); //Dependency for componentG
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt"); //ForcedInstall
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentG", "1.0.0content.txt"); //Default
+
+ //componentJ is extracted to "extractToAnotherPath" -folder in post install script
+ bool fileExists = QFileInfo::exists(m_installDir + QDir::separator() + "extractToAnotherPath" + QDir::separator() + "installcontentJ.txt");
+ QVERIFY2(fileExists, QString("File \"%1\" does not exist.").arg("installcontentJ.txt").toLatin1());
+ }
+
void init()
{
m_installDir = QInstaller::generateTemporaryFileName();
diff --git a/tests/auto/installer/componentmodel/data/updates.xml b/tests/auto/installer/componentmodel/data/updates.xml
index 3a6139446..cc2da0f8e 100644
--- a/tests/auto/installer/componentmodel/data/updates.xml
+++ b/tests/auto/installer/componentmodel/data/updates.xml
@@ -8,6 +8,8 @@
<DisplayName xml:lang="ru_RU">Корневая компонента</DisplayName>
<DisplayName xml:lang="de_DE">Wurzel Komponente</DisplayName>
<Description>Install this example.</Description>
+ <Description xml:lang="ru_RU">Установите этот пример.</Description>
+ <Description xml:lang="de_DE">Installieren Sie dieses Beispiel.</Description>
<Version>0.1.0-1</Version>
<ReleaseDate>2010-09-21</ReleaseDate>
<Default>true</Default>
diff --git a/tests/auto/installer/componentmodel/tst_componentmodel.cpp b/tests/auto/installer/componentmodel/tst_componentmodel.cpp
index 463485d96..2836c80df 100644
--- a/tests/auto/installer/componentmodel/tst_componentmodel.cpp
+++ b/tests/auto/installer/componentmodel/tst_componentmodel.cpp
@@ -59,6 +59,12 @@ static const QMap<QString, QString> rootComponentDisplayNames = {
{"de_de", QString::fromUtf8("Wurzel Komponente")}
};
+static const QMap<QString, QString> rootComponentDescriptions = {
+ {"", QLatin1String("Install this example.")},
+ {"ru_ru", QString::fromUtf8("Установите этот пример.")},
+ {"de_de", QString::fromUtf8("Installieren Sie dieses Beispiel.")}
+};
+
class tst_ComponentModel : public QObject
{
Q_OBJECT
@@ -372,6 +378,10 @@ private slots:
? rootComponentDisplayNames[localeToTest.toLower()]
: rootComponentDisplayNames[QString()];
+ QString expectedDescription = rootComponentDescriptions.contains(localeToTest.toLower())
+ ? rootComponentDescriptions[localeToTest.toLower()]
+ : rootComponentDescriptions[QString()];
+
setPackageManagerOptions(NoFlags);
QList<Component*> rootComponents = loadComponents();
@@ -384,6 +394,9 @@ private slots:
const QModelIndex root = model.indexFromComponentName(vendorProduct);
QCOMPARE(model.data(root, Qt::DisplayRole).toString(), expectedName);
+ Component *comp = model.componentFromIndex(root);
+ QCOMPARE(comp->value("Description"), expectedDescription);
+
qDeleteAll(rootComponents);
}
}
@@ -529,6 +542,7 @@ private:
component->setValue("Virtual", info.data.value("Virtual").toString());
component->setValue("DisplayName", info.data.value("DisplayName").toString());
component->setValue("Checkable", info.data.value("Checkable").toString());
+ component->setValue("Description", info.data.value("Description").toString());
QString forced = info.data.value("ForcedInstallation", scFalse).toString().toLower();
if (m_core.noForceInstallation())
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml
new file mode 100644
index 000000000..fe5dc4dec
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml
@@ -0,0 +1,28 @@
+<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>componentEssential</Name>
+ <DisplayName>Component Essential</DisplayName>
+ <Description>Component Essential</Description>
+ <Essential>true</Essential>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile UncompressedSize="101" CompressedSize="283" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z
new file mode 100644
index 000000000..bdbabc7fd
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z
new file mode 100644
index 000000000..9c86042c0
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml
new file mode 100644
index 000000000..f76c03faa
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml
@@ -0,0 +1,27 @@
+<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>componentEssential</Name>
+ <DisplayName>Component Essential</DisplayName>
+ <Description>Component Essential</Description>
+ <Essential>true</Essential>
+ <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/repositoryWithEssential/componentA/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z
new file mode 100644
index 000000000..46a9f1d1e
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z
new file mode 100644
index 000000000..435f260ee
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/settings.qrc b/tests/auto/installer/contentshaupdate/settings.qrc
index a5d045f46..e3426be92 100644
--- a/tests/auto/installer/contentshaupdate/settings.qrc
+++ b/tests/auto/installer/contentshaupdate/settings.qrc
@@ -5,10 +5,16 @@
<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/repositoryWithEssential/Updates.xml</file>
+ <file>data/repositoryWithEssential/componentA/1.0.0content.7z</file>
+ <file>data/repositoryWithEssential/componentEssential/2.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>
+ <file>data/repositoryUpdateWithEssential/Updates.xml</file>
+ <file>data/repositoryUpdateWithEssential/componentA/0.1.0content.7z</file>
+ <file>data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z</file>
</qresource>
</RCC>
diff --git a/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp
index d8d2f5377..5d282fe38 100644
--- a/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp
+++ b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp
@@ -58,34 +58,50 @@ private slots:
void updateWithContentSha1_data()
{
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QString>("repositoryForUpdate");
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;
+ QTest::newRow("Sha1UpdateForEssential")
+ << ":///data/repositoryWithEssential" << ":///data/repositoryUpdateWithEssential"
+ << "componentEssential" << "2.0.0content.txt" << "1.0.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::EssentialUpdated;
+ QTest::newRow("ContentSha1Change")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentA" << "1.0.0content.txt" << "0.1.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Success;
+ QTest::newRow("NewContentSha1")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentB" << "1.0.0content.txt" << "0.1.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Success;
+ QTest::newRow("SameContentSha1")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentC" << "1.0.0content.txt" << "1.0.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Canceled;
+ QTest::newRow("Sha1RemovedFromRepo")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentD" << "1.0.0content.txt" << "2.0.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Success;
}
void updateWithContentSha1()
{
+ QFETCH(QString, repository);
+ QFETCH(QString, repositoryForUpdate);
QFETCH(QString, component);
QFETCH(QString, content);
QFETCH(QString, updatedContent);
QFETCH(PackageManagerCore::Status, expectedStatusAfterInstall);
QFETCH(PackageManagerCore::Status, expectedStatusAfterUpdate);
- setRepository(":///data/repository");
+ setRepository(repository);
QCOMPARE(expectedStatusAfterInstall, core->installSelectedComponentsSilently(QStringList() << component));
QCOMPARE(expectedStatusAfterInstall, core->status());
VerifyInstaller::verifyInstallerResources(m_installDir, component, content);
core->commitSessionOperations();
core->setPackageManager();
- setRepository(":///data/repositoryUpdate");
+ setRepository(repositoryForUpdate);
QCOMPARE(expectedStatusAfterUpdate, core->updateComponentsSilently(QStringList()));
VerifyInstaller::verifyInstallerResources(m_installDir, component, updatedContent);
}
diff --git a/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp
index aa2849559..ef185a5cf 100644
--- a/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp
+++ b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.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.
@@ -46,12 +46,12 @@ private slots:
m_core.setValue(QLatin1String("QMAKE_BINARY"), QUOTE(QMAKE_BINARY));
m_core.setValue(QLatin1String("QMAKE_BINARY_OLD"), QLatin1String("FAKE_QMAKE"));
ElevatedExecuteOperation operation(&m_core);
- operation.setArguments(QStringList() << QLatin1String("UNDOEXECUTE") << QLatin1String("FAKE_QMAKE"));
+ operation.setArguments(QStringList() << QLatin1String("UNDOEXECUTE") << QLatin1String("FAKE_QMAKE") << QLatin1String("-v"));
- QTest::ignoreMessage(QtDebugMsg, "\"FAKE_QMAKE\" started, arguments: \"\"");
- QString message = "Failed to run undo operation \"Execute\" for component . Trying again with arguments %1";
+ QTest::ignoreMessage(QtDebugMsg, "\"FAKE_QMAKE\" started, arguments: \"-v\"");
+ QString message = "Failed to run undo operation \"Execute\" for component . Trying again with arguments %1, -v";
QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY))));
- message = "\"%1\" started, arguments: \"\"";
+ message = "\"%1\" started, arguments: \"-v\"";
QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY))));
QCOMPARE(operation.undoOperation(), true);
diff --git a/tests/auto/installer/scriptengine/tst_scriptengine.cpp b/tests/auto/installer/scriptengine/tst_scriptengine.cpp
index 105bcf5d7..6c55fe205 100644
--- a/tests/auto/installer/scriptengine/tst_scriptengine.cpp
+++ b/tests/auto/installer/scriptengine/tst_scriptengine.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 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.
@@ -388,13 +388,24 @@ private slots:
QCOMPARE(result.isError(), false);
}
+ void loadSimpleComponentScript_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("postLoad");
+ QTest::newRow("Pre component script") << ":///data/component1.qs" << false;
+ QTest::newRow("Post component script") << ":///data/component1.qs" << true;
+ }
+
void loadSimpleComponentScript()
{
- try {
- // ignore retranslateUi which is called by loadComponentScript
+ QFETCH(QString, path);
+ QFETCH(bool, postLoad);
+
+ try {
+ // ignore retranslateUi which is called by evaluateComponentScript
setExpectedScriptOutput("Component constructor - OK");
setExpectedScriptOutput("retranslateUi - OK");
- m_component->loadComponentScript(":///data/component1.qs");
+ m_component->evaluateComponentScript(path, postLoad);
setExpectedScriptOutput("retranslateUi - OK");
m_component->languageChanged();
@@ -422,8 +433,19 @@ private slots:
}
}
+ void loadBrokenComponentScript_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("postLoad");
+ QTest::newRow("Pre component script") << ":///data/component2.qs" << false;
+ QTest::newRow("Post component script") << ":///data/component2.qs" << true;
+ }
+
void loadBrokenComponentScript()
{
+ QFETCH(QString, path);
+ QFETCH(bool, postLoad);
+
Component *testComponent = new Component(&m_core);
testComponent->setValue(scName, "broken.component");
@@ -433,21 +455,31 @@ private slots:
try {
// ignore Output from script
setExpectedScriptOutput("script function: Component");
- testComponent->loadComponentScript(":///data/component2.qs");
+ testComponent->evaluateComponentScript(path, postLoad);
} catch (const Error &error) {
const QString debugMessage(
- QString("create Error-Exception: \"Exception while loading the component script \"%1\": "
- "ReferenceError: broken is not defined\"").arg(QDir::toNativeSeparators(":///data/component2.qs")));
+ QString("Exception while loading the component script \"%1\": "
+ "ReferenceError: broken is not defined on line number: 33").arg(QDir::toNativeSeparators(":///data/component2.qs")));
QVERIFY2(debugMessage.contains(error.message()), "(ReferenceError: broken is not defined)");
}
}
+ void loadComponentUserInterfaces_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("postLoad");
+ QTest::newRow("Pre component script") << ":///data/userinterface.qs" << false;
+ QTest::newRow("Post component script") << ":///data/userinterface.qs" << true;
+ }
+
void loadComponentUserInterfaces()
{
- try {
+ QFETCH(QString, path);
+ QFETCH(bool, postLoad);
+ try {
setExpectedScriptOutput("checked: false");
m_component->loadUserInterfaces(QDir(":///data"), QStringList() << QLatin1String("form.ui"));
- m_component->loadComponentScript(":///data/userinterface.qs");
+ m_component->evaluateComponentScript(path, postLoad);
} catch (const Error &error) {
QFAIL(qPrintable(error.message()));
}
@@ -591,7 +623,7 @@ private slots:
try {
m_core.setPackageManager();
Component *component = m_core.componentByName("component.test.addOperation");
- component->loadComponentScript(":///data/addOperation.qs");
+ component->evaluateComponentScript(":///data/addOperation.qs");
setExpectedScriptOutput("Component::createOperations()");
component->createOperations();
diff --git a/tools/repogen/repogen.cpp b/tools/repogen/repogen.cpp
index a8720a0de..2abe67e78 100644
--- a/tools/repogen/repogen.cpp
+++ b/tools/repogen/repogen.cpp
@@ -185,7 +185,7 @@ int main(int argc, char** argv)
"Error: Repository parameter missing argument"));
}
- if (!QFileInfo(args.first()).exists()) {
+ if (!QFileInfo::exists(args.first())) {
return printErrorAndUsageAndExit(QCoreApplication::translate("QInstaller",
"Error: Only local filesystem repositories now supported"));
}