forked from qt-creator/qt-creator
VCS: Detect VCS directories even for disabled VCS plugins
Most of the version control support plugins detect that a directory/file is under version control by looking for certain files in the directory structure. This search doesn't really need anything specific from the plugin, except for a list of file names. Allow version control plugins to specify the list of files to look for in their plugin meta data as "VcsDetectionFiles". When it is checked if a directory is under version control, and none is found from the enabled plugins, use the meta data to find out if any installed but disabled plugin feels responsible for that directory. Show a notification if a plugin is found that handles such a detected version control system, with the option to enable the plugin and restart QtC if necessary. Since this adds discoverability of the version control support even when plugins are disabled, disable the VCS plugins that can use this mechanism (except for Git). Change-Id: Ib507572c0065dd889a2f9b780c794f9cd985e265 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
"Name" : "Bazaar",
|
"Name" : "Bazaar",
|
||||||
"Version" : "${IDE_VERSION}",
|
"Version" : "${IDE_VERSION}",
|
||||||
"CompatVersion" : "${IDE_VERSION_COMPAT}",
|
"CompatVersion" : "${IDE_VERSION_COMPAT}",
|
||||||
|
"DisabledByDefault" : true,
|
||||||
"VendorId" : "huguesdelorme",
|
"VendorId" : "huguesdelorme",
|
||||||
"Vendor" : "Hugues Delorme",
|
"Vendor" : "Hugues Delorme",
|
||||||
"Copyright" : "(C) 2016 Hugues Delorme, ${IDE_COPYRIGHT}",
|
"Copyright" : "(C) 2016 Hugues Delorme, ${IDE_COPYRIGHT}",
|
||||||
@@ -23,5 +24,8 @@
|
|||||||
],
|
],
|
||||||
"Url" : "https://www.qt.io",
|
"Url" : "https://www.qt.io",
|
||||||
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-bazaar.html",
|
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-bazaar.html",
|
||||||
|
"VcsDetectionFiles" : [
|
||||||
|
".bzr/branch-format"
|
||||||
|
],
|
||||||
${IDE_PLUGIN_DEPENDENCIES}
|
${IDE_PLUGIN_DEPENDENCIES}
|
||||||
}
|
}
|
||||||
|
@@ -1126,6 +1126,35 @@ void ICore::restart()
|
|||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Asks the user if they want to enable the \a plugins and their dependencies.
|
||||||
|
If the user agrees, the plugins are enabled.
|
||||||
|
If all plugins are soft loadable without restart, they get loaded directly.
|
||||||
|
Otherwise the "Restart Required" dialog is shown.
|
||||||
|
|
||||||
|
Returns whether the user agreed to enabling the plugins.
|
||||||
|
*/
|
||||||
|
bool ICore::enablePlugins(const QSet<ExtensionSystem::PluginSpec *> &plugins)
|
||||||
|
{
|
||||||
|
std::optional<QSet<PluginSpec *>> additionalPlugins
|
||||||
|
= PluginManager::askForEnablingPlugins(dialogParent(), plugins, /*enable=*/true);
|
||||||
|
if (!additionalPlugins) // canceled
|
||||||
|
return false;
|
||||||
|
const QSet<PluginSpec *> affectedPlugins = plugins + *additionalPlugins;
|
||||||
|
bool softloadable = true;
|
||||||
|
for (PluginSpec *spec : affectedPlugins) {
|
||||||
|
spec->setEnabledBySettings(true);
|
||||||
|
softloadable = softloadable && spec->isSoftLoadable();
|
||||||
|
}
|
||||||
|
ExtensionSystem::PluginManager::writeSettings();
|
||||||
|
if (softloadable) {
|
||||||
|
PluginManager::loadPluginsAtRuntime(affectedPlugins);
|
||||||
|
} else {
|
||||||
|
ICore::askForRestart(Tr::tr("Plugin changes will take effect after restart."));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "core_global.h"
|
#include "core_global.h"
|
||||||
#include "icontext.h"
|
#include "icontext.h"
|
||||||
|
|
||||||
|
#include <extensionsystem/pluginspec.h>
|
||||||
#include <utils/appmainwindow.h>
|
#include <utils/appmainwindow.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/qtcsettings.h>
|
#include <utils/qtcsettings.h>
|
||||||
@@ -116,6 +117,8 @@ public:
|
|||||||
|
|
||||||
static void restart();
|
static void restart();
|
||||||
|
|
||||||
|
static bool enablePlugins(const QSet<ExtensionSystem::PluginSpec *> &plugins);
|
||||||
|
|
||||||
enum SaveSettingsReason {
|
enum SaveSettingsReason {
|
||||||
SettingsDialogDone,
|
SettingsDialogDone,
|
||||||
ModeChanged,
|
ModeChanged,
|
||||||
|
@@ -12,12 +12,15 @@
|
|||||||
#include "iversioncontrol.h"
|
#include "iversioncontrol.h"
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
#include <extensionsystem/pluginspec.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/infobar.h>
|
#include <utils/infobar.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QLabel>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
@@ -177,6 +180,74 @@ static FilePath fixedDir(const FilePath &directory)
|
|||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void askForDisabledVcsPlugins(const FilePath &inputDirectory)
|
||||||
|
{
|
||||||
|
using namespace ExtensionSystem;
|
||||||
|
FilePath toplevel;
|
||||||
|
|
||||||
|
PluginSpec *spec = Utils::findOrDefault(
|
||||||
|
PluginManager::plugins(), [&toplevel, inputDirectory](PluginSpec *plugin) {
|
||||||
|
if (plugin->isEffectivelyEnabled())
|
||||||
|
return false;
|
||||||
|
const QJsonObject metaData = plugin->metaData();
|
||||||
|
const QJsonArray filesArray = metaData.value("VcsDetectionFiles").toArray();
|
||||||
|
if (filesArray.isEmpty())
|
||||||
|
return false;
|
||||||
|
QStringList files;
|
||||||
|
for (const QJsonValue &v : filesArray) {
|
||||||
|
const QString str = v.toString();
|
||||||
|
if (!str.isEmpty())
|
||||||
|
files.append(str);
|
||||||
|
}
|
||||||
|
if (files.isEmpty())
|
||||||
|
return false;
|
||||||
|
qCDebug(findRepoLog) << "Checking if plugin" << plugin->displayName() << "can handle"
|
||||||
|
<< inputDirectory.toUserOutput();
|
||||||
|
qCDebug(findRepoLog) << "by checking for" << files;
|
||||||
|
const FilePath dir = VcsManager::findRepositoryForFiles(inputDirectory, files);
|
||||||
|
if (dir.isEmpty())
|
||||||
|
return false;
|
||||||
|
qCDebug(findRepoLog) << "The plugin" << plugin->displayName() << "can handle"
|
||||||
|
<< inputDirectory.toUserOutput();
|
||||||
|
toplevel = dir;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!spec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Id vcsSuggestion = Id("VcsManager.Suggestion.").withSuffix(spec->id());
|
||||||
|
InfoBar *infoBar = ICore::infoBar();
|
||||||
|
if (!infoBar->canInfoBeAdded(vcsSuggestion))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QString pluginDisplayName = spec->displayName();
|
||||||
|
Utils::InfoBarEntry info(
|
||||||
|
vcsSuggestion,
|
||||||
|
Tr::tr("A directory under version control was detected that is supported by the %1 plugin.")
|
||||||
|
.arg(pluginDisplayName),
|
||||||
|
Utils::InfoBarEntry::GlobalSuppression::Enabled);
|
||||||
|
info.addCustomButton(Tr::tr("Enable %1").arg(pluginDisplayName), [vcsSuggestion, spec] {
|
||||||
|
// TODO In case the plugin is actually loaded during runtime (softloadable),
|
||||||
|
// we'd need to restructure findVersionControlForDirectory below to take the new plugin
|
||||||
|
// into account.
|
||||||
|
// At the moment softloadable VCS plugins are not supported though.
|
||||||
|
if (ICore::enablePlugins({spec}))
|
||||||
|
ICore::infoBar()->removeInfo(vcsSuggestion);
|
||||||
|
});
|
||||||
|
|
||||||
|
info.setDetailsWidgetCreator([toplevel, pluginDisplayName]() -> QWidget * {
|
||||||
|
auto label = new QLabel;
|
||||||
|
label->setWordWrap(true);
|
||||||
|
label->setOpenExternalLinks(true);
|
||||||
|
label->setText(Tr::tr("The directory \"%1\" seems to be under version control that can be "
|
||||||
|
"handled by the disabled %2 plugin.")
|
||||||
|
.arg(toplevel.toUserOutput(), pluginDisplayName));
|
||||||
|
label->setContentsMargins(0, 0, 0, 8);
|
||||||
|
return label;
|
||||||
|
});
|
||||||
|
ICore::infoBar()->addInfo(info);
|
||||||
|
};
|
||||||
|
|
||||||
IVersionControl* VcsManager::findVersionControlForDirectory(const FilePath &inputDirectory,
|
IVersionControl* VcsManager::findVersionControlForDirectory(const FilePath &inputDirectory,
|
||||||
FilePath *topLevelDirectory)
|
FilePath *topLevelDirectory)
|
||||||
@@ -221,6 +292,8 @@ IVersionControl* VcsManager::findVersionControlForDirectory(const FilePath &inpu
|
|||||||
// report result;
|
// report result;
|
||||||
if (topLevelDirectory)
|
if (topLevelDirectory)
|
||||||
topLevelDirectory->clear();
|
topLevelDirectory->clear();
|
||||||
|
|
||||||
|
askForDisabledVcsPlugins(directory);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,9 @@
|
|||||||
],
|
],
|
||||||
"Url" : "https://www.qt.io",
|
"Url" : "https://www.qt.io",
|
||||||
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-fossil.html",
|
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-fossil.html",
|
||||||
|
"VcsDetectionFiles" : [
|
||||||
|
".fslckout"
|
||||||
|
],
|
||||||
${IDE_PLUGIN_DEPENDENCIES},
|
${IDE_PLUGIN_DEPENDENCIES},
|
||||||
|
|
||||||
"JsonWizardPaths" : [":/fossil/wizard"]
|
"JsonWizardPaths" : [":/fossil/wizard"]
|
||||||
|
@@ -30,6 +30,10 @@
|
|||||||
"Description" : "Show given commit hash"
|
"Description" : "Show given commit hash"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"VcsDetectionFiles" : [
|
||||||
|
".git",
|
||||||
|
".git/config"
|
||||||
|
],
|
||||||
${IDE_PLUGIN_DEPENDENCIES},
|
${IDE_PLUGIN_DEPENDENCIES},
|
||||||
|
|
||||||
"Mimetypes" : [
|
"Mimetypes" : [
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
"Name" : "Mercurial",
|
"Name" : "Mercurial",
|
||||||
"Version" : "${IDE_VERSION}",
|
"Version" : "${IDE_VERSION}",
|
||||||
"CompatVersion" : "${IDE_VERSION_COMPAT}",
|
"CompatVersion" : "${IDE_VERSION_COMPAT}",
|
||||||
|
"DisabledByDefault" : true,
|
||||||
"VendorId" : "brianmcgillion",
|
"VendorId" : "brianmcgillion",
|
||||||
"Vendor" : "Brian McGillion",
|
"Vendor" : "Brian McGillion",
|
||||||
"Copyright" : "(C) 2016 Brian McGillion, ${IDE_COPYRIGHT}",
|
"Copyright" : "(C) 2016 Brian McGillion, ${IDE_COPYRIGHT}",
|
||||||
@@ -23,5 +24,8 @@
|
|||||||
],
|
],
|
||||||
"Url" : "https://www.qt.io",
|
"Url" : "https://www.qt.io",
|
||||||
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-mercurial.html",
|
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-mercurial.html",
|
||||||
|
"VcsDetectionFiles" : [
|
||||||
|
".hg/requires"
|
||||||
|
],
|
||||||
${IDE_PLUGIN_DEPENDENCIES}
|
${IDE_PLUGIN_DEPENDENCIES}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
"Name" : "Subversion",
|
"Name" : "Subversion",
|
||||||
"Version" : "${IDE_VERSION}",
|
"Version" : "${IDE_VERSION}",
|
||||||
"CompatVersion" : "${IDE_VERSION_COMPAT}",
|
"CompatVersion" : "${IDE_VERSION_COMPAT}",
|
||||||
|
"DisabledByDefault" : true,
|
||||||
"VendorId" : "theqtcompany",
|
"VendorId" : "theqtcompany",
|
||||||
"Vendor" : "The Qt Company Ltd",
|
"Vendor" : "The Qt Company Ltd",
|
||||||
"Copyright" : "${IDE_COPYRIGHT}",
|
"Copyright" : "${IDE_COPYRIGHT}",
|
||||||
@@ -23,6 +24,10 @@
|
|||||||
],
|
],
|
||||||
"Url" : "https://www.qt.io",
|
"Url" : "https://www.qt.io",
|
||||||
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-subversion.html",
|
"DocumentationUrl" : "https://doc.qt.io/qtcreator/creator-vcs-subversion.html",
|
||||||
|
"VcsDetectionFiles" : [
|
||||||
|
".svn/wc.db",
|
||||||
|
"_svn/wc.db"
|
||||||
|
],
|
||||||
${IDE_PLUGIN_DEPENDENCIES},
|
${IDE_PLUGIN_DEPENDENCIES},
|
||||||
|
|
||||||
"Mimetypes" : [
|
"Mimetypes" : [
|
||||||
|
Reference in New Issue
Block a user