summaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorKatja Marttila <katja.marttila@qt.io>2020-11-19 07:25:01 +0200
committerKatja Marttila <katja.marttila@qt.io>2020-12-07 07:36:36 +0200
commite82ab45ed71d9b807dc23eae559c759f4584b79d (patch)
tree1ff8a7379a7c0fbd1908783404babd9b83e4d414 /src/libs
parentb43ab89a64c6484a8af4be424ab695b956d7f7bc (diff)
Add option to define operations in component.xml
Operations can from now on be declared also in component.xml. The operations are performed, backuped and rollbacked the same way as they would be when defined from scripting api. Task-number: QTIFW-507 Change-Id: Ia509219b94737136c3de25db0cb0c72076b48380 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Arttu Tarkiainen <arttu.tarkiainen@qt.io>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/ifwtools/repositorygen.cpp4
-rw-r--r--src/libs/installer/component.cpp47
-rw-r--r--src/libs/installer/component.h5
-rw-r--r--src/libs/installer/extractarchiveoperation.cpp16
-rw-r--r--src/libs/kdtools/updatesinfo.cpp30
-rw-r--r--src/libs/kdtools/updatesinfodata_p.h2
6 files changed, 96 insertions, 8 deletions
diff --git a/src/libs/ifwtools/repositorygen.cpp b/src/libs/ifwtools/repositorygen.cpp
index 819ab1ac8..5b7ec44a9 100644
--- a/src/libs/ifwtools/repositorygen.cpp
+++ b/src/libs/ifwtools/repositorygen.cpp
@@ -190,7 +190,7 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
// list of current unused or later transformed tags
QStringList blackList;
blackList << QLatin1String("UserInterfaces") << QLatin1String("Translations") <<
- QLatin1String("Licenses") << QLatin1String("Name");
+ QLatin1String("Licenses") << QLatin1String("Name") << QLatin1String("Operations");
bool foundDefault = false;
bool foundVirtual = false;
@@ -379,6 +379,8 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
}
update.appendChild(package.firstChildElement(QLatin1String("Licenses")).cloneNode());
}
+ // operations
+ update.appendChild(package.firstChildElement(QLatin1String("Operations")).cloneNode());
} else {
// Extract metadata from archive
if (!info.metaFile.isEmpty()){
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index e8f036ccd..cb028b940 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -237,6 +237,7 @@ static const QLatin1String scUnstable("Unstable");
*/
Component::Component(PackageManagerCore *core)
: d(new ComponentPrivate(core, this))
+ , m_defaultArchivePath(QLatin1String("@TargetDir@"))
{
setPrivate(d);
@@ -342,6 +343,9 @@ void Component::loadDataFromPackage(const Package &package)
QHash<QString, QVariant> licenseHash = package.data(QLatin1String("Licenses")).toHash();
if (!licenseHash.isEmpty())
loadLicenses(QString::fromLatin1("%1/%2/").arg(localTempPath(), name()), licenseHash);
+ QVariant operationsVariant = package.data(QLatin1String("Operations"));
+ if (operationsVariant.canConvert<QList<QPair<QString, QVariant>>>())
+ m_operationsList = operationsVariant.value<QList<QPair<QString, QVariant>>>();
}
/*!
@@ -688,6 +692,39 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
}
}
+/*!
+ Loads all operations defined in the component.xml except Extract operation.
+ Operations are added to the list of operations needed to install this component.
+*/
+void Component::loadXMLOperations()
+{
+ for (auto operation: m_operationsList) {
+ if (operation.first != QLatin1String("Extract"))
+ addOperation(operation.first, operation.second.toStringList());
+ }
+}
+
+/*!
+ Loads all Extract operations defined in the component.xml.
+ Operations are overwriting the default implementation of Extract operation.
+*/
+void Component::loadXMLExtractOperations()
+{
+ for (auto operation: m_operationsList) {
+ if (operation.first == QLatin1String("Extract")) {
+ // Create hash for Extract operations. Operation has a mandatory extract folder as
+ // first argument and optional archive name as second argument.
+ const QStringList &operationArgs = operation.second.toStringList();
+ if (operationArgs.count() == 2) {
+ const QString archiveName = value(scVersion) + operationArgs.at(1);
+ const QString archivePath = QString::fromLatin1("installer://%1/%2").arg(name()).arg(archiveName);
+ m_archivesHash.insert(archivePath, operationArgs.at(0));
+ } else if (operationArgs.count() == 1) {
+ m_defaultArchivePath = operationArgs.at(0);
+ }
+ }
+ }
+}
/*!
\property QInstaller::Component::userInterfaces
@@ -796,8 +833,11 @@ void Component::createOperationsForArchive(const QString &archive)
const bool isZip = Lib7z::isSupportedArchive(archive);
if (isZip) {
- // archives get completely extracted per default (if the script isn't doing other stuff)
- addOperation(QLatin1String("Extract"), QStringList() << archive << QLatin1String("@TargetDir@"));
+ // component.xml can override this value
+ if (m_archivesHash.contains(archive))
+ addOperation(QLatin1String("Extract"), QStringList() << archive << m_archivesHash.value(archive));
+ else
+ addOperation(QLatin1String("Extract"), QStringList() << archive << m_defaultArchivePath);
} else {
createOperationsForPath(archive);
}
@@ -824,10 +864,11 @@ void Component::createOperations()
d->m_operationsCreated = true;
return;
}
-
+ loadXMLExtractOperations();
foreach (const QString &archive, archives())
createOperationsForArchive(archive);
+ loadXMLOperations();
d->m_operationsCreated = true;
}
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index 6ff5c8c38..494d79b13 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -121,6 +121,8 @@ public:
void loadTranslations(const QDir &directory, const QStringList &qms);
void loadUserInterfaces(const QDir &directory, const QStringList &uis);
void loadLicenses(const QString &directory, const QHash<QString, QVariant> &hash);
+ void loadXMLOperations();
+ void loadXMLExtractOperations();
void markAsPerformedInstallation();
QStringList userInterfaces() const;
@@ -227,6 +229,9 @@ private:
private:
QString validatorCallbackName;
ComponentPrivate *d;
+ QList<QPair<QString, QVariant>> m_operationsList;
+ QHash<QString, QString> m_archivesHash;
+ QString m_defaultArchivePath;
};
QDebug operator<<(QDebug dbg, Component *component);
diff --git a/src/libs/installer/extractarchiveoperation.cpp b/src/libs/installer/extractarchiveoperation.cpp
index 99dd88a7e..5b13b1f25 100644
--- a/src/libs/installer/extractarchiveoperation.cpp
+++ b/src/libs/installer/extractarchiveoperation.cpp
@@ -122,9 +122,15 @@ bool ExtractArchiveOperation::performOperation()
QStringList files = callback.extractedFiles();
- const QString resourcesPath = targetDir + QLatin1Char('/') + QLatin1String("installerResources");
- QString fileDirectory = resourcesPath + QLatin1Char('/') +
- archivePath.section(QLatin1Char('/'), 1, 1, QString::SectionSkipEmpty) + QLatin1Char('/');
+ QString installDir = targetDir;
+ // If we have package manager in use (normal installer run) then use
+ // TargetDir for saving filenames, otherwise those would be saved to
+ // extracted folder.
+ if (packageManager())
+ installDir = packageManager()->value(QLatin1String("TargetDir"));
+ const QString resourcesPath = installDir + QLatin1Char('/') + QLatin1String("installerResources");
+ QString fileDirectory = resourcesPath + QLatin1Char('/') + archivePath.section(QLatin1Char('/'), 1, 1,
+ QString::SectionSkipEmpty) + QLatin1Char('/');
QString archiveFileName = archivePath.section(QLatin1Char('/'), 2, 2, QString::SectionSkipEmpty);
QFileInfo fileInfo2(archiveFileName);
QString suffix = fileInfo2.suffix();
@@ -145,7 +151,7 @@ bool ExtractArchiveOperation::performOperation()
setDefaultFilePermissions(file.fileName(), DefaultFilePermissions::NonExecutable);
QDataStream out (&file);
for (int i = 0; i < files.count(); ++i) {
- files[i] = replacePath(files.at(i), targetDir, QLatin1String(scRelocatable));
+ files[i] = replacePath(files.at(i), installDir, QLatin1String(scRelocatable));
}
out << files;
setValue(QLatin1String("files"), file.fileName());
@@ -176,6 +182,8 @@ bool ExtractArchiveOperation::undoOperation()
// If yes, files are listed in .dat instead of in a separate file.
bool useStringListType(value(QLatin1String("files")).type() == QVariant::StringList);
QString targetDir = arguments().at(1);
+ if (packageManager())
+ targetDir = packageManager()->value(QLatin1String("TargetDir"));
QStringList files;
if (useStringListType) {
files = value(QLatin1String("files")).toStringList();
diff --git a/src/libs/kdtools/updatesinfo.cpp b/src/libs/kdtools/updatesinfo.cpp
index 2d7e001ea..3119b6240 100644
--- a/src/libs/kdtools/updatesinfo.cpp
+++ b/src/libs/kdtools/updatesinfo.cpp
@@ -154,6 +154,10 @@ bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE)
} else if (childE.tagName() == QLatin1String("UpdateFile")) {
info.data[QLatin1String("CompressedSize")] = childE.attribute(QLatin1String("CompressedSize"));
info.data[QLatin1String("UncompressedSize")] = childE.attribute(QLatin1String("UncompressedSize"));
+ } else if (childE.tagName() == QLatin1String("Operations")) {
+ const QDomNodeList operationNodes = childE.childNodes();
+ QVariant operationListVariant = parseOperations(childE.childNodes());
+ info.data.insert(QLatin1String("Operations"), operationListVariant);
} else {
info.data[childE.tagName()] = childE.text();
}
@@ -197,6 +201,32 @@ void UpdatesInfoData::processLocalizedTag(const QDomElement &childE, QHash<QStri
info[childE.tagName()] = childE.text();
}
+QVariant UpdatesInfoData::parseOperations(const QDomNodeList &operationNodes)
+{
+ QVariant operationListVariant;
+ QList<QPair<QString, QVariant>> operationsList;
+ for (int i = 0; i < operationNodes.count(); ++i) {
+ const QDomNode operationNode = operationNodes.at(i);
+ if (operationNode.nodeName() == QLatin1String("Operation")) {
+ const QDomNodeList argumentNodes = operationNode.childNodes();
+ QStringList attributes;
+ for (int i = 0; i < argumentNodes.count(); ++i) {
+ const QDomNode argumentNode = argumentNodes.at(i);
+ if (argumentNode.nodeName() == QLatin1String("Argument")) {
+ QDomElement argumentElement = argumentNode.toElement();
+ attributes.append(argumentElement.text());
+ }
+ }
+ QPair<QString, QVariant> pair;
+ pair.first = operationNode.toElement().attributeNode(QLatin1String("name")).value();
+ pair.second = attributes;
+ operationsList.append(pair);
+ }
+ }
+ operationListVariant.setValue(operationsList);
+ return operationListVariant;
+}
+
//
// UpdatesInfo
diff --git a/src/libs/kdtools/updatesinfodata_p.h b/src/libs/kdtools/updatesinfodata_p.h
index 69b004bc3..07da6fcf0 100644
--- a/src/libs/kdtools/updatesinfodata_p.h
+++ b/src/libs/kdtools/updatesinfodata_p.h
@@ -33,6 +33,7 @@
#include <QSharedData>
QT_FORWARD_DECLARE_CLASS(QDomElement)
+QT_FORWARD_DECLARE_CLASS(QDomNodeList)
namespace KDUpdater {
@@ -60,6 +61,7 @@ public:
private:
void processLocalizedTag(const QDomElement &childE, QHash<QString, QVariant> &info) const;
+ QVariant parseOperations(const QDomNodeList &operationNodes);
};
} // namespace KDUpdater