summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
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;