diff options
Diffstat (limited to 'src/mods.cpp')
-rw-r--r-- | src/mods.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/mods.cpp b/src/mods.cpp new file mode 100644 index 000000000..285c4cbb9 --- /dev/null +++ b/src/mods.cpp @@ -0,0 +1,98 @@ +/* +Minetest-c55 +Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "mods.h" +#include <queue> +#include <fstream> +#include <sstream> +#include "filesys.h" +#include "strfnd.h" + +// Get a dependency-sorted list of ModSpecs +core::list<ModSpec> getMods(core::list<std::string> &modspaths) + throw(ModError) +{ + std::queue<ModSpec> mods_satisfied; + core::list<ModSpec> mods_unsorted; + core::list<ModSpec> mods_sorted; + for(core::list<std::string>::Iterator i = modspaths.begin(); + i != modspaths.end(); i++){ + std::string modspath = *i; + std::vector<fs::DirListNode> dirlist = fs::GetDirListing(modspath); + for(u32 j=0; j<dirlist.size(); j++){ + if(!dirlist[j].dir) + continue; + std::string modname = dirlist[j].name; + std::string modpath = modspath + DIR_DELIM + modname; + std::set<std::string> depends; + std::ifstream is((modpath+DIR_DELIM+"depends.txt").c_str(), + std::ios_base::binary); + while(is.good()){ + std::string dep; + std::getline(is, dep); + dep = trim(dep); + if(dep != "") + depends.insert(dep); + } + ModSpec spec(modname, modpath, depends); + mods_unsorted.push_back(spec); + if(depends.empty()) + mods_satisfied.push(spec); + } + } + // Sort by depencencies + while(!mods_satisfied.empty()){ + ModSpec mod = mods_satisfied.front(); + mods_satisfied.pop(); + mods_sorted.push_back(mod); + for(core::list<ModSpec>::Iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); i++){ + ModSpec &mod2 = *i; + if(mod2.unsatisfied_depends.empty()) + continue; + mod2.unsatisfied_depends.erase(mod.name); + if(!mod2.unsatisfied_depends.empty()) + continue; + mods_satisfied.push(mod2); + } + } + std::ostringstream errs(std::ios::binary); + // Check unsatisfied dependencies + for(core::list<ModSpec>::Iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); i++){ + ModSpec &mod = *i; + if(mod.unsatisfied_depends.empty()) + continue; + errs<<"mod \""<<mod.name + <<"\" has unsatisfied dependencies:"; + for(std::set<std::string>::iterator + i = mod.unsatisfied_depends.begin(); + i != mod.unsatisfied_depends.end(); i++){ + errs<<" \""<<(*i)<<"\""; + } + errs<<"."<<std::endl; + mods_sorted.push_back(mod); + } + if(errs.str().size() != 0){ + throw ModError(errs.str()); + } + return mods_sorted; +} + + |