From 294cb02aafea429c826f7a1107024b50ccf2d7f9 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Thu, 6 Jun 2013 16:40:21 +0100 Subject: [PATCH] Finished work on issue #10. --- src/backend/metadata.cpp | 12 ++---- src/gui/main.cpp | 83 ++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/backend/metadata.cpp b/src/backend/metadata.cpp index fa19cb25..ca92185d 100644 --- a/src/backend/metadata.cpp +++ b/src/backend/metadata.cpp @@ -536,15 +536,6 @@ namespace boss { for (set::const_iterator it=incompatibilities.begin(), endit=incompatibilities.end(); it != endit; ++it) { incs.insert(boost::to_lower_copy(it->Name())); } - for (vector::const_iterator it=masters.begin(), endit=masters.end(); it != endit; ++it) { - reqs.insert(boost::to_lower_copy(*it)); - } - for (set::const_iterator it=requirements.begin(), endit=requirements.end(); it != endit; ++it) { - reqs.insert(boost::to_lower_copy(it->Name())); - } - for (set::const_iterator it=loadAfter.begin(), endIt=loadAfter.end(); it != endIt; ++it) { - reqs.insert(boost::to_lower_copy(it->Name())); - } //Check 1: None of this plugin's masters or requirements or 'load after' plugins may be in branch. //Check 2: None of this plugin's masters or requirements or 'load after' plugins may be in incs. @@ -553,6 +544,7 @@ namespace boss { //Check 5: This plugin must not be present in branch (performed above). //Also check the consistency of the plugins this plugin is dependent on. for (vector::const_iterator it=masters.begin(), endit=masters.end(); it != endit; ++it) { + reqs.insert(boost::to_lower_copy(*it)); if (branch.find(boost::to_lower_copy(*it)) != branch.end()) issues.insert(pair(*it, true)); if (incs.find(boost::to_lower_copy(*it)) != incs.end()) @@ -564,6 +556,7 @@ namespace boss { } } for (set::const_iterator it=requirements.begin(), endIt=requirements.end(); it != endIt; ++it) { + reqs.insert(boost::to_lower_copy(it->Name())); if (branch.find(boost::to_lower_copy(it->Name())) != branch.end()) issues.insert(pair(it->Name(), true)); if (incs.find(boost::to_lower_copy(it->Name())) != incs.end()) @@ -575,6 +568,7 @@ namespace boss { } } for (set::const_iterator it=loadAfter.begin(), endIt=loadAfter.end(); it != endIt; ++it) { + reqs.insert(boost::to_lower_copy(it->Name())); if (branch.find(boost::to_lower_copy(it->Name())) != branch.end()) issues.insert(pair(it->Name(), true)); if (incs.find(boost::to_lower_copy(it->Name())) != incs.end()) diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 8b0d492e..82ae80c2 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -395,6 +395,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { progDia->Pulse(); + bool cyclicDependenciesExist = false; if (fs::exists(_game.MasterlistPath()) || fs::exists(_game.UserlistPath())) { out << "Merging plugin lists, evaluating conditions and and checking for install validity..." << endl; @@ -408,6 +409,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { lang = boss::LANG_ENG; //Merge plugin list, masterlist and userlist plugin data. + map consistencyIssues; for (list::iterator it=plugins.begin(), endIt=plugins.end(); it != endIt; ++it) { //Check if there is already a plugin in the 'plugins' list or not. list::iterator pos = std::find(mlist_plugins.begin(), mlist_plugins.end(), *it); @@ -441,28 +443,31 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { set dependencies, incompatibilities, reqs; map issues; issues = it->CheckSelfConsistency(plugins, dependencies, incompatibilities, reqs); - for (map::const_iterator jt=issues.begin(), endJt=issues.end(); jt != endJt; ++jt) { - if (jt->second) - messages.push_back(boss::Message(boss::MESSAGE_ERROR, "For \"" + it->Name() + "\", \"" + jt->first + "\" is a circular dependency.")); - else - messages.push_back(boss::Message(boss::MESSAGE_ERROR, "For \"" + it->Name() + "\", \"" + jt->first + "\" is given as a dependency and an incompatibility.")); - } + consistencyIssues.insert(issues.begin(), issues.end()); //Also check install validity. issues = it->CheckInstallValidity(_game); - list messages = it->Messages(); + list pluginMessages = it->Messages(); for (map::const_iterator jt=issues.begin(), endJt=issues.end(); jt != endJt; ++jt) { if (jt->second) - messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is incompatible with \"" + it->Name() + "\" and is present.")); + pluginMessages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is incompatible with \"" + it->Name() + "\" and is present.")); else - messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is required by \"" + it->Name() + "\" but is missing.")); + pluginMessages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is required by \"" + it->Name() + "\" but is missing.")); } if (!issues.empty()) - it->Messages(messages); + it->Messages(pluginMessages); progDia->Pulse(); } + for (map::const_iterator jt=consistencyIssues.begin(), endJt=consistencyIssues.end(); jt != endJt; ++jt) { + if (jt->second) { + messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is a circular dependency. Plugins will not be sorted.")); + cyclicDependenciesExist = true; + } else + messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is given as a dependency and an incompatibility.")); + } + end = time(NULL); out << "Time taken to merge lists, evaluate conditions and check for install validity: " << (end - start) << " seconds." << endl; start = time(NULL); @@ -470,45 +475,47 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { progDia->Pulse(); - out << "Sorting plugins..." << endl; + if (!cyclicDependenciesExist) { + out << "Sorting plugins..." << endl; - //std::sort doesn't compare each plugin to every other plugin, it seems to compare plugins until no movement is necessary, because it assumes that each plugin will be comparable on all tested data, which isn't the case when dealing with masters, etc. Therefore, loop through the list and move each plugin's dependencies directly before it, then apply std::sort. - list::iterator it=plugins.begin(); - while (it != plugins.end()) { - list::iterator jt=it; - ++jt; + //std::sort doesn't compare each plugin to every other plugin, it seems to compare plugins until no movement is necessary, because it assumes that each plugin will be comparable on all tested data, which isn't the case when dealing with masters, etc. Therefore, loop through the list and move each plugin's dependencies directly before it, then apply std::sort. + list::iterator it=plugins.begin(); + while (it != plugins.end()) { + list::iterator jt=it; + ++jt; - out << "Sorting for: " << it->Name() << endl; + out << "Sorting for: " << it->Name() << endl; - list moved; - while (jt != plugins.end()) { - if (it->MustLoadAfter(*jt)) { - moved.push_back(*jt); - jt = plugins.erase(jt); + list moved; + while (jt != plugins.end()) { + if (it->MustLoadAfter(*jt)) { + moved.push_back(*jt); + jt = plugins.erase(jt); + } else + ++jt; + + progDia->Pulse(); + } + if (!moved.empty()) { + plugins.insert(it, moved.begin(), moved.end()); + advance(it, -1*(int)moved.size()); } else - ++jt; + ++it; progDia->Pulse(); } - if (!moved.empty()) { - plugins.insert(it, moved.begin(), moved.end()); - advance(it, -1*(int)moved.size()); - } else - ++it; + + plugins.sort(boss::load_order_sort); + + end = time(NULL); + out << "Time taken to sort plugins: " << (end - start) << " seconds." << endl; progDia->Pulse(); + + for (list::iterator it=plugins.begin(), endIt = plugins.end(); it != endIt; ++it) + out << it->Name() << endl; } - plugins.sort(boss::load_order_sort); - - end = time(NULL); - out << "Time taken to sort plugins: " << (end - start) << " seconds." << endl; - - progDia->Pulse(); - - for (list::iterator it=plugins.begin(), endIt = plugins.end(); it != endIt; ++it) - out << it->Name() << endl; - out << "Generating report..." << endl; //Read the details section of the previous report, if it exists.