From 9f617cd0387e8ac3147f7cce6ca03a14fe9010d8 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Mon, 19 Oct 2020 19:51:19 +0200 Subject: [PATCH] Entries for missing files are now retained for custom collections. --- es-app/src/CollectionSystemManager.cpp | 50 +++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/es-app/src/CollectionSystemManager.cpp b/es-app/src/CollectionSystemManager.cpp index 38857a6ca..09c642dda 100644 --- a/es-app/src/CollectionSystemManager.cpp +++ b/es-app/src/CollectionSystemManager.cpp @@ -142,13 +142,36 @@ void CollectionSystemManager::saveCustomCollection(SystemData* sys) if (found) { CollectionSystemData sysData = mCustomCollectionSystemsData.at(name); if (sysData.needsSave) { - std::ofstream configFile; + // Read back any entries from the configuration file for game files that are + // currently missing, and combine them with the active content. If we wouldn't do + // this, they would be purged from the collection. Maybe a directory has been + // temporarily moved or the files are not reachable for whatever reason. It would + // be incredibly annoying to have entries purged from the collection in such + // instances. Using the logic below, the handling of custom collections corresponds + // to the handling of gamelist.xml files, i.e. it's up to the user to make a + // conscious decision of what entries to remove. + std::vector fileGameEntries; + std::vector activeGameEntries; + std::ifstream configFileIn; + std::ofstream configFileOut; + #if defined(_WIN64) - configFile.open(Utils::String:: + configFileIn.open(Utils::String:: stringToWideString(getCustomCollectionConfigPath(name)).c_str()); #else - configFile.open(getCustomCollectionConfigPath(name)); + configFileIn.open(getCustomCollectionConfigPath(name)); #endif + for (std::string gameEntry; getline(configFileIn, gameEntry); ) { + std::string gamePath = Utils::String::replace(gameEntry, "%ROMPATH%", rompath); + gamePath = Utils::String::replace(gamePath, "//", "/"); + // Only add the entry if it's not a regular file or a symlink, in other words + // only add missing files. + if (!Utils::FileSystem::isRegularFile(gamePath) && + !Utils::FileSystem::isSymlink(gamePath)) + fileGameEntries.push_back(gameEntry); + } + configFileIn.close(); + for (std::unordered_map::const_iterator iter = games.cbegin(); iter != games.cend(); ++iter) { std::string path = iter->first; @@ -157,9 +180,26 @@ void CollectionSystemManager::saveCustomCollection(SystemData* sys) if (path.find(rompath) == 0) path.replace(0, rompath.size(), "%ROMPATH%/"); - configFile << path << std::endl; + activeGameEntries.push_back(path); } - configFile.close(); + + fileGameEntries.insert(fileGameEntries.cend(), activeGameEntries.cbegin(), + activeGameEntries.cend()); + std::sort(fileGameEntries.begin(), fileGameEntries.end()); + auto last = std::unique(fileGameEntries.begin(), fileGameEntries.end()); + fileGameEntries.erase(last, fileGameEntries.end()); + + #if defined(_WIN64) + configFile.open(Utils::String:: + stringToWideString(getCustomCollectionConfigPath(name)).c_str()); + #else + configFileOut.open(getCustomCollectionConfigPath(name)); + #endif + + for (auto it = fileGameEntries.cbegin(); it != fileGameEntries.cend(); it++) + configFileOut << (*it) << std::endl; + + configFileOut.close(); } } else {