Don't add .ghost file extensions in plugin class

Instead assume that paths passed in are correct, and then trim the
.ghost extension if present before setting the plugin name.
This commit is contained in:
Oliver Hamlet
2023-08-23 19:48:20 +01:00
parent 74aeb3c54b
commit 356eb0243f
9 changed files with 45 additions and 42 deletions
+1 -1
View File
@@ -451,7 +451,7 @@ Changed
Fixed
-----
- ``.ghost`` file extensionms are no longer recursively trimmed when checking if
- ``.ghost`` file extensions are no longer recursively trimmed when checking if
a file has a valid plugin file extension during metadata condition evaluation.
Via loot-condition-interpreter.
- When looking for a plugin file matching a path during metadata condition
+2 -1
View File
@@ -43,7 +43,8 @@ public:
/**
* Get the plugin's filename.
* @return The plugin filename.
* @return The plugin filename. If the plugin was ghosted when it was loaded,
* this filename will be without the .ghost suffix.
*/
virtual std::string GetName() const = 0;
+10 -7
View File
@@ -115,7 +115,15 @@ std::vector<std::filesystem::path> GetAdditionalDataPaths(
std::filesystem::path ResolvePluginPath(
const std::filesystem::path& dataPath,
const std::filesystem::path& pluginPath) {
return pluginPath.is_absolute() ? pluginPath : dataPath / pluginPath;
auto absolutePath =
pluginPath.is_absolute() ? pluginPath : dataPath / pluginPath;
// In case the plugin is ghosted.
if (!std::filesystem::exists(absolutePath)) {
absolutePath += loot::GHOST_FILE_EXTENSION;
}
return absolutePath;
}
std::vector<std::filesystem::path> FindArchives(
@@ -252,12 +260,7 @@ void Game::LoadPlugins(const std::vector<std::filesystem::path>& pluginPaths,
[&](const std::filesystem::path& pluginPath) {
try {
const auto resolvedPluginPath =
boost::iequals(pluginPath.extension().u8string(),
GHOST_FILE_EXTENSION)
? ResolvePluginPath(
DataPath(),
std::filesystem::path(pluginPath).replace_extension())
: ResolvePluginPath(DataPath(), pluginPath);
ResolvePluginPath(DataPath(), pluginPath);
const bool loadHeader =
loadHeadersOnly ||
+9
View File
@@ -223,4 +223,13 @@ std::string NormalizeFilename(const std::string& filename) {
return normalizedFilename;
#endif
}
std::string TrimDotGhostExtension(const std::string& filename) {
// If the name passed ends in '.ghost', that should be trimmed.
if (boost::iends_with(filename, GHOST_FILE_EXTENSION)) {
return filename.substr(0, filename.length() - GHOST_FILE_EXTENSION_LENGTH);
}
return filename;
}
}
+2
View File
@@ -53,6 +53,8 @@ int CompareFilenames(const std::string& lhs, const std::string& rhs);
// that the normalized filenames distinguish characters in a similar way to the
// Windows filesystem.
std::string NormalizeFilename(const std::string& filename);
std::string TrimDotGhostExtension(const std::string& filename);
}
#endif
+1 -3
View File
@@ -36,9 +36,7 @@
namespace loot {
PluginMetadata::PluginMetadata(const std::string& n) : name_(n) {
// If the name passed ends in '.ghost', that should be trimmed.
if (boost::iends_with(name_, GHOST_FILE_EXTENSION)) {
name_ = name_.substr(0, name_.length() - GHOST_FILE_EXTENSION_LENGTH);
}
name_ = TrimDotGhostExtension(n);
if (IsRegexPlugin()) {
nameRegex_ = std::regex(name_, std::regex::ECMAScript | std::regex::icase);
+9 -20
View File
@@ -141,7 +141,7 @@ Plugin::Plugin(const GameType gameType,
const GameCache& gameCache,
std::filesystem::path pluginPath,
const bool headerOnly) :
name_(pluginPath.filename().u8string()),
name_(TrimDotGhostExtension(pluginPath.filename().u8string())),
esPlugin(
std::unique_ptr<::Plugin, decltype(&esp_plugin_free)>(nullptr,
esp_plugin_free)),
@@ -150,17 +150,12 @@ Plugin::Plugin(const GameType gameType,
auto logger = getLogger();
try {
// In case the plugin is ghosted.
if (!std::filesystem::exists(pluginPath)) {
pluginPath += GHOST_FILE_EXTENSION;
}
Load(pluginPath, gameType, headerOnly);
auto ret = esp_plugin_is_empty(esPlugin.get(), &isEmpty_);
if (ret != ESP_OK) {
throw FileAccessError(
"Error checking if \"" + name_ +
"Error checking if \"" + pluginPath.u8string() +
"\" is empty. esplugin error code: " + std::to_string(ret));
}
@@ -173,7 +168,7 @@ Plugin::Plugin(const GameType gameType,
&overrideRecordCount_);
if (ret != ESP_OK) {
throw FileAccessError(
"Error counting override records in \"" + name_ +
"Error counting override records in \"" + pluginPath.u8string() +
"\". esplugin error code: " + std::to_string(ret));
}
@@ -184,7 +179,7 @@ Plugin::Plugin(const GameType gameType,
if (logger) {
logger->debug(
"Plugin file \"{}\" loads {} assets from Bethesda archives",
name_,
pluginPath.u8string(),
GetAssetCount());
}
}
@@ -192,10 +187,11 @@ Plugin::Plugin(const GameType gameType,
tags_ = ExtractBashTags(GetDescription());
} catch (const std::exception& e) {
if (logger) {
logger->error(
"Cannot read plugin file \"{}\". Details: {}", name_, e.what());
logger->error("Cannot read plugin file \"{}\". Details: {}",
pluginPath.u8string(),
e.what());
}
throw FileAccessError("Cannot read \"" + name_ +
throw FileAccessError("Cannot read \"" + pluginPath.u8string() +
"\". Details: " + e.what());
}
}
@@ -396,13 +392,6 @@ bool Plugin::IsValid(const GameType gameType,
true,
&isValid);
if (returnCode != ESP_OK || !isValid) {
// Try adding .ghost extension.
auto ghostedFilename = pluginPath.u8string() + GHOST_FILE_EXTENSION;
returnCode = esp_plugin_is_valid(
GetEspluginGameId(gameType), ghostedFilename.c_str(), true, &isValid);
}
if (returnCode == ESP_OK && isValid) {
return true;
}
@@ -411,7 +400,7 @@ bool Plugin::IsValid(const GameType gameType,
auto logger = getLogger();
if (logger) {
logger->debug("The file \"{}\" is not a valid plugin.",
pluginPath.filename().u8string());
pluginPath.u8string());
}
return false;
@@ -87,10 +87,11 @@ TEST_P(GameCacheTest,
gettingPluginsShouldReturnASetOfCachedPluginsIfPluginsHaveBeenCached) {
cache_.AddPlugin(
Plugin(game_.GetType(), GameCache(), game_.DataPath() / blankEsm, true));
cache_.AddPlugin(Plugin(game_.GetType(),
GameCache(),
game_.DataPath() / blankMasterDependentEsm,
true));
cache_.AddPlugin(
Plugin(game_.GetType(),
GameCache(),
game_.DataPath() / (blankMasterDependentEsm + ".ghost"),
true));
EXPECT_FALSE(cache_.GetPlugins().empty());
}
+6 -6
View File
@@ -265,7 +265,7 @@ TEST_P(PluginTest, loadingWholePluginShouldReadHeaderData) {
TEST_P(PluginTest, loadingWholePluginShouldReadFields) {
Plugin plugin(game_.GetType(),
game_.GetCache(),
game_.DataPath() / blankMasterDependentEsm,
game_.DataPath() / (blankMasterDependentEsm + ".ghost"),
false);
if (GetParam() == GameType::tes3) {
@@ -481,7 +481,7 @@ TEST_P(PluginTest,
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true);
Plugin plugin2(game_.GetType(),
game_.GetCache(),
game_.DataPath() / blankMasterDependentEsm,
game_.DataPath() / (blankMasterDependentEsm + ".ghost"),
true);
EXPECT_FALSE(plugin1.DoRecordsOverlap(plugin2));
@@ -505,7 +505,7 @@ TEST_P(PluginTest,
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false);
Plugin plugin2(game_.GetType(),
game_.GetCache(),
game_.DataPath() / blankMasterDependentEsm,
game_.DataPath() / (blankMasterDependentEsm + ".ghost"),
false);
EXPECT_TRUE(plugin1.DoRecordsOverlap(plugin2));
@@ -528,7 +528,7 @@ TEST_P(PluginTest, getOverlapSizeShouldCountEachRecordOnce) {
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false);
Plugin plugin2(game_.GetType(),
game_.GetCache(),
game_.DataPath() / blankMasterDependentEsm,
game_.DataPath() / (blankMasterDependentEsm + ".ghost"),
false);
EXPECT_EQ(4, plugin1.GetOverlapSize({&plugin2, &plugin2}));
@@ -541,7 +541,7 @@ TEST_P(PluginTest, getOverlapSizeShouldCheckAgainstAllGivenPlugins) {
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsp, false);
Plugin plugin3(game_.GetType(),
game_.GetCache(),
game_.DataPath() / blankMasterDependentEsm,
game_.DataPath() / (blankMasterDependentEsm + ".ghost"),
false);
EXPECT_EQ(4, plugin1.GetOverlapSize({&plugin2, &plugin3}));
@@ -553,7 +553,7 @@ TEST_P(PluginTest,
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, true);
Plugin plugin2(game_.GetType(),
game_.GetCache(),
game_.DataPath() / blankMasterDependentEsm,
game_.DataPath() / (blankMasterDependentEsm + ".ghost"),
true);
EXPECT_EQ(0, plugin1.GetOverlapSize({&plugin2}));