summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-04-07 16:05:47 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-05-05 08:38:14 +0300
commitdae54c30a9f8c6e15de2f5daf3b0806fbbf63cbd (patch)
treea50f08889978c07c72f79315b7d404d35ae0ffb6 /src
parent61b05e03159195ccafe6173707c249f8d56bbb8d (diff)
macOS: Create alias of maintenance tool to Applications directory
This makes maintenance tool startable from Launchpad and Spotlight search. Add "MaintenanceToolAlias" configuration variable for setting the name of the alias, which may differ from the actual file name in installation directory. Task-number: QTIFW-2535 Task-number: QTIFW-2478 Change-Id: I73ae5bbf5d0196b2512b5517cb02c391b2ab278c Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/libs/installer/fileutils.h3
-rw-r--r--src/libs/installer/fileutils_mac.mm75
-rw-r--r--src/libs/installer/installer.pro2
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp66
-rw-r--r--src/libs/installer/packagemanagercore_p.h4
-rw-r--r--src/libs/installer/settings.cpp12
-rw-r--r--src/libs/installer/settings.h1
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;