From: Ingo Ruhnke Date: Sat, 23 Aug 2014 21:39:23 +0000 (+0200) Subject: Added script to generate index for addon repository X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=77670ab7044567b726420cd0ca5d63edfc6d0bcf;p=supertux.git Added script to generate index for addon repository --- diff --git a/tools/build-addon-index.py b/tools/build-addon-index.py new file mode 100755 index 000000000..0159ab9d7 --- /dev/null +++ b/tools/build-addon-index.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +# SuperTux +# Copyright (C) 2006 Matthias Braun +# +# 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 3 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, see . + + +import sexpr +import sys +import os +import glob +import hashlib + +def escape_str(str): + return "\"%s\"" % str.replace("\"", "\\\"") + +class Addon: + def __init__(self, filename): + lst = sexpr.parse(filename) + if lst[0][0] != "supertux-addoninfo": + raise Exception("not a supertux-addoninfo: %s" % lst[0][0]) + else: + tags = {} + for k, v in lst[0][1:]: + if k == "id": + self.id = v + elif k == "version": + self.version = int(v) + elif k == "type": + self.type = v + elif k == "title": + self.title = v + elif k == "author": + self.author = v + elif k == "license": + self.license = v + else: + raise Exception("unknown tag: %s" % k) + + self.md5 = "" + self.url = "" + + def write(self, fout): + fout.write(" (supertux-addoninfo\n") + fout.write(" (id %s)\n" % escape_str(self.id)) + fout.write(" (version %d)\n" % self.version) + fout.write(" (type %s)\n" % escape_str(self.type)) + fout.write(" (title %s)\n" % escape_str(self.title)) + fout.write(" (author %s)\n" % escape_str(self.author)) + fout.write(" (license %s)\n" % escape_str(self.license)) + fout.write(" (http-url %s)\n" % escape_str(self.url)) + fout.write(" (md5 %s)\n" % escape_str(self.md5)) + fout.write(" )\n") + +def process_addon(addon_dir, nfo, md5, url): + # print addon_dir, nfo + with open(nfo) as fin: + addon = Addon(fin.read()) + addon.md5 = md5 + addon.url = url + addon.write(sys.stdout) + +sys.stdout.write(";; automatically generated by build-addon-index.py\n") +sys.stdout.write("(supertux-addons\n") +for directory in sys.argv[1:]: + for addon_dir in os.listdir(directory): + zipfile = os.path.normpath(os.path.join(directory, "../repository/", addon_dir + ".zip")) + with open(zipfile, 'rb') as fin: + md5 = hashlib.md5(fin.read()).hexdigest() + url = "http://localhost:8000/repository/%s" % (addon_dir + ".zip") + nfos = glob.glob(os.path.join(directory, addon_dir, "*.nfo")) + if len(nfos) == 0: + raise Exception(".nfo file missing") + elif len(nfos) > 1: + raise Exception("to many .nfo files") + else: + try: + process_addon(os.path.join(directory, addon_dir), nfos[0], md5, url) + except Exception, e: + sys.stderr.write("%s: ignoring addon because: %s\n" % (addon_dir, e)) +sys.stdout.write(")\n\n;; EOF ;;\n") + +# EOF # diff --git a/tools/sexpr.py b/tools/sexpr.py new file mode 100755 index 000000000..4c69f920f --- /dev/null +++ b/tools/sexpr.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Ingo Ruhnke +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# 3. This notice may not be removed or altered from any source distribution. + +import re +import codecs + +def parse(text): + stack = [[]] + state = 'list' + i = 0 + line = 1 + column = 0 + while i < len(text): + c = text[i] + if c == '\n': + line += 1 + column = 0 + else: + column += 1 + + if state == 'list': + if c == '(': + stack.append([]) + elif c == ')': + stack[-2].append(stack.pop()) + elif c == "\"": + state = 'string' + atom = "" + elif c == ";": + state = 'comment' + elif c.isalpha(): + state = 'symbol' + atom = c + elif c.isdigit(): + state = 'number' + atom = c + elif c.isspace(): + pass + else: + raise Exception("%d:%d: error: unexpected character: '%s'" % (line, column, c)) + + elif state == 'comment': + if c == '\n': + state = 'list' + else: + pass + + elif state == 'string': + if c == "\\": + i += 1 + atom += text[i] + elif c == "\"": + stack[-1].append(atom) + state = 'list' + else: + atom += c + + elif state == 'number': + if not c.isdigit() or c != ".": + stack[-1].append(int(atom)) + state = 'list' + i -= 1 + else: + atom += c + + elif state == 'symbol': + if c.isspace() or c == '(' or c == ')': + stack[-1].append(atom) + state = 'list' + i -= 1 + else: + atom += c + + # print c, stack + + i += 1 + + if len(stack) == 1: + return stack[0] + else: + raise Exception("error: list not closed") + +if __name__ == "__main__": + print "parsing..." + result = parse(r'(() ("bar" foo) ()) () bar ') + print "1.", result + print "2.", parse(""";;comment + ("Hello World" 5 1 123) ("Hello" 123 123 "foobar") ;; comment""") + print "3.", parse(r'(8(8)8)') + print "4.", parse(r'') + print "5.", parse(r' ') + with codecs.open("white.stf", encoding='utf-8') as fin: + print "6.", parse(fin.read()) + +# EOF #