Add new ability for filtering incompatible plugins

In commit f9118dd13c **"npp-compatible-versions"** has been added in plugin list for helping not only Plugin Admin, but also Plugin Manager (Plugin Loader) to check the compatibility with the latest version of plugin (if the version of installed plugin is the latest one).
However, if the version of installed plugin is the previous one, there's no info to know if this plugin with old version is compatible with running Notepad++. In order to filter better old version plugins, **"old-versions-compatibility"** is added in plugin list, so Plugin Manager can use it to check the compatibility to decide load it or not.

The value of "old-versions-compatibility" is a string made by 2 interval versions as following:
`"old-versions-compatibility": "[,2.6][,8.2.1]"`

The first interval versions are for old plugin versions: [,2.6] means from all the versions to v2.6 included.
The second interval versions are for Notepad++ versions: [,8.2.1] means from all the versions to v8.2.1 included.
Both interval versions together means: the plugin in question from the 1st version to v2.6 is compatible with Notepad++ v8.2.1 and all Notepad++ previous versions.

Here is the sample:
```json
{
	"folder-name": "mimeTools",
	"display-name": "Mime tools",
	"version": "2.7",
	"npp-compatible-versions": "[8.3,]",
	"old-versions-compatibility": "[,2.6][,8.2.1]",
	"id": "b65fbfaa15b443131eb69188069cacbff04eca66e0cb84130631303a1d3895f8",
	"repository": "https://github.com/npp-plugins/mimetools/releases/download/v2.7/mimetools.v2.7.zip",
	"description": "Implements several main functionalities defined in MIME.",
	"author": "Don HO",
	"homepage": "https://github.com/npp-plugins/mimetools"
},
```
Considering these 2 scenarios:
1. The current distributed plugin version is v2.7 (the latest one normally), and it is compatible with all Notepad++ version from v8.3. If installed MineTools plugin is v2.7 and running Notepad++ is v8.3.3 then it's OK, and MineTools v2.7 will be loaded.

2. If installed MineTools plugin is v2.6 and running Notepad++ is v8.3.3 then Plugin Manager learns it's a previous version (v2.6 < v2.7), so it will check "old-versions-compatibility" - it will find v2.6 is in the 1st interval [,2.6] - it's matched, then Plugin Manager keep checking the running Notepad++'s compatibility: v8.3.3 is not in the 2nd interval [,8.2.1] - it's not compatible, then MineTools plugin v2.6 won't be loaded.

