summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@theqtcompany.com>2015-07-10 11:54:41 +0200
committerKarsten Heimrich <karsten.heimrich@theqtcompany.com>2015-07-14 11:45:04 +0000
commit7530807cb040224a2ed31e290ed6f2fb7fc75574 (patch)
tree52e06de5db9b907b63cae25abc7ac50205379702 /src/libs/installer
parentb4a2001d65e13f006da03d39e56a0d989117c597 (diff)
Make the installation relocatable (with some limitations).
Replace the install path with a constant that's updated while loading the stored configuration and operation values. Dynamic variables now need to be set after reading the .ini file, cause there we store the values we found during installation. Makes an installation relocatable, though with some limitations: * Uninstaller entry might break on Windows * Start menu sortcuts might break on Windows * Everything else written to the system using full path Task-number: QTIFW-653 Change-Id: Ie3255299460d4ad7f18c88de9044c95db10d17ac Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com> Reviewed-by: Karsten Heimrich <karsten.heimrich@theqtcompany.com>
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/constants.h3
-rw-r--r--src/libs/installer/fileutils.cpp16
-rw-r--r--src/libs/installer/fileutils.h2
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp27
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp82
-rw-r--r--src/libs/installer/packagemanagercoredata.h3
6 files changed, 88 insertions, 45 deletions
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index e7cc3fe98..df31a2cd8 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -89,6 +89,9 @@ static const QLatin1String scWizardDefaultWidth("WizardDefaultWidth");
static const QLatin1String scWizardDefaultHeight("WizardDefaultHeight");
static const QLatin1String scProductUUID("ProductUUID");
static const QLatin1String scAllUsers("AllUsers");
+
+const char scRelocatable[] = "@RELOCATABLE_PATH@";
+
}
#endif // CONSTANTS_H
diff --git a/src/libs/installer/fileutils.cpp b/src/libs/installer/fileutils.cpp
index 7da62a367..8f0472a08 100644
--- a/src/libs/installer/fileutils.cpp
+++ b/src/libs/installer/fileutils.cpp
@@ -585,3 +585,19 @@ bool QInstaller::isInBundle(const QString &path, QString *bundlePath)
#endif
return false;
}
+
+/*!
+ Replaces the path \a before with the path \a after at the beginning of \a path and returns
+ the replaced path. If \a before cannot be found in \a path, the original value is returned.
+*/
+QString QInstaller::replacePath(const QString &path, const QString &before, const QString &after)
+{
+ if (path.isEmpty() || before.isEmpty())
+ return path;
+
+ QString pathToPatch = QDir::cleanPath(path);
+ const QString pathToReplace = QDir::cleanPath(before);
+ if (pathToPatch.startsWith(pathToReplace))
+ return QDir::cleanPath(after) + pathToPatch.mid(pathToReplace.size());
+ return path;
+}
diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h
index ca85bbf89..ca8891c50 100644
--- a/src/libs/installer/fileutils.h
+++ b/src/libs/installer/fileutils.h
@@ -100,6 +100,8 @@ private:
quint64 INSTALLER_EXPORT fileSize(const QFileInfo &info);
bool INSTALLER_EXPORT isInBundle(const QString &path, QString *bundlePath = 0);
+ QString replacePath(const QString &path, const QString &pathBefore, const QString &pathAfter);
+
#ifdef Q_OS_WIN
QString INSTALLER_EXPORT getLongPathName(const QString &name);
QString INSTALLER_EXPORT getShortPathName(const QString &name);
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index ad2e03ead..f240a309f 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -554,6 +554,7 @@ void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params
#endif
}
processFilesForDelayedDeletion();
+ m_data.setDynamicPredefinedVariables();
disconnect(this, &PackageManagerCorePrivate::installationStarted,
ProgressCoordinator::instance(), &ProgressCoordinator::reset);
@@ -733,15 +734,20 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
// write current state (variables) to the maintenance tool ini file
const QString iniPath = targetDir() + QLatin1Char('/') + m_data.settings().maintenanceToolIniFile();
- QVariantHash variables;
+ QVariantHash variables; // Do not change to QVariantMap! Breaks existing .ini files,
+ // cause the variant types do not match while restoring the variables from the file.
QSettingsWrapper cfg(iniPath, QSettingsWrapper::IniFormat);
foreach (const QString &key, m_data.keys()) {
- if (key != scRunProgramDescription && key != scRunProgram && key != scRunProgramArguments)
- variables.insert(key, m_data.value(key));
+ if (key == scRunProgramDescription || key == scRunProgram || key == scRunProgramArguments)
+ continue;
+ QVariant value = m_data.value(key);
+ if (value.canConvert(QVariant::String))
+ value = replacePath(value.toString(), targetDir(), QLatin1String(scRelocatable));
+ variables.insert(key, value);
}
cfg.setValue(QLatin1String("Variables"), variables);
- QVariantList repos;
+ QVariantList repos; // Do not change either!
foreach (const Repository &repo, m_data.settings().defaultRepositories())
repos.append(QVariant().fromValue(repo));
cfg.setValue(QLatin1String("DefaultRepositories"), repos);
@@ -796,12 +802,15 @@ void PackageManagerCorePrivate::readMaintenanceConfigFiles(const QString &target
{
QSettingsWrapper cfg(targetDir + QLatin1Char('/') + m_data.settings().maintenanceToolIniFile(),
QSettingsWrapper::IniFormat);
- const QVariantHash vars = cfg.value(QLatin1String("Variables")).toHash();
- for (QHash<QString, QVariant>::ConstIterator it = vars.constBegin(); it != vars.constEnd(); ++it)
- m_data.setValue(it.key(), it.value().toString());
-
+ const QVariantHash v = cfg.value(QLatin1String("Variables")).toHash(); // Do not change to
+ // QVariantMap! Breaks reading from existing .ini files, cause the variant types do not match.
+ for (QVariantHash::const_iterator it = v.constBegin(); it != v.constEnd(); ++it) {
+ m_data.setValue(it.key(), replacePath(it.value().toString(), QLatin1String(scRelocatable),
+ targetDir));
+ }
QSet<Repository> repos;
- const QVariantList variants = cfg.value(QLatin1String("DefaultRepositories")).toList();
+ const QVariantList variants = cfg.value(QLatin1String("DefaultRepositories"))
+ .toList(); // Do not change either!
foreach (const QVariant &variant, variants)
repos.insert(variant.value<Repository>());
if (!repos.isEmpty())
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index 77103b61e..399f929f9 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -52,27 +52,14 @@ namespace QInstaller
PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &variables)
{
m_variables = variables;
+ setDynamicPredefinedVariables();
// Set some common variables that may used e.g. as placeholder in some of the settings variables or
// in a script or...
- m_variables.insert(QLatin1String("rootDir"), QDir::rootPath());
- m_variables.insert(QLatin1String("homeDir"), QDir::homePath());
- m_variables.insert(QLatin1String("RootDir"), QDir::rootPath());
- m_variables.insert(QLatin1String("HomeDir"), QDir::homePath());
m_variables.insert(scTargetConfigurationFile, QLatin1String("components.xml"));
m_variables.insert(QLatin1String("InstallerDirPath"), QCoreApplication::applicationDirPath());
m_variables.insert(QLatin1String("InstallerFilePath"), QCoreApplication::applicationFilePath());
- QString dir = QLatin1String("/opt");
-#ifdef Q_OS_WIN
- TCHAR buffer[MAX_PATH + 1] = { 0 };
- SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0, buffer);
- dir = QString::fromWCharArray(buffer);
-#elif defined (Q_OS_OSX)
- dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(0);
-#endif
- m_variables.insert(QLatin1String("ApplicationsDir"), dir);
-
#ifdef Q_OS_WIN
m_variables.insert(QLatin1String("os"), QLatin1String("win"));
#elif defined(Q_OS_OSX)
@@ -83,26 +70,6 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
// TODO: add more platforms as needed...
#endif
-#ifdef Q_OS_WIN
- QSettingsWrapper user(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Explorer\\User Shell Folders"), QSettingsWrapper::NativeFormat);
- QSettingsWrapper system(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Explorer\\Shell Folders"), QSettingsWrapper::NativeFormat);
-
- const QString programs = user.value(QLatin1String("Programs"), QString()).toString();
- const QString allPrograms = system.value(QLatin1String("Common Programs"), QString()).toString();
-
- QString desktop;
- if (m_variables.value(scAllUsers) == scTrue) {
- desktop = system.value(QLatin1String("Desktop")).toString();
- } else {
- desktop = user.value(QLatin1String("Desktop")).toString();
- }
- m_variables.insert(QLatin1String("DesktopDir"), replaceWindowsEnvironmentVariables(desktop));
- m_variables.insert(QLatin1String("UserStartMenuProgramsPath"), replaceWindowsEnvironmentVariables(programs));
- m_variables.insert(QLatin1String("AllUsersStartMenuProgramsPath"), replaceWindowsEnvironmentVariables(allPrograms));
-#endif
-
m_settings = Settings::fromFileAndPrefix(QLatin1String(":/metadata/installer-config/config.xml"),
QLatin1String(":/metadata/installer-config/"), Settings::RelaxedParseMode);
@@ -132,12 +99,57 @@ void PackageManagerCoreData::clear()
m_settings = Settings();
}
+/*!
+ Set some common variables that may be used e.g. as placeholder in some of the settings
+ variables or in a script or...
+*/
+void PackageManagerCoreData::setDynamicPredefinedVariables()
+{
+ m_variables.insert(QLatin1String("rootDir"), QDir::rootPath());
+ m_variables.insert(QLatin1String("homeDir"), QDir::homePath());
+ m_variables.insert(QLatin1String("RootDir"), QDir::rootPath());
+ m_variables.insert(QLatin1String("HomeDir"), QDir::homePath());
+
+ QString dir = QLatin1String("/opt");
+#ifdef Q_OS_WIN
+ TCHAR buffer[MAX_PATH + 1] = { 0 };
+ SHGetFolderPath(0, CSIDL_PROGRAM_FILES, 0, 0, buffer);
+ dir = QString::fromWCharArray(buffer);
+#elif defined (Q_OS_OSX)
+ dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(0);
+#endif
+ m_variables.insert(QLatin1String("ApplicationsDir"), dir);
+
+#ifdef Q_OS_WIN
+ QSettingsWrapper user(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Explorer\\User Shell Folders"), QSettingsWrapper::NativeFormat);
+ QSettingsWrapper system(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Explorer\\Shell Folders"), QSettingsWrapper::NativeFormat);
+
+ const QString programs = user.value(QLatin1String("Programs"), QString()).toString();
+ const QString allPrograms = system.value(QLatin1String("Common Programs"), QString())
+ .toString();
+
+ QString desktop;
+ if (m_variables.value(QLatin1String("AllUsers")) == scTrue) {
+ desktop = system.value(QLatin1String("Desktop")).toString();
+ } else {
+ desktop = user.value(QLatin1String("Desktop")).toString();
+ }
+ m_variables.insert(QLatin1String("DesktopDir"), replaceWindowsEnvironmentVariables(desktop));
+ m_variables.insert(QLatin1String("UserStartMenuProgramsPath"),
+ replaceWindowsEnvironmentVariables(programs));
+ m_variables.insert(QLatin1String("AllUsersStartMenuProgramsPath"),
+ replaceWindowsEnvironmentVariables(allPrograms));
+#endif
+}
+
Settings &PackageManagerCoreData::settings() const
{
return m_settings;
}
-QList<QString> PackageManagerCoreData::keys() const
+QStringList PackageManagerCoreData::keys() const
{
return m_variables.keys();
}
diff --git a/src/libs/installer/packagemanagercoredata.h b/src/libs/installer/packagemanagercoredata.h
index b9e94878d..6e29ca79e 100644
--- a/src/libs/installer/packagemanagercoredata.h
+++ b/src/libs/installer/packagemanagercoredata.h
@@ -46,9 +46,10 @@ public:
explicit PackageManagerCoreData(const QHash<QString, QString> &variables);
void clear();
+ void setDynamicPredefinedVariables();
Settings &settings() const;
- QList<QString> keys() const;
+ QStringList keys() const;
bool contains(const QString &key) const;
bool setValue(const QString &key, const QString &normalizedValue);