summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/examples/package.xml1
-rw-r--r--doc/installerfw.qdoc6
-rw-r--r--src/libs/installer/component.cpp12
-rw-r--r--src/libs/installer/component.h4
-rw-r--r--src/libs/installer/componentmodel.cpp20
-rw-r--r--src/libs/installer/componentselectionpage_p.cpp4
-rw-r--r--src/libs/installer/constants.h1
-rw-r--r--src/libs/installer/packagemanagercore.cpp77
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp4
-rw-r--r--src/libs/kdtools/localpackagehub.cpp7
-rw-r--r--src/libs/kdtools/localpackagehub.h4
-rw-r--r--tests/auto/installer/componentmodel/data/updates.xml10
-rw-r--r--tests/auto/installer/componentmodel/tst_componentmodel.cpp30
-rw-r--r--tests/auto/installer/installer.pro3
-rw-r--r--tests/auto/installer/treename/data/invalid_repository/Updates.xml40
-rw-r--r--tests/auto/installer/treename/data/repository/Updates.xml119
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7zbin0 -> 251 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7zbin0 -> 146 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7zbin0 -> 251 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7zbin0 -> 146 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentC/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentD/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/settings.qrc26
-rw-r--r--tests/auto/installer/treename/treename.pro10
-rw-r--r--tests/auto/installer/treename/tst_treename.cpp136
49 files changed, 472 insertions, 52 deletions
diff --git a/doc/examples/package.xml b/doc/examples/package.xml
index 16b9e07ce..81792416c 100644
--- a/doc/examples/package.xml
+++ b/doc/examples/package.xml
@@ -42,4 +42,5 @@
<Argument>@TargetDir@/Folder2</Argument>
</Operation>
</Operations>
+ <TreeName>com.vendor.subcomponent</TreeName>
</Package>
diff --git a/doc/installerfw.qdoc b/doc/installerfw.qdoc
index fe49d6a9e..0543a800c 100644
--- a/doc/installerfw.qdoc
+++ b/doc/installerfw.qdoc
@@ -938,6 +938,12 @@
For more information, see \l{Adding Operations}. For a
summary of available operations, see \l {Operations}.
+ \row
+ \li TreeName
+ \li Specifies the component location in the install tree view. Overwrites the original
+ location which is calculated from component name. Component names and tree names
+ must be unique. Optional.
+
\endtable
\section2 Component Dependencies
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index 2e797944b..ff01e4251 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -274,6 +274,7 @@ 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);
@@ -301,6 +302,7 @@ 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());
@@ -523,6 +525,16 @@ QString Component::displayName() const
}
/*!
+ Returns this component's location in the tree view. If the tree name is not
+ set, returns the component name. The tree name must be unique, it must not
+ conflict with other tree names or component names.
+*/
+QString Component::treeName() const
+{
+ return d->m_vars.value(scTreeName, name());
+}
+
+/*!
Loads the component script into the script engine.
*/
void Component::loadComponentScript()
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index f7f03391f..d042bfe6a 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -62,6 +62,7 @@ class INSTALLER_EXPORT Component : public QObject, public ComponentModelHelper
Q_PROPERTY(bool installed READ isInstalled)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(bool unstable READ isUnstable)
+ Q_PROPERTY(QString treeName READ treeName)
public:
explicit Component(PackageManagerCore *core);
@@ -157,6 +158,7 @@ public:
QString name() const;
QString displayName() const;
+ QString treeName() const;
quint64 updateUncompressedSize();
QUrl repositoryUrl() const;
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index 45e27ba4a..aab487b45 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -159,7 +159,7 @@ QModelIndex ComponentModel::parent(const QModelIndex &child) const
if (Component *childComponent = componentFromIndex(child)) {
if (Component *parent = childComponent->parentComponent())
- return indexFromComponentName(parent->name());
+ return indexFromComponentName(parent->treeName());
}
return QModelIndex();
}
@@ -513,18 +513,18 @@ void ComponentModel::updateAndEmitModelState()
emit checkStateChanged(m_modelState);
foreach (const Component *component, m_rootComponentList) {
- emit dataChanged(indexFromComponentName(component->name()),
- indexFromComponentName(component->name()));
+ emit dataChanged(indexFromComponentName(component->treeName()),
+ indexFromComponentName(component->treeName()));
QList<Component *> children = component->childItems();
foreach (const Component *child, children)
- emit dataChanged(indexFromComponentName(child->name()),
- indexFromComponentName(child->name()));
+ emit dataChanged(indexFromComponentName(child->treeName()),
+ indexFromComponentName(child->treeName()));
}
}
void ComponentModel::collectComponents(Component *const component, const QModelIndex &parent) const
{
- m_indexByNameCache.insert(component->name(), parent);
+ m_indexByNameCache.insert(component->treeName(), parent);
for (int i = 0; i < component->childCount(); ++i)
collectComponents(component->childAt(i), index(i, 0, parent));
}
@@ -568,8 +568,8 @@ QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compone
// get all parent nodes for the components we're going to update
QMap<QString, Component *> sortedNodesMap;
foreach (Component *component, components) {
- while (component && !sortedNodesMap.values(component->name()).contains(component)) {
- sortedNodesMap.insertMulti(component->name(), component);
+ while (component && !sortedNodesMap.values(component->treeName()).contains(component)) {
+ sortedNodesMap.insertMulti(component->treeName(), component);
component = component->parentComponent();
}
}
@@ -596,7 +596,7 @@ QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compone
continue;
node->setCheckState(newState);
- changed.insert(indexFromComponentName(node->name()));
+ changed.insert(indexFromComponentName(node->treeName()));
m_currentCheckedState[Qt::Checked].remove(node);
m_currentCheckedState[Qt::Unchecked].remove(node);
diff --git a/src/libs/installer/componentselectionpage_p.cpp b/src/libs/installer/componentselectionpage_p.cpp
index 31c4dbedc..a9f4ba134 100644
--- a/src/libs/installer/componentselectionpage_p.cpp
+++ b/src/libs/installer/componentselectionpage_p.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -274,7 +274,7 @@ void ComponentSelectionPagePrivate::updateTreeView()
m_treeView->setExpanded(m_currentModel->index(0, 0), true);
foreach (Component *component, m_core->components(PackageManagerCore::ComponentType::All)) {
if (component->isExpandedByDefault()) {
- const QModelIndex index = m_currentModel->indexFromComponentName(component->name());
+ const QModelIndex index = m_currentModel->indexFromComponentName(component->treeName());
m_treeView->setExpanded(index, true);
}
}
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index feee73fad..42b14ce63 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -55,6 +55,7 @@ static const QLatin1String scTargetDir("TargetDir");
static const QLatin1String scReleaseDate("ReleaseDate");
static const QLatin1String scDescription("Description");
static const QLatin1String scDisplayName("DisplayName");
+static const QLatin1String scTreeName("TreeName");
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 7eaae7b33..41744ff96 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -1372,11 +1372,11 @@ bool PackageManagerCore::fetchLocalPackagesTree()
foreach (const QString &key, keys) {
QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
component->loadDataFromPackage(installedPackages.value(key));
- const QString &name = component->name();
+ const QString &name = component->treeName();
if (components.contains(name)) {
- qCritical("Cannot register component! Component with identifier %s already registered.",
- qPrintable(name));
- continue;
+ d->setStatus(Failure, tr("Cannot register component! Component with identifier %1 "
+ "already exists.").arg(name));
+ return false;
}
components.insert(name, component.take());
}
@@ -2210,7 +2210,7 @@ bool PackageManagerCore::componentUninstallableFromCommandLine(const QString &co
return false;
}
ComponentModel *model = defaultComponentModel();
- const QModelIndex &idx = model->indexFromComponentName(componentName);
+ const QModelIndex &idx = model->indexFromComponentName(component->treeName());
if (model->data(idx, Qt::CheckStateRole) == QVariant::Invalid) {
// Component cannot be unselected, check why
if (component->forcedInstallation()) {
@@ -2246,9 +2246,13 @@ bool PackageManagerCore::checkComponentsForInstallation(const QStringList &compo
ComponentModel *model = defaultComponentModel();
foreach (const QString &name, components) {
- const QModelIndex &idx = model->indexFromComponentName(name);
Component *component = componentByName(name);
- if (component && idx.isValid()) {
+ if (!component) {
+ errorMessage.append(tr("Cannot install %1. Component not found.\n").arg(name));
+ continue;
+ }
+ const QModelIndex &idx = model->indexFromComponentName(component->treeName());
+ if (idx.isValid()) {
if ((model->data(idx, Qt::CheckStateRole) == QVariant::Invalid) && !component->forcedInstallation()) {
// User cannot select the component, check why
if (component->autoDependencies().count() > 0) {
@@ -2265,7 +2269,7 @@ bool PackageManagerCore::checkComponentsForInstallation(const QStringList &compo
installComponentsFound = true;
}
} else { // idx is invalid and component valid when we have invisible virtual component
- component && component->isVirtual()
+ component->isVirtual()
? errorMessage.append(tr("Cannot install %1. Component is virtual.\n").arg(name))
: errorMessage.append(tr("Cannot install %1. Component not found.\n").arg(name));
}
@@ -2330,7 +2334,7 @@ PackageManagerCore::Status PackageManagerCore::updateComponentsSilently(const QS
QList<Component*> componentsToBeUpdated;
//Mark components to be updated
foreach (Component *comp, componentList) {
- const QModelIndex &idx = model->indexFromComponentName(comp->name());
+ const QModelIndex &idx = model->indexFromComponentName(comp->treeName());
if (!userSelectedComponents) { // No components given, update all
model->setData(idx, Qt::Checked, Qt::CheckStateRole);
} else {
@@ -2350,7 +2354,7 @@ PackageManagerCore::Status PackageManagerCore::updateComponentsSilently(const QS
return PackageManagerCore::Success;
}
foreach (Component *componentToUpdate, componentsToBeUpdated) {
- const QModelIndex &idx = model->indexFromComponentName(componentToUpdate->name());
+ const QModelIndex &idx = model->indexFromComponentName(componentToUpdate->treeName());
model->setData(idx, Qt::Checked, Qt::CheckStateRole);
}
}
@@ -2434,11 +2438,11 @@ PackageManagerCore::Status PackageManagerCore::uninstallComponentsSilently(const
bool uninstallComponentFound = false;
foreach (const QString &componentName, components){
- const QModelIndex &idx = model->indexFromComponentName(componentName);
Component *component = componentByName(componentName);
if (component) {
- if (componentUninstallableFromCommandLine(componentName)) {
+ const QModelIndex &idx = model->indexFromComponentName(component->treeName());
+ if (componentUninstallableFromCommandLine(component->name())) {
model->setData(idx, Qt::Unchecked, Qt::CheckStateRole);
uninstallComponentFound = true;
}
@@ -3516,14 +3520,17 @@ QString PackageManagerCore::maintenanceToolName() const
bool PackageManagerCore::updateComponentData(struct Data &data, Component *component)
{
try {
- // check if we already added the component to the available components list
- const QString name = data.package->data(scName).toString();
+ // Check if we already added the component to the available components list.
+ // Component treenames and names must be unique.
+ QString name = data.package->data(scTreeName).toString();
+ if (name.isEmpty())
+ name = data.package->data(scName).toString();
if (data.components->contains(name)) {
- qCritical("Cannot register component! Component with identifier %s already registered.",
- qPrintable(name));
+ d->setStatus(Failure, tr("Cannot register component! Component with identifier %1 "
+ "already exists.").arg(name));
return false;
}
-
+ name = data.package->data(scName).toString();
if (settings().allowUnstableComponents()) {
// Check if there are sha checksum mismatch. Component will still show in install tree
// but is unselectable.
@@ -3643,6 +3650,7 @@ bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const Loc
data.components = &components;
data.installedPackages = &locals;
+ QMap<QString, QString> treeNameComponents;
foreach (Package *const package, remotes) {
if (d->statusCanceledOrFailed())
return false;
@@ -3654,17 +3662,42 @@ bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const Loc
data.package = package;
component->loadDataFromPackage(*package);
if (updateComponentData(data, component.data())) {
- const QString name = component->name();
+ // 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);
+ if (!treeName.isEmpty())
+ treeNameComponents.insert(component->name(), treeName);
+ QString name = component->treeName();
components.insert(name, component.take());
+ } else {
+ return false;
}
}
foreach (const QString &key, locals.keys()) {
QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
component->loadDataFromPackage(locals.value(key));
- const QString &name = component->name();
- if (!components.contains(name))
- components.insert(name, component.take());
+ 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());
+ // 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());
+ }
+ // 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());
+ }
}
// store all components that got a replacement
@@ -3750,6 +3783,8 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
// this is not a dependency, it is a real update
components.insert(name, d->m_updaterComponentsDeps.takeLast());
+ } else {
+ return false;
}
}
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 94e08018a..924de0de3 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -2233,6 +2233,7 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
m_localPackageHub->addPackage(component->name(),
component->value(scVersion),
component->value(scDisplayName),
+ component->value(scTreeName),
component->value(scDescription),
component->dependencies(),
component->autoDependencies(),
@@ -2273,7 +2274,8 @@ bool PackageManagerCorePrivate::runningProcessesFound()
void PackageManagerCorePrivate::setComponentSelection(const QString &id, Qt::CheckState state)
{
ComponentModel *model = m_core->isUpdater() ? m_core->updaterComponentModel() : m_core->defaultComponentModel();
- const QModelIndex &idx = model->indexFromComponentName(id);
+ Component *component = m_core->componentByName(id);
+ const QModelIndex &idx = model->indexFromComponentName(component->treeName());
if (idx.isValid())
model->setData(idx, state, Qt::CheckStateRole);
}
diff --git a/src/libs/kdtools/localpackagehub.cpp b/src/libs/kdtools/localpackagehub.cpp
index d6208a610..9d35a9d1d 100644
--- a/src/libs/kdtools/localpackagehub.cpp
+++ b/src/libs/kdtools/localpackagehub.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -317,6 +317,7 @@ void LocalPackageHub::refresh()
void LocalPackageHub::addPackage(const QString &name,
const QString &version,
const QString &title,
+ const QString &treeName,
const QString &description,
const QStringList &dependencies,
const QStringList &autoDependencies,
@@ -339,6 +340,7 @@ void LocalPackageHub::addPackage(const QString &name,
info.inheritVersionFrom = inheritVersionFrom;
info.installDate = QDate::currentDate();
info.title = title;
+ info.treeName = treeName;
info.description = description;
info.dependencies = dependencies;
info.autoDependencies = autoDependencies;
@@ -398,6 +400,7 @@ 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);
if (info.inheritVersionFrom.isEmpty())
addTextChildHelper(&package, QLatin1String("Version"), info.version);
else
@@ -468,6 +471,8 @@ 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")) {
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 7a067e73e..d43c4a6a5 100644
--- a/src/libs/kdtools/localpackagehub.h
+++ b/src/libs/kdtools/localpackagehub.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -43,6 +43,7 @@ struct KDTOOLS_EXPORT LocalPackage
QString name;
QString title;
QString description;
+ QString treeName;
QString version;
QString inheritVersionFrom;
QStringList dependencies;
@@ -98,6 +99,7 @@ public:
void addPackage(const QString &pkgName,
const QString &version, // mandatory
const QString &title,
+ const QString &treeName,
const QString &description,
const QStringList &dependencies,
const QStringList &autoDependencies,
diff --git a/tests/auto/installer/componentmodel/data/updates.xml b/tests/auto/installer/componentmodel/data/updates.xml
index 2341866ee..3a6139446 100644
--- a/tests/auto/installer/componentmodel/data/updates.xml
+++ b/tests/auto/installer/componentmodel/data/updates.xml
@@ -177,4 +177,14 @@
file="license.txt"/>
</Licenses>
</PackageUpdate>
+ <PackageUpdate>
+ <Name>com.vendor.fifth.product.noncheckable.sub2</Name>
+ <DisplayName>A sub component, moved to top level</DisplayName>
+ <Description>Install this example.</Description>
+ <Version>0.1.0-1</Version>
+ <ReleaseDate>2010-09-21</ReleaseDate>
+ <SortingPriority>0</SortingPriority>
+ <UpdateFile UncompressedSize="61" CompressedSize="61"/>
+ <TreeName>moved_with_treename</TreeName>
+ </PackageUpdate>
</Updates>
diff --git a/tests/auto/installer/componentmodel/tst_componentmodel.cpp b/tests/auto/installer/componentmodel/tst_componentmodel.cpp
index 220aa73e3..0672a03ec 100644
--- a/tests/auto/installer/componentmodel/tst_componentmodel.cpp
+++ b/tests/auto/installer/componentmodel/tst_componentmodel.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -37,8 +37,8 @@
using namespace KDUpdater;
using namespace QInstaller;
-#define EXPECTED_COUNT_VIRTUALS_VISIBLE 11
-#define EXPECTED_COUNT_VIRTUALS_INVISIBLE 10
+#define EXPECTED_COUNT_VIRTUALS_VISIBLE 12
+#define EXPECTED_COUNT_VIRTUALS_INVISIBLE 11
static const char vendorProduct[] = "com.vendor.product";
static const char vendorSecondProduct[] = "com.vendor.second.product";
@@ -51,6 +51,7 @@ static const char vendorThirdProductVirtual[] = "com.vendor.third.product.virtua
static const char vendorFourthProductCheckable[] = "com.vendor.fourth.product.checkable";
static const char vendorFifthProductNonCheckable[] = "com.vendor.fifth.product.noncheckable";
static const char vendorFifthProductSub[] = "com.vendor.fifth.product.noncheckable.sub";
+static const char vendorFifthProductSubWithTreeName[] = "moved_with_treename";
static const QMap<QString, QString> rootComponentDisplayNames = {
{"", QLatin1String("The root component")},
@@ -78,7 +79,7 @@ private slots:
m_defaultPartially << vendorSecondProduct;
m_defaultUnchecked << vendorSecondProductSub1 << vendorSecondProductSubnode
<< vendorSecondProductSubnodeSub << vendorFourthProductCheckable
- << vendorFifthProductSub;
+ << vendorFifthProductSub << vendorFifthProductSubWithTreeName;
m_uncheckable << vendorFifthProductNonCheckable;
}
@@ -99,7 +100,7 @@ private slots:
foreach (const QString &name, all) {
QVERIFY(model.indexFromComponentName(name).isValid());
QVERIFY(model.componentFromIndex(model.indexFromComponentName(name)) != 0);
- QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->name(), name);
+ QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->treeName(), name);
}
foreach (Component *const component, rootComponents)
@@ -124,7 +125,7 @@ private slots:
foreach (const QString &name, all) {
QVERIFY(model.indexFromComponentName(name).isValid());
QVERIFY(model.componentFromIndex(model.indexFromComponentName(name)) != 0);
- QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->name(), name);
+ QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->treeName(), name);
}
foreach (Component *const component, rootComponents)
@@ -415,8 +416,8 @@ private:
void testComponentsLoaded(const QList<Component *> &rootComponents) const
{
- // we need to have five root components
- QCOMPARE(rootComponents.count(), 5);
+ // we need to have six root components
+ QCOMPARE(rootComponents.count(), 6);
QList<Component*> components = rootComponents;
foreach (Component *const component, rootComponents)
@@ -431,9 +432,9 @@ private:
{
// row count with invalid model index should return:
if (m_core.virtualComponentsVisible())
- QCOMPARE(model->rowCount(), 5); // 5 (4 non virtual and 1 virtual root component)
+ QCOMPARE(model->rowCount(), 6); // 6 (5 non virtual and 1 virtual root component)
else
- QCOMPARE(model->rowCount(), 4); // 4 (the 4 non virtual root components)
+ QCOMPARE(model->rowCount(), 5); // 5 (the 5 non virtual root components)
QCOMPARE(model->columnCount(), columnCount);
const QModelIndex firstParent = model->indexFromComponentName(vendorProduct);
@@ -497,15 +498,15 @@ private:
// these components should have checked state
foreach (Component *const component, model->checked())
- QVERIFY(checked.contains(component->name()));
+ QVERIFY(checked.contains(component->treeName()));
// these components should not have partially checked state
foreach (Component *const component, model->partially())
- QVERIFY(partially.contains(component->name()));
+ QVERIFY(partially.contains(component->treeName()));
// these components should not have checked state
foreach (Component *const component, model->unchecked())
- QVERIFY(unchecked.contains(component->name()));
+ QVERIFY(unchecked.contains(component->treeName()));
}
QList<Component*> loadComponents() const
@@ -520,6 +521,7 @@ private:
// we need at least these to be able to test the model
component->setValue("Name", info.data.value("Name").toString());
+ component->setValue("TreeName", info.data.value("TreeName").toString());
QString isDefault = info.data.value("Default").toString();
if (m_core.noDefaultInstallation())
isDefault = scFalse;
@@ -537,7 +539,7 @@ private:
component->setCheckable(false);
component->setCheckState(Qt::Checked);
}
- components.insert(component->name(), component);
+ components.insert(component->treeName(), component);
}
QList <Component*> rootComponents;
diff --git a/tests/auto/installer/installer.pro b/tests/auto/installer/installer.pro
index 4421643b8..2f65d607e 100644
--- a/tests/auto/installer/installer.pro
+++ b/tests/auto/installer/installer.pro
@@ -37,7 +37,8 @@ SUBDIRS += \
environmentvariableoperation \
licenseagreement \
globalsettingsoperation \
- elevatedexecuteoperation
+ elevatedexecuteoperation \
+ treename
win32 {
SUBDIRS += registerfiletypeoperation \
diff --git a/tests/auto/installer/treename/data/invalid_repository/Updates.xml b/tests/auto/installer/treename/data/invalid_repository/Updates.xml
new file mode 100644
index 000000000..a9542eb0d
--- /dev/null
+++ b/tests/auto/installer/treename/data/invalid_repository/Updates.xml
@@ -0,0 +1,40 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component depends on componentB.sub2.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <Dependencies>componentB.sub2</Dependencies>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>570dec768b1f266c66656f015e772f0e6e41b73d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentA.sub1</Name>
+ <DisplayName>Component A subcomponent 1</DisplayName>
+ <Description>component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>da5819910a7f7c95eb61a49543e273fd6e2e9aae</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>Component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>72eee5304ff866e024b477d7b2432df8f2428483</SHA1>
+ <TreeName>componentA.sub1</TreeName>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/treename/data/repository/Updates.xml b/tests/auto/installer/treename/data/repository/Updates.xml
new file mode 100644
index 000000000..1ab3caa23
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/Updates.xml
@@ -0,0 +1,119 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component depends on componentB.sub2.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <Dependencies>componentB.sub2</Dependencies>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>570dec768b1f266c66656f015e772f0e6e41b73d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentA.sub1</Name>
+ <DisplayName>Component A subcomponent 1</DisplayName>
+ <Description>component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>da5819910a7f7c95eb61a49543e273fd6e2e9aae</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentA.sub2</Name>
+ <DisplayName>Component A subcomponent 2</DisplayName>
+ <Description>component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <TreeName>ASub2ToRoot</TreeName>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>73ac2c332ce01fadf0f1c7e16a27faaf0f853e18</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>Component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>72eee5304ff866e024b477d7b2432df8f2428483</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub1</Name>
+ <DisplayName>Component B subcomponent 2 1</DisplayName>
+ <Description>Subcomponent for B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e19f1a26698afe0b72c9048b403253421b8fed4b</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub1.sub1</Name>
+ <DisplayName>Component B sub component for sub1</DisplayName>
+ <Description>Subsubcomponent for B. Moved to root with treename.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <TreeName>BSub1Sub1ToRoot</TreeName>
+ <UpdateFile CompressedSize="291" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6a348979273336862c7a5e16305779e81fee1081</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub1.sub2</Name>
+ <DisplayName>Component B second sub component for sub1</DisplayName>
+ <Description>Subsubcomponent for B. Moved under componentC with treename.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <TreeName>componentC.sub1</TreeName>
+ <UpdateFile CompressedSize="291" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c1bca8944147ec64343c146f461288990268b4a9</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub2</Name>
+ <DisplayName>Component B subcomponent 2</DisplayName>
+ <Description>Subcomponent for B. Moved to root with treename.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>8000</SortingPriority>
+ <TreeName>BSub2ToRoot</TreeName>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>bde9feba3a8134e9c1412b674ee21642938fafec</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C</DisplayName>
+ <Description>Component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>cc33e730d9127e1636566ea35bbe4f186ba4bcb7</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D</DisplayName>
+ <Description>Component D. Autodepends on moved item componentA.sub2 </Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <AutoDependOn>componentA.sub2</AutoDependOn>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3ca69d6bb062c4442fdb20fe0e62bb0f04e8a419</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z
new file mode 100644
index 000000000..f7e22c055
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha1
new file mode 100644
index 000000000..3378d2da5
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+d46bf0f128c64749fb03050045afc816774185e2 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7z
new file mode 100644
index 000000000..81ff563fc
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z
new file mode 100644
index 000000000..d7f4c781c
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha1
new file mode 100644
index 000000000..0eb4045af
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+6561aae70d055e1c4d72b30b12aef7a85cf2139e \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7z
new file mode 100644
index 000000000..38d7c557d
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z
new file mode 100644
index 000000000..e50fc1e92
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha1
new file mode 100644
index 000000000..082bcbf64
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+d8486606a02b9c492e4c17d1e42cfea835a1da51 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7z
new file mode 100644
index 000000000..c062c3cee
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z
new file mode 100644
index 000000000..2c254e3aa
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha1
new file mode 100644
index 000000000..019ab5051
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+3fd04b8e55846f9622ffb8f9ae5f4e6c8b57f90e \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7z
new file mode 100644
index 000000000..31630e810
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z
new file mode 100644
index 000000000..261ea6ab9
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha1
new file mode 100644
index 000000000..c3753ca62
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+2e89c27c3590e12cd900cb55fa2c91428babfd45 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7z
new file mode 100644
index 000000000..c449e57f6
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z
new file mode 100644
index 000000000..d938d0fb2
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha1
new file mode 100644
index 000000000..3db5bca08
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+2407a2adb3d82211921b509e6dd792d67862de0e \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7z
new file mode 100644
index 000000000..6996a4d01
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z
new file mode 100644
index 000000000..7319cf08f
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha1
new file mode 100644
index 000000000..855e2edab
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+a8b85ffe4f91b4dc68a6402b314402949ef17a7a \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7z
new file mode 100644
index 000000000..b91e41207
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z
new file mode 100644
index 000000000..b3a0e683c
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha1
new file mode 100644
index 000000000..377526fb6
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+274b3dbe9cceeca1b577eb2a8302d7690ad93eb3 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7z
new file mode 100644
index 000000000..e9ab3969d
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z
new file mode 100644
index 000000000..7eca1e977
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha1
new file mode 100644
index 000000000..d3b44feee
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+d3015ef5340508ad426c43daa2517c7b62581bab \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7z
new file mode 100644
index 000000000..47ea321ec
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z
new file mode 100644
index 000000000..2299f9812
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha1
new file mode 100644
index 000000000..51dcdd0ed
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+5ce5b91fb7ce209d83ba616ac01bf30e2942f70c \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7z
new file mode 100644
index 000000000..3443e843b
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/settings.qrc b/tests/auto/installer/treename/settings.qrc
new file mode 100644
index 000000000..3837d4440
--- /dev/null
+++ b/tests/auto/installer/treename/settings.qrc
@@ -0,0 +1,26 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/componentA/1.0.0meta.7z</file>
+ <file>data/repository/componentA/1.0.0content.7z</file>
+ <file>data/repository/componentA.sub1/1.0.0meta.7z</file>
+ <file>data/repository/componentA.sub1/1.0.0content.7z</file>
+ <file>data/repository/componentA.sub2/1.0.0meta.7z</file>
+ <file>data/repository/componentA.sub2/1.0.0content.7z</file>
+ <file>data/repository/componentB/1.0.0meta.7z</file>
+ <file>data/repository/componentB/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub1/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub1/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub1.sub1/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub1.sub1/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub1.sub2/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub1.sub2/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub2/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub2/1.0.0content.7z</file>
+ <file>data/repository/componentC/1.0.0meta.7z</file>
+ <file>data/repository/componentC/1.0.0content.7z</file>
+ <file>data/repository/componentD/1.0.0meta.7z</file>
+ <file>data/repository/componentD/1.0.0content.7z</file>
+ <file>data/invalid_repository/Updates.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/treename/treename.pro b/tests/auto/installer/treename/treename.pro
new file mode 100644
index 000000000..f983b39cf
--- /dev/null
+++ b/tests/auto/installer/treename/treename.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_treename.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ..\shared\config.qrc
diff --git a/tests/auto/installer/treename/tst_treename.cpp b/tests/auto/installer/treename/tst_treename.cpp
new file mode 100644
index 000000000..0dc7bfa33
--- /dev/null
+++ b/tests/auto/installer/treename/tst_treename.cpp
@@ -0,0 +1,136 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 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 "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <packagemanagercore.h>
+#include <component.h>
+#include <componentmodel.h>
+
+#include <QTest>
+#include <QRegularExpression>
+
+class tst_TreeName : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void moveToRoot();
+ void moveToSubItem();
+ void dependencyToMovedItem();
+ void autodependOnMovedItem();
+ void moveToExistingItem();
+
+ void init();
+ void cleanup();
+
+private:
+ QString m_installDir;
+
+};
+
+void tst_TreeName::moveToRoot()
+{
+ // componentB.sub1.sub1 moved from sub item to root (BSub1Sub1ToRoot)
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentB.sub1.sub1"));
+ QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ QCOMPARE(installedComponents.count(), 1);
+ QCOMPARE(installedComponents.at(0)->name(), "componentB.sub1.sub1");
+ QCOMPARE(installedComponents.at(0)->treeName(), "BSub1Sub1ToRoot");
+ QVERIFY(core->componentByName("componentB.sub1.sub1") != 0);
+ QVERIFY(core->componentByName("BSub1Sub1ToRoot") == 0);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentB.sub1.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentBSub1Sub1.txt");
+}
+
+void tst_TreeName::moveToSubItem()
+{
+ // componentB.sub1.sub2 moved under componentC (componentC.sub1)
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository");
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentC"));
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentB.sub1.sub2", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentC", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentBSub1Sub2.txt" << "componentC.txt");
+}
+
+void tst_TreeName::dependencyToMovedItem()
+{
+ // componentA depends on componentB.sub2 which is moved to root
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentA"));
+
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentB.sub2", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentA.txt" << "componentASub1.txt" << "componentBSub2.txt");
+}
+
+void tst_TreeName::autodependOnMovedItem()
+{
+ // componentD autodepends on componentA.sub2 which is moved to root
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentA.sub2"));
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA.sub2", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentD", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentASub2.txt" << "componentD.txt");
+}
+
+void tst_TreeName::moveToExistingItem()
+{
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/invalid_repository");
+ QCOMPARE(PackageManagerCore::Failure, core->installSelectedComponentsSilently(QStringList() << "componentA"));
+ QCOMPARE(core->error(), "Cannot register component! Component with identifier componentA.sub1 already exists.");
+}
+
+void tst_TreeName::init()
+{
+ m_installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_installDir));
+}
+
+void tst_TreeName::cleanup()
+{
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+}
+
+QTEST_MAIN(tst_TreeName)
+
+#include "tst_treename.moc"