diff options
author | rubenwardy <rw@rubenwardy.com> | 2020-01-19 01:22:33 +0000 |
---|---|---|
committer | rubenwardy <rw@rubenwardy.com> | 2020-01-19 01:22:33 +0000 |
commit | 1b1c94ffa0d349f2702342cf6e1796840db88a87 (patch) | |
tree | f0eae76eec6285584a97caf00cf332a16654e50c /app/tasks/minetestcheck/tree.py | |
parent | bcd003685e9fbc38ff484a55ead38d381d75925b (diff) | |
download | cheatdb-1b1c94ffa0d349f2702342cf6e1796840db88a87.tar.xz |
Add release contents validation
Diffstat (limited to 'app/tasks/minetestcheck/tree.py')
-rw-r--r-- | app/tasks/minetestcheck/tree.py | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/app/tasks/minetestcheck/tree.py b/app/tasks/minetestcheck/tree.py new file mode 100644 index 0000000..38c2880 --- /dev/null +++ b/app/tasks/minetestcheck/tree.py @@ -0,0 +1,162 @@ +import os +from . import MinetestCheckError, ContentType +from .config import parse_conf + +def get_base_dir(path): + if not os.path.isdir(path): + raise IOError("Expected dir") + + root, subdirs, files = next(os.walk(path)) + if len(subdirs) == 1 and len(files) == 0: + return get_base_dir(path + "/" + subdirs[0]) + else: + return path + + +def detect_type(path): + if os.path.isfile(path + "/game.conf"): + return ContentType.GAME + elif os.path.isfile(path + "/init.lua"): + return ContentType.MOD + elif os.path.isfile(path + "/modpack.txt") or \ + os.path.isfile(path + "/modpack.conf"): + return ContentType.MODPACK + elif os.path.isdir(path + "/mods"): + return ContentType.GAME + elif os.path.isfile(path + "/texture_pack.conf"): + return ContentType.TXP + else: + return ContentType.UNKNOWN + + +class PackageTreeNode: + def __init__(self, baseDir, relative, author=None, repo=None, name=None): + print(baseDir) + self.baseDir = baseDir + self.relative = relative + self.author = author + self.name = name + self.repo = repo + self.meta = None + self.children = [] + + # Detect type + self.type = detect_type(baseDir) + self.read_meta() + + if self.type == ContentType.GAME: + if not os.path.isdir(baseDir + "/mods"): + raise MinetestCheckError(("game at {} does not have a mods/ folder").format(self.relative)) + self.add_children_from_mod_dir(baseDir + "/mods") + elif self.type == ContentType.MODPACK: + self.add_children_from_mod_dir(baseDir) + + + def read_meta(self): + result = {} + + # .conf file + try: + with open(self.baseDir + "/mod.conf", "r") as myfile: + conf = parse_conf(myfile.read()) + for key in ["name", "description", "title", "depends", "optional_depends"]: + try: + result[key] = conf[key] + except KeyError: + pass + except IOError: + pass + + # description.txt + if not "description" in result: + try: + with open(self.baseDir + "/description.txt", "r") as myfile: + result["description"] = myfile.read() + except IOError: + pass + + # depends.txt + import re + pattern = re.compile("^([a-z0-9_]+)\??$") + if not "depends" in result and not "optional_depends" in result: + try: + with open(self.baseDir + "/depends.txt", "r") as myfile: + contents = myfile.read() + soft = [] + hard = [] + for line in contents.split("\n"): + line = line.strip() + if pattern.match(line): + if line[len(line) - 1] == "?": + soft.append( line[:-1]) + else: + hard.append(line) + + result["depends"] = hard + result["optional_depends"] = soft + + except IOError: + pass + + else: + if "depends" in result: + result["depends"] = [x.strip() for x in result["depends"].split(",")] + if "optional_depends" in result: + result["optional_depends"] = [x.strip() for x in result["optional_depends"].split(",")] + + + # Calculate Title + if "name" in result and not "title" in result: + result["title"] = result["name"].replace("_", " ").title() + + # Calculate short description + if "description" in result: + desc = result["description"] + idx = desc.find(".") + 1 + cutIdx = min(len(desc), 200 if idx < 5 else idx) + result["short_description"] = desc[:cutIdx] + + if "name" in result: + self.name = result["name"] + del result["name"] + + self.meta = result + + def add_children_from_mod_dir(self, dir): + for entry in next(os.walk(dir))[1]: + path = os.path.join(dir, entry) + if not entry.startswith('.') and os.path.isdir(path): + child = PackageTreeNode(path, self.relative + entry + "/", name=entry) + if not child.type.isModLike(): + raise MinetestCheckError(("Expecting mod or modpack, found {} at {} inside {}") \ + .format(child.type.value, child.relative, self.type.value)) + + self.children.append(child) + + + def fold(self, attr, key=None, acc=None): + if acc is None: + acc = set() + + if self.meta is None: + return acc + + at = getattr(self, attr) + value = at if key is None else at.get(key) + + if isinstance(value, list): + acc |= set(value) + elif value is not None: + acc.add(value) + + for child in self.children: + child.fold(attr, key, acc) + + return acc + + def get(self, key): + return self.meta.get(key) + + def validate(self): + for child in self.children: + child.validate() |