ghwt.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/env python3
  2. # Copyright 2016 The Meson development team
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS,
  9. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. # See the License for the specific language governing permissions and
  11. # limitations under the License.
  12. import urllib.request, json, sys, os, shutil, subprocess
  13. import configparser, hashlib
  14. private_repos = {'meson', 'wrapweb', 'meson-ci'}
  15. def gh_get(url):
  16. r = urllib.request.urlopen(url)
  17. jd = json.loads(r.read().decode('utf-8'))
  18. return jd
  19. def list_projects():
  20. jd = gh_get('https://api.github.com/orgs/mesonbuild/repos')
  21. entries = [entry['name'] for entry in jd]
  22. entries = [e for e in entries if e not in private_repos]
  23. entries.sort()
  24. for i in entries:
  25. print(i)
  26. return 0
  27. def unpack(sproj, branch, outdir):
  28. subprocess.check_call(['git', 'clone', '-b', branch, 'https://github.com/mesonbuild/%s.git' % sproj, outdir])
  29. usfile = os.path.join(outdir, 'upstream.wrap')
  30. assert(os.path.isfile(usfile))
  31. config = configparser.ConfigParser()
  32. config.read(usfile)
  33. us_url = config['wrap-file']['source_url']
  34. us = urllib.request.urlopen(us_url).read()
  35. h = hashlib.sha256()
  36. h.update(us)
  37. dig = h.hexdigest()
  38. should = config['wrap-file']['source_hash']
  39. if dig != should:
  40. print('Incorrect hash on download.')
  41. print(' expected:', dig)
  42. print(' obtained:', should)
  43. return 1
  44. spdir = os.path.split(outdir)[0]
  45. ofilename = os.path.join(spdir, config['wrap-file']['source_filename'])
  46. with open(ofilename, 'wb') as ofile:
  47. ofile.write(us)
  48. if 'lead_directory_missing' in config['wrap-file']:
  49. os.mkdir(outdir)
  50. shutil.unpack_archive(ofilename, outdir)
  51. else:
  52. shutil.unpack_archive(ofilename, spdir)
  53. extdir = os.path.join(spdir, config['wrap-file']['directory'])
  54. assert(os.path.isdir(extdir))
  55. shutil.move(os.path.join(outdir, '.git'), extdir)
  56. subprocess.check_call(['git', 'reset', '--hard'], cwd=extdir)
  57. shutil.rmtree(outdir)
  58. shutil.move(extdir, outdir)
  59. shutil.rmtree(os.path.join(outdir, '.git'))
  60. os.unlink(ofilename)
  61. def install(sproj):
  62. sproj_dir = os.path.join('subprojects', sproj)
  63. if not os.path.isdir('subprojects'):
  64. print('Run this in your source root and make sure there is a subprojects directory in it.')
  65. return 1
  66. if os.path.isdir(sproj_dir):
  67. print('Subproject is already there. To update, nuke the dir and reinstall.')
  68. return 1
  69. blist = gh_get('https://api.github.com/repos/mesonbuild/%s/branches' % sproj)
  70. blist = [b['name'] for b in blist]
  71. blist = [b for b in blist if b != 'master']
  72. blist.sort()
  73. branch = blist[-1]
  74. print('Using branch', branch)
  75. return unpack(sproj, branch, sproj_dir)
  76. def run(args):
  77. if len(args) == 0 or args[0] == '-h' or args[0] == '--help':
  78. print(sys.argv[0], 'list/install', 'package_name')
  79. return 1
  80. command = args[0]
  81. args = args[1:]
  82. if command == 'list':
  83. list_projects()
  84. return 0
  85. elif command == 'install':
  86. if len(args) != 1:
  87. print('Install requires exactly one argument.')
  88. return 1
  89. return install(args[0])
  90. else:
  91. print('Unknown command')
  92. return 1
  93. if __name__ == '__main__':
  94. print('This is an emergency wrap downloader. Use only when wrapdb is down.')
  95. sys.exit(run(sys.argv[1:]))