PluginInstall: Prevent selection of installed plugin

Prevent selection of plugin libraries that are already in any plugin
directory. Check if they can resolve their dependencies as well.
Also generally check if a plugin with the same ID is already installed.

Change-Id: I0cdc0b3e0eba8682f90db7a460974106a6d5e44c
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
Eike Ziller
2024-12-11 11:28:40 +01:00
parent 65d9635ef7
commit 1fcfe14a9d

View File

@@ -12,14 +12,16 @@
#include <solutions/tasking/tasktreerunner.h> #include <solutions/tasking/tasktreerunner.h>
#include <utils/algorithm.h>
#include <utils/appinfo.h>
#include <utils/async.h> #include <utils/async.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/infolabel.h> #include <utils/infolabel.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <utils/qtcprocess.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <utils/unarchiver.h> #include <utils/unarchiver.h>
#include <utils/wizard.h> #include <utils/wizard.h>
@@ -102,8 +104,15 @@ public:
m_info->setText(Tr::tr("File does not exist.")); m_info->setText(Tr::tr("File does not exist."));
return false; return false;
} }
if (hasLibSuffix(path)) if (hasLibSuffix(path)) {
if (Utils::anyOf(PluginManager::pluginPaths(), [path](const FilePath &pluginPath) {
return path.isChildOf(pluginPath);
})) {
m_info->setText(Tr::tr("Plugin is already installed."));
return false;
}
return true; return true;
}
const auto sourceAndCommand = Unarchiver::sourceAndCommand(path); const auto sourceAndCommand = Unarchiver::sourceAndCommand(path);
if (!sourceAndCommand) if (!sourceAndCommand)
@@ -118,6 +127,31 @@ public:
using CheckResult = expected_str<PluginSpec *>; using CheckResult = expected_str<PluginSpec *>;
static Result checkPlugin(PluginSpec *spec)
{
if (Utils::anyOf(PluginManager::plugins(), [spec](PluginSpec *other) {
return other->id() == spec->id();
}))
return Result::Error(
Tr::tr("A plugin with ID \"%1\" is already installed.").arg(spec->id()));
if (!spec->resolveDependencies(PluginManager::plugins())) {
return Result::Error(
Tr::tr("Plugin failed to resolve dependencies:") + " " + spec->errorString());
}
return Result::Ok;
}
static expected_str<std::unique_ptr<PluginSpec>> checkPlugin(
expected_str<std::unique_ptr<PluginSpec>> spec)
{
if (!spec)
return spec;
const Result ok = checkPlugin(spec->get());
if (ok)
return spec;
return Utils::make_unexpected(ok.error());
}
// Async. Result is set if any issue was found. // Async. Result is set if any issue was found.
void checkContents(QPromise<CheckResult> &promise, const FilePath &tempDir) void checkContents(QPromise<CheckResult> &promise, const FilePath &tempDir)
{ {
@@ -132,15 +166,15 @@ void checkContents(QPromise<CheckResult> &promise, const FilePath &tempDir)
return; return;
} }
if (!plugins.front()->resolveDependencies(PluginManager::plugins())) { PluginSpec *plugin = plugins.front();
promise.addResult(Utils::make_unexpected( const Result ok = checkPlugin(plugin);
Tr::tr("Plugin failed to resolve dependencies:") + " " if (!ok) {
+ plugins.front()->errorString())); promise.addResult(Utils::make_unexpected(ok.error()));
qDeleteAll(plugins); delete plugin;
return; return;
} }
promise.addResult(plugins.front()); promise.addResult(plugin);
} }
class CheckArchivePage : public WizardPage class CheckArchivePage : public WizardPage
@@ -180,7 +214,8 @@ public:
emit completeChanged(); emit completeChanged();
if (hasLibSuffix(m_data->sourcePath)) { if (hasLibSuffix(m_data->sourcePath)) {
m_cancelButton->setVisible(false); m_cancelButton->setVisible(false);
expected_str<std::unique_ptr<PluginSpec>> spec = readCppPluginSpec(m_data->sourcePath); expected_str<std::unique_ptr<PluginSpec>> spec = checkPlugin(
readCppPluginSpec(m_data->sourcePath));
if (!spec) { if (!spec) {
m_label->setType(InfoLabel::Error); m_label->setType(InfoLabel::Error);
m_label->setText(spec.error()); m_label->setText(spec.error());
@@ -434,6 +469,7 @@ static std::function<void(FilePath)> postCopyOperation()
static bool copyPluginFile(const FilePath &src, const FilePath &dest) static bool copyPluginFile(const FilePath &src, const FilePath &dest)
{ {
const FilePath destFile = dest.pathAppended(src.fileName()); const FilePath destFile = dest.pathAppended(src.fileName());
QTC_ASSERT(src != destFile, return true);
if (destFile.exists()) { if (destFile.exists()) {
QMessageBox box(QMessageBox::Question, QMessageBox box(QMessageBox::Question,
Tr::tr("Overwrite File"), Tr::tr("Overwrite File"),