forked from qt-creator/qt-creator
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:
@@ -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"),
|
||||||
|
Reference in New Issue
Block a user