Here are the test instructions for this PR:
1.  download x64 debug binary here:
https://ci.appveyor.com/api/buildjobs/5ba501ecu21k28i7/artifacts/Notepad%2B%2B.x64.Debug.exe
2. Create an empty file "nppPluginList.json" in your `npp\plugins\Config\`
and copy the following content
5e23fce868/src/pl.x64.json
and paste into `npp\plugins\Config\nppPluginList.json`
You have to copy "updater" folder (which contains GUP.exe) to enable plugin list.
3. Download DSpellCheck plugin v1.4.22 which is not compatible with Notepad++ from v8.3 and later version here:
https://github.com/Predelnik/DSpellCheck/releases/download/v1.4.22/DSpellCheck_x64.zip
Install it into plugin folder manually.
4. Now launch Notepad++ x64 debug binary and watch it crash.
5. Edit "nppPluginList.json" by adding `"old-versions-compatibility": "[,1.4.22][,8.2.1]",` into DSpellCheck section.
6. Startup Notepad++. Notepad++ doesn't crash. and now you can check DSpellCheck plugin is not loaded on the startup.

Fix  #11358, fix #11349, close  #11356
This commit is contained in:
Don Ho 2022-03-08 05:19:01 +01:00
parent 53cbe1c227
commit a84cbe8f69
3 changed files with 57 additions and 3 deletions

View File

@ -355,11 +355,20 @@ bool PluginsManager::loadPluginsV2(const TCHAR* dir, const PluginViewList* plugi
// Find plugin version // Find plugin version
Version v; Version v;
v.setVersionFrom(pluginsFullPathFilter); v.setVersionFrom(pluginsFullPathFilter);
if (pui->_version == v) if (v == pui->_version)
{ {
// Find compatible Notepad++ versions // Find compatible Notepad++ versions
isCompatible = nppVer.isCompatibleTo(pui->_nppCompatibleVersions.first, pui->_nppCompatibleVersions.second); isCompatible = nppVer.isCompatibleTo(pui->_nppCompatibleVersions.first, pui->_nppCompatibleVersions.second);
} }
else if (v < pui->_version && // If dll version is older, and _oldVersionCompatibility is valid (not empty), we search in "_oldVersionCompatibility"
!(pui->_oldVersionCompatibility.first.first.empty() && pui->_oldVersionCompatibility.first.second.empty()) && // first version interval is valid
!(pui->_oldVersionCompatibility.first.second.empty() && pui->_oldVersionCompatibility.second.second.empty())) // second version interval is valid
{
if (v.isCompatibleTo(pui->_oldVersionCompatibility.first.first, pui->_oldVersionCompatibility.first.second)) // dll older version found
{
isCompatible = nppVer.isCompatibleTo(pui->_oldVersionCompatibility.second.first, pui->_oldVersionCompatibility.second.second);
}
}
} }
} }
@ -404,11 +413,20 @@ bool PluginsManager::loadPluginsV2(const TCHAR* dir, const PluginViewList* plugi
// Find plugin version // Find plugin version
Version v2; Version v2;
v2.setVersionFrom(pluginsFullPathFilter2); v2.setVersionFrom(pluginsFullPathFilter2);
if (pui2->_version == v2) if (v2 == pui2->_version)
{ {
// Find compatible Notepad++ versions // Find compatible Notepad++ versions
isCompatible2 = nppVer.isCompatibleTo(pui2->_nppCompatibleVersions.first, pui2->_nppCompatibleVersions.second); isCompatible2 = nppVer.isCompatibleTo(pui2->_nppCompatibleVersions.first, pui2->_nppCompatibleVersions.second);
} }
else if (v2 < pui2->_version && // If dll version is older, and _oldVersionCompatibility is valid (not empty), we search in "_oldVersionCompatibility"
!(pui2->_oldVersionCompatibility.first.first.empty() && pui2->_oldVersionCompatibility.first.second.empty()) && // first version interval is valid
!(pui2->_oldVersionCompatibility.first.second.empty() && pui2->_oldVersionCompatibility.second.second.empty())) // second version interval is valid
{
if (v2.isCompatibleTo(pui2->_oldVersionCompatibility.first.first, pui2->_oldVersionCompatibility.first.second)) // dll older version found
{
isCompatible2 = nppVer.isCompatibleTo(pui2->_oldVersionCompatibility.second.first, pui2->_oldVersionCompatibility.second.second);
}
}
} }
} }

View File

@ -558,6 +558,27 @@ std::pair<Version, Version> getIntervalVersions(generic_string intervalVerStr)
return result; return result;
} }
// twoIntervalVerStr format:
// "[4.2,6.6.6][6.4,8.9]" : The 1st interval from version 4.2 to 6.6.6 inclusive, the 2nd interval from version 6.4 to 8.9
// "[8.3,][6.9,6.9]" : The 1st interval any version from 8.3 to the latest version, the 2nd interval present only version 6.9
// "[,8.2.1][4.4,]" : The 1st interval 8.2.1 and any previous version, , the 2nd interval any version from 4.4 to the latest version
std::pair<std::pair<Version, Version>, std::pair<Version, Version>> getTwoIntervalVersions(generic_string twoIntervalVerStr)
{
std::pair<std::pair<Version, Version>, std::pair<Version, Version>> r;
generic_string sep = TEXT("][");
generic_string::size_type pos = twoIntervalVerStr.find(sep, 0);
if (pos == string::npos)
return r;
generic_string intervalStr1 = twoIntervalVerStr.substr(0, pos + 1);
generic_string intervalStr2 = twoIntervalVerStr.substr(pos + 1, twoIntervalVerStr.length() - pos + 1);
r.first = getIntervalVersions(intervalStr1);
r.second = getIntervalVersions(intervalStr2);
return r;
}
bool loadFromJson(std::vector<PluginUpdateInfo*>& pl, const json& j) bool loadFromJson(std::vector<PluginUpdateInfo*>& pl, const json& j)
{ {
if (j.empty()) if (j.empty())
@ -602,13 +623,21 @@ bool loadFromJson(std::vector<PluginUpdateInfo*>& pl, const json& j)
pi->_nppCompatibleVersions = getIntervalVersions(nppCompatibleVersionStr); pi->_nppCompatibleVersions = getIntervalVersions(nppCompatibleVersionStr);
} }
if (i.contains("old-versions-compatibility"))
{
json jOldVerCompatibility = i["old-versions-compatibility"];
string versionsStr = jOldVerCompatibility.get<std::string>();
generic_string oldVerCompatibilityStr(versionsStr.begin(), versionsStr.end());
pi->_oldVersionCompatibility = getTwoIntervalVersions(oldVerCompatibilityStr);
}
valStr = i.at("repository").get<std::string>(); valStr = i.at("repository").get<std::string>();
pi->_repository = wmc.char2wchar(valStr.c_str(), CP_ACP); pi->_repository = wmc.char2wchar(valStr.c_str(), CP_ACP);
valStr = i.at("homepage").get<std::string>(); valStr = i.at("homepage").get<std::string>();
pi->_homepage = wmc.char2wchar(valStr.c_str(), CP_ACP); pi->_homepage = wmc.char2wchar(valStr.c_str(), CP_ACP);
pl.push_back(pi); pl.push_back(pi);
} }
#ifdef DEBUG #ifdef DEBUG

View File

@ -40,6 +40,13 @@ struct PluginUpdateInfo
// <4.2, 6.6.6>: from v4.2 (included) to v6.6.6 (included) // <4.2, 6.6.6>: from v4.2 (included) to v6.6.6 (included)
// <0.0.0.0, 8.2.1> all until v8.2.1 (included) // <0.0.0.0, 8.2.1> all until v8.2.1 (included)
// <8.3, 0.0.0.0> from v8.3 (included) to all // <8.3, 0.0.0.0> from v8.3 (included) to all
// Optional
std::pair<std::pair<Version, Version>, std::pair<Version, Version>> _oldVersionCompatibility; // Used only by Plugin Manager to filter plugins while loading plugins
// The 1st interval versions are for old plugins' versions
// The 2nd interval versions are for Notepad++ versions
// which are compatible with the old plugins' versions given in the 1st interval
generic_string _homepage; generic_string _homepage;
generic_string _sourceUrl; generic_string _sourceUrl;
generic_string _description; generic_string _description;