build-addon-index.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #!/usr/bin/env python
  2. #
  3. # SuperTux
  4. # Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. import argparse
  19. import glob
  20. import hashlib
  21. import os
  22. import subprocess
  23. import sys
  24. import sexpr
  25. def escape_str(str):
  26. return "\"%s\"" % str.replace("\"", "\\\"")
  27. class Addon:
  28. def __init__(self, filename):
  29. lst = sexpr.parse(filename)
  30. if lst[0][0] != "supertux-addoninfo":
  31. raise Exception("not a supertux-addoninfo: %s" % lst[0][0])
  32. else:
  33. tags = {}
  34. for k, v in lst[0][1:]:
  35. if k == "id":
  36. self.id = v
  37. elif k == "version":
  38. self.version = int(v)
  39. elif k == "type":
  40. self.type = v
  41. elif k == "title":
  42. self.title = v
  43. elif k == "author":
  44. self.author = v
  45. elif k == "license":
  46. self.license = v
  47. else:
  48. raise Exception("unknown tag: %s" % k)
  49. self.md5 = ""
  50. self.url = ""
  51. def write(self, fout):
  52. fout.write(" (supertux-addoninfo\n")
  53. fout.write(" (id %s)\n" % escape_str(self.id))
  54. fout.write(" (version %d)\n" % self.version)
  55. fout.write(" (type %s)\n" % escape_str(self.type))
  56. fout.write(" (title %s)\n" % escape_str(self.title))
  57. fout.write(" (author %s)\n" % escape_str(self.author))
  58. fout.write(" (license %s)\n" % escape_str(self.license))
  59. fout.write(" (url %s)\n" % escape_str(self.url))
  60. fout.write(" (md5 %s)\n" % escape_str(self.md5))
  61. fout.write(" )\n")
  62. def process_addon(fout, addon_dir, nfo, base_url, zipdir):
  63. # print addon_dir, nfo
  64. with open(nfo) as fin:
  65. addon = Addon(fin.read())
  66. zipfile = addon.id + "_v" + str(addon.version) + ".zip"
  67. # see http://pivotallabs.com/barriers-deterministic-reproducible-zip-files/
  68. os.remove(os.path.join(zipdir, zipfile))
  69. zipout = os.path.relpath(os.path.join(zipdir, zipfile), addon_dir)
  70. subprocess.call(["zip", "-X", "-r", "--quiet", zipout, "."], cwd=addon_dir)
  71. with open(os.path.join(zipdir, zipfile), 'rb') as fin:
  72. addon.md5 = hashlib.md5(fin.read()).hexdigest()
  73. addon.url = base_url + zipfile
  74. addon.write(fout)
  75. def generate_index(fout, directory, base_url, zipdir):
  76. fout.write(";; automatically generated by build-addon-index.py\n")
  77. fout.write("(supertux-addons\n")
  78. for addon_dir in os.listdir(directory):
  79. addon_dir = os.path.join(directory, addon_dir)
  80. if os.path.isdir(addon_dir):
  81. print addon_dir
  82. nfos = glob.glob(os.path.join(addon_dir, "*.nfo"))
  83. if len(nfos) == 0:
  84. raise Exception(".nfo file missing from %s" % addon_dir)
  85. elif len(nfos) > 1:
  86. raise Exception("to many .nfo files in %s" % addon_dir)
  87. else:
  88. try:
  89. process_addon(fout, addon_dir, nfos[0], base_url, zipdir)
  90. except Exception, e:
  91. sys.stderr.write("%s: ignoring addon because: %s\n" % (addon_dir, e))
  92. fout.write(")\n\n;; EOF ;;\n")
  93. if __name__ == "__main__":
  94. parser = argparse.ArgumentParser(description='Addon Index/Zip Generator')
  95. parser.add_argument('DIRECTORY', type=str, nargs=1,
  96. help="directory containing the mods")
  97. parser.add_argument('-o', '--output', metavar='FILE', type=str, required=False,
  98. help="output file")
  99. parser.add_argument('-z', '--zipdir', metavar="DIR", type=str, required=True,
  100. help="generate zip files")
  101. parser.add_argument('-u', '--url', metavar='FILE', type=str,
  102. default="https://raw.githubusercontent.com/SuperTux/addons/master/repository/",
  103. help="base url")
  104. args = parser.parse_args()
  105. if args.output is None:
  106. fout = sys.stdout
  107. generate_index(fout, args.DIRECTORY[0], args.url, args.zipdir)
  108. else:
  109. with open(args.output, "w") as fout:
  110. generate_index(fout, args.DIRECTORY[0], args.url, args.zipdir)
  111. # EOF #