diff options
-rw-r--r-- | src/libs/installer/constants.h | 3 | ||||
-rw-r--r-- | src/libs/installer/fileutils.cpp | 16 | ||||
-rw-r--r-- | src/libs/installer/fileutils.h | 2 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.cpp | 27 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercoredata.cpp | 82 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercoredata.h | 3 | ||||
-rw-r--r-- | src/libs/kdtools/kdupdaterupdateoperation.cpp | 43 |
7 files changed, 123 insertions, 53 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> ¶ms #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); diff --git a/src/libs/kdtools/kdupdaterupdateoperation.cpp b/src/libs/kdtools/kdupdaterupdateoperation.cpp index 6ede07ae7..f4505d6da 100644 --- a/src/libs/kdtools/kdupdaterupdateoperation.cpp +++ b/src/libs/kdtools/kdupdaterupdateoperation.cpp @@ -34,6 +34,8 @@ #include "kdupdaterupdateoperation.h" +#include "constants.h" +#include "fileutils.h" #include "packagemanagercore.h" #include <QDataStream> @@ -401,10 +403,13 @@ QDomDocument UpdateOperation::toXml() const QDomDocument doc; QDomElement root = doc.createElement(QLatin1String("operation")); doc.appendChild(root); + QDomElement args = doc.createElement(QLatin1String("arguments")); + const QString target = m_core ? m_core->value(QInstaller::scTargetDir) : QString(); Q_FOREACH (const QString &s, arguments()) { QDomElement arg = doc.createElement(QLatin1String("argument")); - arg.appendChild(doc.createTextNode(s)); + arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target, + QLatin1String(QInstaller::scRelocatable)))); args.appendChild(arg); } root.appendChild(args); @@ -413,22 +418,31 @@ QDomDocument UpdateOperation::toXml() const // append all values set with setValue QDomElement values = doc.createElement(QLatin1String("values")); - for (QVariantMap::const_iterator it = m_values.begin(); it != m_values.end(); ++it) { + for (QVariantMap::const_iterator it = m_values.constBegin(); it != m_values.constEnd(); ++it) { // the installer can't be put into XML, ignore if (it.key() == QLatin1String("installer")) continue; QDomElement value = doc.createElement(QLatin1String("value")); - const QVariant& variant = it.value(); + QVariant variant = it.value(); value.setAttribute(QLatin1String("name"), it.key()); - value.setAttribute(QLatin1String("type"), QLatin1String( QVariant::typeToName( variant.type()))); + value.setAttribute(QLatin1String("type"), QLatin1String(variant.typeName())); if (variant.type() != QVariant::List && variant.type() != QVariant::StringList && variant.canConvert(QVariant::String)) { - // it can convert to string? great! - value.appendChild( doc.createTextNode(variant.toString())); + // it can convert to string? great! + value.appendChild(doc.createTextNode(QInstaller::replacePath(variant.toString(), + target, QLatin1String(QInstaller::scRelocatable)))); } else { // no? then we have to go the hard way... + if (variant.type() == QVariant::StringList) { + QStringList list = variant.toStringList(); + for (int i = 0; i < list.count(); ++i) { + list[i] = QInstaller::replacePath(list.at(i), target, + QLatin1String(QInstaller::scRelocatable)); + } + variant = QVariant::fromValue(list); + } QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); stream << variant; @@ -446,14 +460,19 @@ QDomDocument UpdateOperation::toXml() const */ bool UpdateOperation::fromXml(const QDomDocument &doc) { + QString target = QCoreApplication::applicationDirPath(); + QInstaller::isInBundle(target, &target); // Does not change target on non OSX platforms. + QStringList args; const QDomElement root = doc.documentElement(); const QDomElement argsElem = root.firstChildElement(QLatin1String("arguments")); Q_ASSERT(! argsElem.isNull()); for (QDomNode n = argsElem.firstChild(); ! n.isNull(); n = n.nextSibling()) { const QDomElement e = n.toElement(); - if (!e.isNull() && e.tagName() == QLatin1String("argument")) - args << e.text(); + if (!e.isNull() && e.tagName() == QLatin1String("argument")) { + args << QInstaller::replacePath(e.text(), QLatin1String(QInstaller::scRelocatable), + target); + } } setArguments(args); @@ -473,6 +492,14 @@ bool UpdateOperation::fromXml(const QDomDocument &doc) if (t == QVariant::List || t == QVariant::StringList || !var.convert(t)) { QDataStream stream(QByteArray::fromBase64( value.toLatin1())); stream >> var; + if (t == QVariant::StringList) { + QStringList list = var.toStringList(); + for (int i = 0; i < list.count(); ++i) { + list[i] = QInstaller::replacePath(list.at(i), + QLatin1String(QInstaller::scRelocatable), target); + } + var = QVariant::fromValue(list); + } } m_values[name] = var; |