diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/installer/fileutils.h | 3 | ||||
-rw-r--r-- | src/libs/installer/fileutils_mac.mm | 75 | ||||
-rw-r--r-- | src/libs/installer/installer.pro | 2 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.cpp | 66 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.h | 4 | ||||
-rw-r--r-- | src/libs/installer/settings.cpp | 12 | ||||
-rw-r--r-- | src/libs/installer/settings.h | 1 |
7 files changed, 159 insertions, 4 deletions
diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h index daaa3485b..8b79ce052 100644 --- a/src/libs/installer/fileutils.h +++ b/src/libs/installer/fileutils.h @@ -89,6 +89,9 @@ private: void INSTALLER_EXPORT mkdir(const QString &path); void INSTALLER_EXPORT mkpath(const QString &path); +#ifdef Q_OS_MACOS + void INSTALLER_EXPORT mkalias(const QString &path, const QString &alias); +#endif quint64 INSTALLER_EXPORT fileSize(const QFileInfo &info); bool INSTALLER_EXPORT isInBundle(const QString &path, QString *bundlePath = 0); diff --git a/src/libs/installer/fileutils_mac.mm b/src/libs/installer/fileutils_mac.mm new file mode 100644 index 000000000..d3792d510 --- /dev/null +++ b/src/libs/installer/fileutils_mac.mm @@ -0,0 +1,75 @@ +/************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "fileutils.h" + +#include "errors.h" + +#include <QCoreApplication> + +#include <objc/objc.h> +#include <Foundation/NSURL.h> +#include <Foundation/NSError.h>> + +namespace QInstaller { + +/*! + \internal + + Creates a bookmark variant of Finder alias from target \a path to \a alias. + Throws \c Error on failure. +*/ +void mkalias(const QString &path, const QString &alias) +{ + NSURL *targetUrl = [NSURL fileURLWithPath:path.toNSString()]; + NSURL *aliasUrl = [NSURL fileURLWithPath:alias.toNSString()]; + + NSError *error = nil; + NSData *data = [targetUrl bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile + includingResourceValuesForKeys:nil relativeToURL:nil error:&error]; + + if (data != nil) { + BOOL success = [NSURL writeBookmarkData:data toURL:aliasUrl + options:NSURLBookmarkCreationSuitableForBookmarkFile error:&error]; + if (success == NO) { + throw Error(QCoreApplication::translate("QInstaller", + "Cannot create alias from \"%1\" to \"%2\": %3.") + .arg(path, alias, QString::fromNSString(error.localizedDescription)) + ); + } + } else { + throw Error(QCoreApplication::translate("QInstaller", + "Could not get bookmark from URL \"%1\": %2.").arg( + QString::fromNSString(targetUrl.absoluteString), + QString::fromNSString(error.localizedDescription) + ) + ); + } +} + +} // namespace QInstaller diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index 60c695fd2..fca960bec 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -222,6 +222,8 @@ SOURCES += packagemanagercore.cpp \ componentselectionpage_p.cpp \ commandlineparser.cpp +macos:SOURCES += fileutils_mac.mm + FORMS += proxycredentialsdialog.ui \ serverauthenticationdialog.ui diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index fc7a8e2c0..c532e2cbd 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -50,6 +50,7 @@ #include "binarycreator.h" #include "loggingutils.h" #include "concurrentoperationrunner.h" +#include "remoteclient.h" #include "selfrestarter.h" #include "filedownloaderfactory.h" @@ -810,6 +811,23 @@ QString PackageManagerCorePrivate::maintenanceToolName() const return QString::fromLatin1("%1/%2").arg(targetDir()).arg(filename); } +QString PackageManagerCorePrivate::maintenanceToolAliasPath() const +{ +#ifdef Q_OS_MACOS + const bool isRoot = (AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive()); + const QString applicationsDir = m_core->value( + isRoot ? QLatin1String("ApplicationsDir") : QLatin1String("ApplicationsDirUser") + ); + QString maintenanceToolAlias = QString::fromLatin1("%1/%2") + .arg(applicationsDir, m_data.settings().maintenanceToolAlias()); + if (!maintenanceToolAlias.endsWith(QLatin1String(".app"))) + maintenanceToolAlias += QLatin1String(".app"); + + return maintenanceToolAlias; +#endif + return QString(); +} + QString PackageManagerCorePrivate::offlineBinaryName() const { QString filename = m_core->value(scOfflineBinaryName, qApp->applicationName() @@ -1521,6 +1539,15 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper input.close(); if (m_core->isInstaller()) registerMaintenanceTool(); +#ifdef Q_OS_MACOS + if (newBinaryWritten) { + // Remove old alias as the name may have changed. + deleteMaintenanceToolAlias(); + // The new alias file is created after the maintenance too binary is renamed, + // but we need to set the value before the variables get written to disk. + m_core->setValue(QLatin1String("CreatedMaintenanceToolAlias"), maintenanceToolAliasPath()); + } +#endif writeMaintenanceConfigFiles(); QFile::remove(dataFile); @@ -1530,11 +1557,12 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper qCDebug(QInstaller::lcInstallerInstallLog) << "Maintenance tool hard restart:" << (restart ? "true." : "false."); - if (newBinaryWritten) + if (newBinaryWritten) { deferredRename(maintenanceToolName() + QLatin1String(".new"), maintenanceToolName(), restart); - else if (restart) + writeMaintenanceToolAlias(); + } else if (restart) { SelfRestarter::setRestartOnQuit(true); - + } } catch (const Error &err) { setStatus(PackageManagerCore::Failure); if (gainedAdminRights) @@ -1603,6 +1631,24 @@ void PackageManagerCorePrivate::writeOfflineBaseBinary() } } +void PackageManagerCorePrivate::writeMaintenanceToolAlias() +{ +#ifdef Q_OS_MACOS + QString maintenanceToolBundle = QString::fromLatin1("%1/%2") + .arg(targetDir(), m_data.settings().maintenanceToolName()); + if (!maintenanceToolBundle.endsWith(QLatin1String(".app"))) + maintenanceToolBundle += QLatin1String(".app"); + + const QString aliasPath = maintenanceToolAliasPath(); + const QDir targetDir(QFileInfo(aliasPath).absolutePath()); + + if (!targetDir.exists()) + targetDir.mkpath(targetDir.absolutePath()); + + mkalias(maintenanceToolBundle, aliasPath); +#endif +} + QString PackageManagerCorePrivate::registerPath() { #ifdef Q_OS_WIN @@ -2023,6 +2069,7 @@ bool PackageManagerCorePrivate::runUninstaller() // No operation delete here, as all old undo operations are deleted in the destructor. deleteMaintenanceTool(); // this will also delete the TargetDir on Windows + deleteMaintenanceToolAlias(); // If not on Windows, we need to remove TargetDir manually. #ifndef Q_OS_WIN @@ -2537,6 +2584,19 @@ void PackageManagerCorePrivate::deleteMaintenanceTool() } } +void PackageManagerCorePrivate::deleteMaintenanceToolAlias() +{ +#ifdef Q_OS_MACOS + const QString maintenanceToolAlias = m_core->value(QLatin1String("CreatedMaintenanceToolAlias")); + QFile aliasFile(maintenanceToolAlias); + if (!maintenanceToolAlias.isEmpty() && !aliasFile.remove()) { + // Not fatal + qWarning(lcInstallerInstallLog) << "Cannot remove alias file" + << maintenanceToolAlias << "for maintenance tool:" << aliasFile.errorString(); + } +#endif +} + void PackageManagerCorePrivate::registerMaintenanceTool() { #ifdef Q_OS_WIN diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index 8e1184c58..0699bce3d 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -89,6 +89,7 @@ public: bool directoryWritable(const QString &path) const; QString maintenanceToolName() const; + QString maintenanceToolAliasPath() const; QString installerBinaryPath() const; QString offlineBinaryName() const; @@ -98,6 +99,8 @@ public: void writeMaintenanceTool(OperationList performedOperations); void writeOfflineBaseBinary(); + void writeMaintenanceToolAlias(); + QString componentsXmlPath() const; QString configurationFileName() const; @@ -240,6 +243,7 @@ private: const double progressOperationSize, const bool adminRightsGained); void deleteMaintenanceTool(); + void deleteMaintenanceToolAlias(); void registerMaintenanceTool(); void unregisterMaintenanceTool(); diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp index a2be73810..b0c6b9d31 100644 --- a/src/libs/installer/settings.cpp +++ b/src/libs/installer/settings.cpp @@ -66,6 +66,7 @@ static const QLatin1String scMaintenanceToolName("MaintenanceToolName"); static const QLatin1String scUserRepositories("UserRepositories"); static const QLatin1String scTmpRepositories("TemporaryRepositories"); static const QLatin1String scMaintenanceToolIniFile("MaintenanceToolIniFile"); +static const QLatin1String scMaintenanceToolAlias("MaintenanceToolAlias"); static const QLatin1String scDependsOnLocalInstallerBinary("DependsOnLocalInstallerBinary"); static const QLatin1String scTranslations("Translations"); static const QLatin1String scCreateLocalRepository("CreateLocalRepository"); @@ -313,7 +314,8 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix, << scTargetDir << scAdminTargetDir << scInstallerApplicationIcon << scInstallerWindowIcon << scLogo << scWatermark << scBanner << scBackground << scPageListPixmap - << scStartMenuDir << scMaintenanceToolName << scMaintenanceToolIniFile << scRemoveTargetDir + << scStartMenuDir << scMaintenanceToolName << scMaintenanceToolIniFile << scMaintenanceToolAlias + << scRemoveTargetDir << scRunProgram << scRunProgramArguments << scRunProgramDescription << scDependsOnLocalInstallerBinary << scAllowSpaceInPath << scAllowNonAsciiCharacters << scDisableAuthorizationFallback @@ -384,6 +386,9 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix, s.d->m_data.value(QLatin1String("UninstallerName"), QLatin1String("maintenancetool")) .toString()); } + if (s.d->m_data.value(scMaintenanceToolAlias).toString().isEmpty()) + s.d->m_data.replace(scMaintenanceToolAlias, s.d->m_data.value(scMaintenanceToolName)); + if (s.d->m_data.value(scTargetConfigurationFile).toString().isEmpty()) s.d->m_data.replace(scTargetConfigurationFile, QLatin1String("components.xml")); if (s.d->m_data.value(scMaintenanceToolIniFile).toString().isEmpty()) { @@ -567,6 +572,11 @@ QString Settings::maintenanceToolIniFile() const return d->m_data.value(scMaintenanceToolIniFile).toString(); } +QString Settings::maintenanceToolAlias() const +{ + return d->m_data.value(scMaintenanceToolAlias).toString(); +} + QString Settings::runProgram() const { return d->m_data.value(scRunProgram).toString(); diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h index 74ed79d44..c34ae2ee9 100644 --- a/src/libs/installer/settings.h +++ b/src/libs/installer/settings.h @@ -110,6 +110,7 @@ public: QString removeTargetDir() const; QString maintenanceToolName() const; QString maintenanceToolIniFile() const; + QString maintenanceToolAlias() const; QString configurationFileName() const; |