summaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2021-11-23 17:23:26 +0200
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-01-06 11:26:29 +0200
commit403e610e6b867dc840c4e78a344cac52bbe751c2 (patch)
tree746f263da474c1603ce14820d164cd37c97e95bc /src/libs
parent8985801a4e61fad34914ed04480d0240ece53c15 (diff)
Add support for moving child components with <TreeName>
Add new optional "moveChildren" attribute to <TreeName> element. Children of components declaring "moveChildren=true" attribute are calculated a value for an automatic tree name element. Multiple components in a single tree branch can declare a tree name, the order which the relocation happens is from leaf components to root components. Components may be moved under another tree name target. Components may be moved to an existing identifier part that does not have a component, for example in the following repository structure: rootA.childA rootB rootB.childB the "rootB" component can legally declare a "rootA" tree name. The tree names of components become static after installed. If a repository declares a new tree name for a component that is installed, it is only applied after updating in maintenance tool. Child components, which have an automatic tree name, are moved if the parent component is updated with a new tree name, however. Task-number: QTIFW-2380 Change-Id: I9c44a114d3c1248b7e2dd4f0b5cda0739af102f3 Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/installer/component.cpp22
-rw-r--r--src/libs/installer/component.h1
-rw-r--r--src/libs/installer/component_p.cpp1
-rw-r--r--src/libs/installer/component_p.h1
-rw-r--r--src/libs/installer/constants.h1
-rw-r--r--src/libs/installer/packagemanagercore.cpp153
-rw-r--r--src/libs/installer/packagemanagercore.h3
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp3
-rw-r--r--src/libs/kdtools/localpackagehub.cpp12
-rw-r--r--src/libs/kdtools/localpackagehub.h4
-rw-r--r--src/libs/kdtools/updatesinfo.cpp4
11 files changed, 159 insertions, 46 deletions
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index 21cb39be1..1f5ad012f 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -287,7 +287,6 @@ void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package)
{
setValue(scName, package.name);
setValue(scDisplayName, package.title);
- setValue(scTreeName, package.treeName);
setValue(scDescription, package.description);
setValue(scVersion, package.version);
setValue(scInheritVersion, package.inheritVersionFrom);
@@ -304,6 +303,9 @@ void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package)
setValue(scCheckable, package.checkable ? scTrue : scFalse);
setValue(scExpandedByDefault, package.expandedByDefault ? scTrue : scFalse);
setValue(scContentSha1, package.contentSha1);
+
+ setValue(scTreeName, package.treeName.first);
+ d->m_treeNameMoveChildren = package.treeName.second;
}
/*!
@@ -318,7 +320,6 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scName, package.data(scName).toString());
setValue(scDisplayName, package.data(scDisplayName).toString());
- setValue(scTreeName, package.data(scTreeName).toString());
setValue(scDescription, package.data(scDescription).toString());
setValue(scDefault, package.data(scDefault).toString());
setValue(scAutoDependOn, package.data(scAutoDependOn).toString());
@@ -349,6 +350,10 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scForcedInstallation, forced);
setValue(scContentSha1, package.data(scContentSha1).toString());
+ const auto treeNamePair = package.data(QLatin1String(scTreeName)).value<QPair<QString, bool>>();
+ setValue(scTreeName, treeNamePair.first);
+ d->m_treeNameMoveChildren = treeNamePair.second;
+
if (d->m_core->isPackageViewer())
return;
@@ -565,7 +570,18 @@ QString Component::displayName() const
*/
QString Component::treeName() const
{
- return d->m_vars.value(scTreeName, name());
+ const QString defaultValue = d->m_vars.value(scAutoTreeName, name());
+ return d->m_vars.value(scTreeName, defaultValue);
+}
+
+/*!
+ Returns \c true if descendants of this component should have automatically
+ created tree names in relation to the parent component's modified location,
+ \c false otherwise.
+*/
+bool Component::treeNameMoveChildren() const
+{
+ return d->m_treeNameMoveChildren;
}
/*!
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index d8588b2ca..6d2784616 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -161,6 +161,7 @@ public:
QString name() const;
QString displayName() const;
QString treeName() const;
+ bool treeNameMoveChildren() const;
quint64 updateUncompressedSize();
QUrl repositoryUrl() const;
diff --git a/src/libs/installer/component_p.cpp b/src/libs/installer/component_p.cpp
index 8533d8e4c..4030d266e 100644
--- a/src/libs/installer/component_p.cpp
+++ b/src/libs/installer/component_p.cpp
@@ -54,6 +54,7 @@ ComponentPrivate::ComponentPrivate(PackageManagerCore *core, Component *qq)
, m_autoCreateOperations(true)
, m_operationsCreatedSuccessfully(true)
, m_updateIsAvailable(false)
+ , m_treeNameMoveChildren(false)
{
}
diff --git a/src/libs/installer/component_p.h b/src/libs/installer/component_p.h
index d673baec1..bdc67898d 100644
--- a/src/libs/installer/component_p.h
+++ b/src/libs/installer/component_p.h
@@ -63,6 +63,7 @@ public:
bool m_autoCreateOperations;
bool m_operationsCreatedSuccessfully;
bool m_updateIsAvailable;
+ bool m_treeNameMoveChildren;
QString m_componentName;
QUrl m_repositoryUrl;
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index 61efe98a8..1b7807e22 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -57,6 +57,7 @@ static const QLatin1String scReleaseDate("ReleaseDate");
static const QLatin1String scDescription("Description");
static const QLatin1String scDisplayName("DisplayName");
static const QLatin1String scTreeName("TreeName");
+static const QLatin1String scAutoTreeName("AutoTreeName");
static const QLatin1String scDependencies("Dependencies");
static const QLatin1String scAutoDependOn("AutoDependOn");
static const QLatin1String scNewComponent("NewComponent");
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 8b670fc41..bb2eca6e6 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -1416,11 +1416,12 @@ bool PackageManagerCore::fetchLocalPackagesTree()
d->clearAllComponentLists();
QHash<QString, QInstaller::Component*> components;
+ QMap<QString, QString> treeNameComponents;
std::function<void(QList<LocalPackage> *, bool)> loadLocalPackages;
loadLocalPackages = [&](QList<LocalPackage> *treeNamePackages, bool firstRun) {
foreach (auto &package, (firstRun ? installedPackages.values() : *treeNamePackages)) {
- if (firstRun && !package.treeName.isEmpty()) {
+ if (firstRun && !package.treeName.first.isEmpty()) {
// Package has a tree name, leave for later
treeNamePackages->append(package);
continue;
@@ -1448,6 +1449,10 @@ bool PackageManagerCore::fetchLocalPackagesTree()
d->m_pendingUnstableComponents.insert(component->name(),
QPair<Component::UnstableError, QString>(Component::InvalidTreeName, errorString));
}
+ const QString treeName = component->value(scTreeName);
+ if (!treeName.isEmpty())
+ treeNameComponents.insert(component->name(), treeName);
+
components.insert(name, component.take());
}
// Second pass with leftover packages
@@ -1463,6 +1468,8 @@ bool PackageManagerCore::fetchLocalPackagesTree()
loadLocalPackages(&treeNamePackagesTmp, true);
}
+ createAutoTreeNames(components, treeNameComponents);
+
if (!d->buildComponentTree(components, false))
return false;
@@ -3692,7 +3699,7 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
// Check if we already added the component to the available components list.
// Component treenames and names must be unique.
const QString packageName = data.package->data(scName).toString();
- const QString packageTreeName = data.package->data(scTreeName).toString();
+ const QString packageTreeName = data.package->data(scTreeName).value<QPair<QString, bool>>().first;
QString name = packageTreeName.isEmpty() ? packageName : packageTreeName;
if (data.components->contains(name)) {
@@ -3837,13 +3844,14 @@ bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const Loc
emit startAllComponentsReset();
d->clearAllComponentLists();
- QHash<QString, QInstaller::Component*> components;
+ QHash<QString, QInstaller::Component*> allComponents;
Data data;
- data.components = &components;
+ data.components = &allComponents;
data.installedPackages = &locals;
- QMap<QString, QString> treeNameComponents;
+ QMap<QString, QString> remoteTreeNameComponents;
+ QMap<QString, QString> allTreeNameComponents;
std::function<bool(PackagesList *, bool)> loadRemotePackages;
loadRemotePackages = [&](PackagesList *treeNamePackages, bool firstRun) -> bool {
@@ -3854,24 +3862,25 @@ bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const Loc
if (!ProductKeyCheck::instance()->isValidPackage(package->data(scName).toString()))
continue;
- if (firstRun && !package->data(scTreeName).toString().isEmpty()) {
+ if (firstRun && !package->data(scTreeName)
+ .value<QPair<QString, bool>>().first.isEmpty()) {
// Package has a tree name, leave for later
treeNamePackages->append(package);
continue;
}
- QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
+ QScopedPointer<QInstaller::Component> remoteComponent(new QInstaller::Component(this));
data.package = package;
- component->loadDataFromPackage(*package);
- if (updateComponentData(data, component.data())) {
+ remoteComponent->loadDataFromPackage(*package);
+ if (updateComponentData(data, remoteComponent.data())) {
// Create a list where is name and treename. Repo can contain a package with
// a different treename of component which is already installed. We don't want
// to move already installed local packages.
- const QString treeName = component->value(scTreeName);
+ const QString treeName = remoteComponent->value(scTreeName);
if (!treeName.isEmpty())
- treeNameComponents.insert(component->name(), treeName);
- QString name = component->treeName();
- components.insert(name, component.take());
+ remoteTreeNameComponents.insert(remoteComponent->name(), treeName);
+ const QString name = remoteComponent->treeName();
+ allComponents.insert(name, remoteComponent.take());
}
}
// Second pass with leftover packages
@@ -3886,36 +3895,41 @@ bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const Loc
if (!loadRemotePackages(&treeNamePackagesTmp, true))
return false;
}
+ allTreeNameComponents = remoteTreeNameComponents;
- foreach (const QString &key, locals.keys()) {
- QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
- component->loadDataFromPackage(locals.value(key));
- QString treeName = component->treeName();
-
- // 1. Component has a treename in local but not in remote
- if (!treeNameComponents.contains(component->name()) && !component->value(scTreeName).isEmpty()) {
- Component *comp = components.take(component->name());
- delete comp;
- components.insert(treeName, component.take());
+ foreach (auto &package, locals) {
+ QScopedPointer<QInstaller::Component> localComponent(new QInstaller::Component(this));
+ localComponent->loadDataFromPackage(package);
+ const QString name = localComponent->treeName();
+
+ // 1. Component has a treename in local but not in remote, add with local treename
+ if (!remoteTreeNameComponents.contains(localComponent->name()) && !localComponent->value(scTreeName).isEmpty()) {
+ delete allComponents.take(localComponent->name());
// 2. Component has different treename in local and remote, add with local treename
- } else if (treeNameComponents.contains(component->name())) {
- QString remoteTreeName = treeNameComponents.value(component->name());
- QString componentTreeName = component->value(scTreeName);
- if (remoteTreeName != componentTreeName) {
- Component *comp = components.take(treeNameComponents.value(component->name()));
- delete comp;
- components.insert(treeName, component.take());
- }
+ } else if (remoteTreeNameComponents.contains(localComponent->name())) {
+ const QString remoteTreeName = remoteTreeNameComponents.value(localComponent->name());
+ const QString localTreeName = localComponent->value(scTreeName);
+ if (remoteTreeName != localTreeName)
+ delete allComponents.take(remoteTreeNameComponents.value(localComponent->name()));
+ else
+ continue;
// 3. Component has same treename in local and remote, don't add the component again.
- } else if (!components.contains(treeName)) {
- components.insert(treeName, component.take());
+ } else if (allComponents.contains(name)) {
+ continue;
}
+ const QString treeName = localComponent->value(scTreeName);
+ if (!treeName.isEmpty())
+ allTreeNameComponents.insert(localComponent->name(), treeName);
+ allComponents.insert(name, localComponent.take());
}
// store all components that got a replacement
- storeReplacedComponents(components, data, &treeNameComponents);
+ storeReplacedComponents(allComponents, data, &allTreeNameComponents);
+
+ // Move children of treename components
+ createAutoTreeNames(allComponents, allTreeNameComponents);
- if (!d->buildComponentTree(components, true))
+ if (!d->buildComponentTree(allComponents, true))
return false;
d->commitPendingUnstableComponents();
@@ -4082,6 +4096,75 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
return true;
}
+/*!
+ \internal
+
+ Creates automatic tree names for \a components that have a parent declaring
+ an explicit tree name. The child components keep the relative location
+ to their parent component.
+
+ The \a treeNameComponents is a map of original component names and new tree names.
+*/
+void PackageManagerCore::createAutoTreeNames(QHash<QString, Component *> &components
+ , const QMap<QString, QString> &treeNameComponents)
+{
+ if (treeNameComponents.isEmpty())
+ return;
+
+ QHash<QString, Component *> componentsTemp = components;
+ for (auto *component : qAsConst(components)) {
+ if (component->treeName() != component->name()) // already handled
+ continue;
+
+ QString newName;
+ // Check treename candidates, keep the name closest to a leaf component
+ for (auto &name : treeNameComponents.keys()) {
+ if (!component->name().startsWith(name))
+ continue;
+
+ const Component *parent = components.value(treeNameComponents.value(name));
+ if (!(parent && parent->treeNameMoveChildren()))
+ continue; // TreeName only applied to parent
+
+ if (newName.split(QLatin1Char('.'), QString::SkipEmptyParts).count()
+ > name.split(QLatin1Char('.'), QString::SkipEmptyParts).count()) {
+ continue;
+ }
+ newName = name;
+ }
+ if (newName.isEmpty()) // Nothing to do
+ continue;
+
+ const QString treeName = component->name()
+ .replace(newName, treeNameComponents.value(newName));
+
+ if (components.contains(treeName) || treeNameComponents.contains(treeName)) {
+ // Can happen if the parent was moved to an existing identifier (which did not
+ // have a component) and contains child that has a conflicting name with a component
+ // in the existing branch.
+ qCritical() << "Cannot register component" << component->name() << "with automatic "
+ "tree name" << treeName << "! Component with identifier" << treeName << "already exists.";
+
+ if (settings().allowUnstableComponents()) {
+ qCDebug(lcInstallerInstallLog)
+ << "Falling back to using the original indetifier:" << component->name();
+
+ const QString errorString = QLatin1String("Tree name conflicts with an existing indentifier");
+ d->m_pendingUnstableComponents.insert(component->name(),
+ QPair<Component::UnstableError, QString>(Component::InvalidTreeName, errorString));
+ } else {
+ componentsTemp.remove(componentsTemp.key(component));
+ }
+ continue;
+ }
+ component->setValue(scAutoTreeName, treeName);
+
+ componentsTemp.remove(componentsTemp.key(component));
+ componentsTemp.insert(treeName, component);
+ }
+ components = componentsTemp;
+}
+
void PackageManagerCore::restoreCheckState()
{
d->restoreCheckState();
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index 9114578fa..cf1916c48 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -414,6 +414,9 @@ private:
bool fetchAllPackages(const PackagesList &remotePackages, const LocalPackagesHash &localPackages);
bool fetchUpdaterPackages(const PackagesList &remotePackages, const LocalPackagesHash &localPackages);
+ void createAutoTreeNames(QHash<QString, Component *> &components,
+ const QMap<QString, QString> &treeNameComponents);
+
void updateDisplayVersions(const QString &displayKey);
QString findDisplayVersion(const QString &componentName, const QHash<QString, QInstaller::Component*> &components,
const QString& versionKey, QHash<QString, bool> &visited);
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 058418f8e..948093ad7 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -2244,7 +2244,8 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
m_localPackageHub->addPackage(component->name(),
component->value(scVersion),
component->value(scDisplayName),
- component->value(scTreeName),
+ QPair<QString, bool>(component->value(scTreeName),
+ component->treeNameMoveChildren()),
component->value(scDescription),
component->dependencies(),
component->autoDependencies(),
diff --git a/src/libs/kdtools/localpackagehub.cpp b/src/libs/kdtools/localpackagehub.cpp
index d709acb54..353d3f4dd 100644
--- a/src/libs/kdtools/localpackagehub.cpp
+++ b/src/libs/kdtools/localpackagehub.cpp
@@ -319,7 +319,7 @@ void LocalPackageHub::refresh()
void LocalPackageHub::addPackage(const QString &name,
const QString &version,
const QString &title,
- const QString &treeName,
+ const QPair<QString, bool> &treeName,
const QString &description,
const QStringList &dependencies,
const QStringList &autoDependencies,
@@ -404,7 +404,8 @@ void LocalPackageHub::writeToDisk()
addTextChildHelper(&package, QLatin1String("Name"), info.name);
addTextChildHelper(&package, QLatin1String("Title"), info.title);
addTextChildHelper(&package, QLatin1String("Description"), info.description);
- addTextChildHelper(&package, scTreeName, info.treeName);
+ addTextChildHelper(&package, scTreeName, info.treeName.first, QLatin1String("moveChildren"),
+ QVariant(info.treeName.second).toString());
if (info.inheritVersionFrom.isEmpty())
addTextChildHelper(&package, QLatin1String("Version"), info.version);
else
@@ -477,9 +478,10 @@ void LocalPackageHub::PackagesInfoData::addPackageFrom(const QDomElement &packag
info.title = childNodeE.text();
else if (childNodeE.tagName() == QLatin1String("Description"))
info.description = childNodeE.text();
- else if (childNodeE.tagName() == scTreeName)
- info.treeName = childNodeE.text();
- else if (childNodeE.tagName() == QLatin1String("Version")) {
+ else if (childNodeE.tagName() == scTreeName) {
+ info.treeName.first = childNodeE.text();
+ info.treeName.second = QVariant(childNodeE.attribute(QLatin1String("moveChildren"))).toBool();
+ } else if (childNodeE.tagName() == QLatin1String("Version")) {
info.version = childNodeE.text();
info.inheritVersionFrom = childNodeE.attribute(QLatin1String("inheritVersionFrom"));
}
diff --git a/src/libs/kdtools/localpackagehub.h b/src/libs/kdtools/localpackagehub.h
index 648d6cf6e..b544ddfb6 100644
--- a/src/libs/kdtools/localpackagehub.h
+++ b/src/libs/kdtools/localpackagehub.h
@@ -43,7 +43,7 @@ struct KDTOOLS_EXPORT LocalPackage
QString name;
QString title;
QString description;
- QString treeName;
+ QPair<QString, bool> treeName;
QString version;
QString inheritVersionFrom;
QStringList dependencies;
@@ -100,7 +100,7 @@ public:
void addPackage(const QString &pkgName,
const QString &version, // mandatory
const QString &title,
- const QString &treeName,
+ const QPair<QString, bool> &treeName,
const QString &description,
const QStringList &dependencies,
const QStringList &autoDependencies,
diff --git a/src/libs/kdtools/updatesinfo.cpp b/src/libs/kdtools/updatesinfo.cpp
index eaa9b039e..545931a55 100644
--- a/src/libs/kdtools/updatesinfo.cpp
+++ b/src/libs/kdtools/updatesinfo.cpp
@@ -140,6 +140,10 @@ bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE)
}
if (!licenseHash.isEmpty())
info.data.insert(QLatin1String("Licenses"), licenseHash);
+ } else if (childE.tagName() == QLatin1String("TreeName")) {
+ const bool moveChildren = QVariant(childE.attribute(QLatin1String("moveChildren"))).toBool();
+ const QPair<QString, bool> treeNamePair(childE.text(), moveChildren);
+ info.data.insert(QLatin1String("TreeName"), QVariant::fromValue(treeNamePair));
} else if (childE.tagName() == QLatin1String("Version")) {
info.data.insert(QLatin1String("inheritVersionFrom"),
childE.attribute(QLatin1String("inheritVersionFrom")));