summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatja Marttila <katja.marttila@qt.io>2019-10-22 13:33:11 +0300
committerKatja Marttila <katja.marttila@qt.io>2020-02-14 09:52:09 +0000
commitac38ce9ee96bc2b827d89b089a9d2e2ca37608d7 (patch)
tree9f3bc6e9902f7dbbf2a8d1314d00a58b09500136
parent817a2d41c9d506b7bb5fe3ba17e0a62cb8d59421 (diff)
Uninstall selected packages from command line
Components can be uninstalled from CLI with --uninstallPackages package1,package2,... Replicates the same behavior as when removing from visual UI, so forced installation, virtual and components installed as autodependency cannot be uninstalled. Change-Id: Ibcd87b5ceb8e509c84c6944510c23e59b28dedb9 Reviewed-by: Iikka Eklund <iikka.eklund@qt.io>
-rw-r--r--src/libs/installer/constants.h4
-rw-r--r--src/libs/installer/globals.cpp5
-rw-r--r--src/libs/installer/globals.h2
-rw-r--r--src/libs/installer/packagemanagercore.cpp57
-rw-r--r--src/libs/installer/packagemanagercore.h3
-rw-r--r--src/sdk/commandlineparser.cpp3
-rw-r--r--src/sdk/installerbase.cpp9
7 files changed, 80 insertions, 3 deletions
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index f43dc2e54..80f3665e2 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -128,6 +128,7 @@ const char ListPackages[] = "listPackages";
const char InstallPackages[] = "installPackages";
const char InstallDefault[] = "installDefault";
const char TargetDir[] = "targetDir";
+const char UninstallSelectedPackages[] = "uninstallPackages";
const char Platform[] = "platform";
const char SquishPort[] = "squish-port";
@@ -136,7 +137,8 @@ static const QStringList scCommandLineInterfaceOptions = {
QLatin1String(ListPackages),
QLatin1String(UpdatePackages),
QLatin1String(InstallPackages),
- QLatin1String(InstallDefault)
+ QLatin1String(InstallDefault),
+ QLatin1String(UninstallSelectedPackages)
};
} // namespace CommandLineOptions
diff --git a/src/libs/installer/globals.cpp b/src/libs/installer/globals.cpp
index 517bcdecf..4c40492f0 100644
--- a/src/libs/installer/globals.cpp
+++ b/src/libs/installer/globals.cpp
@@ -35,6 +35,7 @@ const char IFW_TRANSLATIONS[] = "ifw.translations";
const char IFW_NETWORK[] = "ifw.network";
const char IFW_SERVER[] = "ifw.server";
const char IFW_GENERAL[] = "ifw.general";
+const char IFW_INSTALLER_UNINSTALLLOG[] = "ifw.installer.uninstalllog";
const char IFW_PACKAGE_DISPLAYNAME[] = "ifw.package.displayname";
const char IFW_PACKAGE_DESCRIPTION[] = "ifw.package.description";
@@ -68,6 +69,7 @@ Q_LOGGING_CATEGORY(lcTranslations, IFW_TRANSLATIONS)
Q_LOGGING_CATEGORY(lcNetwork, IFW_NETWORK)
Q_LOGGING_CATEGORY(lcServer, IFW_SERVER)
Q_LOGGING_CATEGORY(lcGeneral, IFW_GENERAL)
+Q_LOGGING_CATEGORY(lcInstallerUninstallLog, IFW_INSTALLER_UNINSTALLLOG)
Q_LOGGING_CATEGORY(lcPackageDisplayname, IFW_PACKAGE_DISPLAYNAME);
Q_LOGGING_CATEGORY(lcPackageDescription, IFW_PACKAGE_DESCRIPTION)
@@ -123,7 +125,8 @@ QStringList loggingCategories()
<< QLatin1String(IFW_PACKAGE_COMPRESSEDSIZE)
<< QLatin1String(IFW_INSTALLER_INSTALLLOG)
<< QLatin1String(IFW_SERVER)
- << QLatin1String(IFW_GENERAL);
+ << QLatin1String(IFW_GENERAL)
+ << QLatin1String(IFW_INSTALLER_UNINSTALLLOG);
return categories;
}
diff --git a/src/libs/installer/globals.h b/src/libs/installer/globals.h
index cd8ef8197..e8f19130e 100644
--- a/src/libs/installer/globals.h
+++ b/src/libs/installer/globals.h
@@ -64,7 +64,7 @@ INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcPackageLicenses)
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcPackageUncompressedSize)
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcPackageCompressedSize)
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcInstallerInstallLog)
-
+INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcInstallerUninstallLog)
QStringList INSTALLER_EXPORT loggingCategories();
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 2b02add1d..f6b393b9d 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -2032,6 +2032,32 @@ void PackageManagerCore::printPackageInformation(const QString &name, const Pack
qCDebug(QInstaller::lcPackageInstalledVersion).noquote() << "\tInstalled version:" << installedPackages.value(name).version;
}
+bool PackageManagerCore::componentUninstallableFromCommandLine(const QString &componentName)
+{
+ // We will do a recursive check for every child this component has.
+ Component *component = componentByName(componentName);
+ const QList<Component*> childComponents = component->childItems();
+ foreach (const Component *childComponent, childComponents) {
+ if (!componentUninstallableFromCommandLine(childComponent->name()))
+ return false;
+ }
+ ComponentModel *model = defaultComponentModel();
+ const QModelIndex &idx = model->indexFromComponentName(componentName);
+ if (model->data(idx, Qt::CheckStateRole) == QVariant::Invalid) {
+ // Component cannot be unselected, check why
+ if (component->forcedInstallation()) {
+ qCWarning(QInstaller::lcInstallerUninstallLog)
+ << "Cannot uninstall ForcedInstallation component" << component->name();
+ } else if (component->autoDependencies().count() > 0) {
+ qCWarning(QInstaller::lcInstallerUninstallLog) << "Cannot uninstall component"
+ << componentName << "because it is added as auto dependency to"
+ << component->autoDependencies().join(QLatin1Char(','));
+ }
+ return false;
+ }
+ return true;
+}
+
void PackageManagerCore::listInstalledPackages()
{
LocalPackagesHash installedPackages = this->localInstalledPackages();
@@ -2091,6 +2117,37 @@ void PackageManagerCore::updateComponentsSilently(const QStringList &componentsT
}
}
+void PackageManagerCore::uninstallComponentsSilently(const QStringList& components)
+{
+ if (d->runningProcessesFound())
+ return;
+ autoRejectMessageBoxes();
+
+ ComponentModel *model = defaultComponentModel();
+ fetchLocalPackagesTree();
+
+ bool uninstallComponentFound = false;
+
+ foreach (const QString &componentName, components){
+ const QModelIndex &idx = model->indexFromComponentName(componentName);
+ Component *component = componentByName(componentName);
+
+ if (component) {
+ if (componentUninstallableFromCommandLine(componentName)) {
+ model->setData(idx, Qt::Unchecked, Qt::CheckStateRole);
+ uninstallComponentFound = true;
+ }
+ } else {
+ qCWarning(QInstaller::lcInstallerUninstallLog) << "Cannot uninstall " << componentName <<". Component not found in install tree.";
+ }
+ }
+
+ if (uninstallComponentFound) {
+ if (d->calculateComponentsAndRun())
+ qCDebug(QInstaller::lcInstallerUninstallLog) << "Components uninstalled successfully";
+ }
+}
+
/*!
Installs selected components \a components without user interface. Virtual components
cannot be installed unless made visible with --show-virtual-components. AutoDependOn
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index 4451e63c2..5e1c40ca5 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -220,6 +220,7 @@ public:
void updateComponentsSilently(const QStringList &componentsToUpdate);
void installSelectedComponentsSilently(const QStringList& components);
void installDefaultComponentsSilently();
+ void uninstallComponentsSilently(const QStringList& components);
// convenience
Q_INVOKABLE bool isInstaller() const;
@@ -358,6 +359,8 @@ private:
bool fetchPackagesTree(const PackagesList &packages, const LocalPackagesHash installedPackages);
void printPackageInformation(const QString &name, const Package *update);
+ bool componentUninstallableFromCommandLine(const QString &componentName);
+
private:
PackageManagerCorePrivate *const d;
friend class PackageManagerCorePrivate;
diff --git a/src/sdk/commandlineparser.cpp b/src/sdk/commandlineparser.cpp
index ed6ba7695..f59a6e69f 100644
--- a/src/sdk/commandlineparser.cpp
+++ b/src/sdk/commandlineparser.cpp
@@ -129,6 +129,9 @@ CommandLineParser::CommandLineParser()
QLatin1String("package,...")));
m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::InstallDefault),
QLatin1String("Install packages that are checked by default.")));
+ m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::UninstallSelectedPackages),
+ QLatin1String("Uninstall selected packages. Note that all child components will be uninstalled as well"),
+ QLatin1String("package,...")));
m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::Platform),
QLatin1String("Use the specified platform plugin."), QLatin1String("plugin")));
m_parser.addPositionalArgument(QLatin1String(CommandLineOptions::KeyValue),
diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp
index b63c911fa..a14999b45 100644
--- a/src/sdk/installerbase.cpp
+++ b/src/sdk/installerbase.cpp
@@ -377,6 +377,15 @@ int InstallerBase::run()
if (!setTargetDirFromCommandLine(parser))
return EXIT_FAILURE;
m_core->installDefaultComponentsSilently();
+ } else if (parser.isSet(QLatin1String(CommandLineOptions::UninstallSelectedPackages))) {
+ if (m_core->isInstaller())
+ throw QInstaller::Error(QLatin1String("Cannot start installer binary as package manager."));
+ m_core->setPackageManager();
+ QStringList packages;
+ const QString &value = parser.value(QLatin1String(CommandLineOptions::UninstallSelectedPackages));
+ if (!value.isEmpty())
+ packages = value.split(QLatin1Char(','), QString::SkipEmptyParts);
+ m_core->uninstallComponentsSilently(packages);
} else {
m_core->setCommandLineInstance(false);
//create the wizard GUI