mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Add many_active() metadata condition
It takes a regex and returns true if there is more than one active plugin matching it, and false otherwise. Closes #522.
This commit is contained in:
@@ -537,6 +537,7 @@ msg:
|
||||
<tr><td>Checksum<td><code>checksum("<var>filepath</var>", <var>checksum</var>)</code><td>Returns true if the calculated CRC-32 checksum of <var>filepath</var> matches <var>checksum</var>, false otherwise. If <var>filepath</var> does not exist, returns false.
|
||||
<tr><td>Version<td><code>version("<var>filepath</var>", "<var>version</var>", <var>comparator</var>)</code><td>Returns true if the boolean expression <code>(actual version of <var>filepath</var>) <var>comparator version</var></code> holds true, false otherwise. If <var>filepath</var> does not exist or does not have a version number, its version is assumed to be <code>0</code>. The comparison is not a straightforward per-character comparison, but instead uses the precedence rules defined by <a href="http://semver.org/">Semantic Versioning</a>, extended to allow leading zeroes, an arbitrary number of release version numbers, case-insensitivity and a wider range of separator characters.
|
||||
<tr><td>Plugin Active Status<td><code>active("<var>filepath</var>")</code><td>Returns true if <var>filepath</var> is a <code>.esp</code> or <code>.esm</code> file that is both installed and active, false otherwise.
|
||||
<tr><td>Many Plugins Active Status<td><code>many_active("<var>regex</var>")</code><td>Returns true if more than one file matching <var>regex</var> is a <code>.esp</code> or <code>.esm</code> file that is both installed and active, false otherwise.
|
||||
</table>
|
||||
|
||||
<p>The different types of variable used in the above functions are described in more detail below.
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
| ("checksum(" > filePath_ > ',' > qi::hex > ')')[phoenix::bind(&ConditionGrammar::CheckSum, this, qi::labels::_val, qi::labels::_1, qi::labels::_2)]
|
||||
| ("version(" > filePath_ > ',' > quotedStr_ > ',' > comparator_ > ')')[phoenix::bind(&ConditionGrammar::CheckVersion, this, qi::labels::_val, qi::labels::_1, qi::labels::_2, qi::labels::_3)]
|
||||
| ("active(" > filePath_ > ')')[phoenix::bind(&ConditionGrammar::CheckActive, this, qi::labels::_val, qi::labels::_1)]
|
||||
| ("many_active(" > quotedStr_ > ')')[phoenix::bind(&ConditionGrammar::CheckManyActive, this, qi::labels::_val, qi::labels::_1)]
|
||||
;
|
||||
|
||||
quotedStr_ %= '"' > +(char_ - '"') > '"';
|
||||
@@ -376,6 +377,36 @@ private:
|
||||
BOOST_LOG_TRIVIAL(trace) << "Active check result: " << result;
|
||||
}
|
||||
|
||||
void CheckManyActive(bool& result, const std::string& regexStr) const {
|
||||
result = false;
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking to see if more than one file matching the regex \"" << regexStr << "\" exist.";
|
||||
|
||||
std::pair<boost::filesystem::path, std::regex> pathRegex = SplitRegex(regexStr);
|
||||
|
||||
if (game_ == nullptr)
|
||||
return;
|
||||
|
||||
// Now we have a valid parent path and a regex filename. Check that
|
||||
// the parent path exists and is a directory.
|
||||
boost::filesystem::path parent_path = game_->DataPath() / pathRegex.first;
|
||||
if (!boost::filesystem::exists(parent_path) || !boost::filesystem::is_directory(parent_path)) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "The path \"" << parent_path << "\" does not exist or is not a directory.";
|
||||
return;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
for (boost::filesystem::directory_iterator itr(parent_path); itr != boost::filesystem::directory_iterator(); ++itr) {
|
||||
const std::string filename = itr->path().filename().string();
|
||||
if (std::regex_match(filename, pathRegex.second) && game_->IsPluginActive(filename)) {
|
||||
++count;
|
||||
BOOST_LOG_TRIVIAL(trace) << "Matching file found: " << itr->path();
|
||||
}
|
||||
}
|
||||
|
||||
result = count > 1;
|
||||
}
|
||||
|
||||
void SyntaxError(Iterator const& /*first*/, Iterator const& last, Iterator const& errorpos, boost::spirit::info const& what) {
|
||||
std::string context(errorpos, last);
|
||||
boost::trim(context);
|
||||
|
||||
@@ -561,6 +561,51 @@ TEST_P(ConditionGrammarTest, anActiveConditionWithAPluginThatIsNotActiveShouldEv
|
||||
EXPECT_FALSE(result_);
|
||||
}
|
||||
|
||||
TEST_P(ConditionGrammarTest, aManyActiveConditionWithARegexMatchingMoreThanOnePluginThatIsActiveShouldEvaluateToTrue) {
|
||||
ASSERT_NO_THROW(game_.Init(false, localPath));
|
||||
|
||||
Grammar grammar(&game_);
|
||||
std::string condition("many_active(\"Blank( - Different Master Dependent)?\\.es(m|p)\")");
|
||||
|
||||
success_ = boost::spirit::qi::phrase_parse(std::cbegin(condition),
|
||||
std::cend(condition),
|
||||
grammar,
|
||||
skipper_,
|
||||
result_);
|
||||
EXPECT_TRUE(success_);
|
||||
EXPECT_TRUE(result_);
|
||||
}
|
||||
|
||||
TEST_P(ConditionGrammarTest, aManyActiveConditionWithARegexMatchingOnlyOnePluginThatIsActiveShouldEvaluateToFalse) {
|
||||
ASSERT_NO_THROW(game_.Init(false, localPath));
|
||||
|
||||
Grammar grammar(&game_);
|
||||
std::string condition("many_active(\"Blank\\.esm\")");
|
||||
|
||||
success_ = boost::spirit::qi::phrase_parse(std::cbegin(condition),
|
||||
std::cend(condition),
|
||||
grammar,
|
||||
skipper_,
|
||||
result_);
|
||||
EXPECT_TRUE(success_);
|
||||
EXPECT_FALSE(result_);
|
||||
}
|
||||
|
||||
TEST_P(ConditionGrammarTest, aManyActiveConditionWithARegexMatchingNoPluginsThatAreActiveShouldEvaluateToFalse) {
|
||||
ASSERT_NO_THROW(game_.Init(false, localPath));
|
||||
|
||||
Grammar grammar(&game_);
|
||||
std::string condition("many_active(\"Blank\\.esp\")");
|
||||
|
||||
success_ = boost::spirit::qi::phrase_parse(std::cbegin(condition),
|
||||
std::cend(condition),
|
||||
grammar,
|
||||
skipper_,
|
||||
result_);
|
||||
EXPECT_TRUE(success_);
|
||||
EXPECT_FALSE(result_);
|
||||
}
|
||||
|
||||
TEST_P(ConditionGrammarTest, aFalseConditionPrecededByANegatorShouldEvaluateToTrue) {
|
||||
Grammar grammar(&game_);
|
||||
std::string condition("not file(\"" + missingEsp + "\")");
|
||||
|
||||
Reference in New Issue
Block a user