diff options
Diffstat (limited to 'meson/ghwt.py')
-rwxr-xr-x | meson/ghwt.py | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/meson/ghwt.py b/meson/ghwt.py new file mode 100755 index 000000000..6f9373b2c --- /dev/null +++ b/meson/ghwt.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 + +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ghwt - GitHub WrapTool +# +# An emergency wraptool(1) replacement downloader that downloads +# directly from GitHub in case wrapdb.mesonbuild.com is down. + +import urllib.request, json, sys, os, shutil, subprocess +import configparser, hashlib + +req_timeout = 600.0 +private_repos = {'meson', 'wrapweb', 'meson-ci'} +spdir = 'subprojects' + +def gh_get(url): + r = urllib.request.urlopen(url, timeout=req_timeout) + jd = json.loads(r.read().decode('utf-8')) + return jd + +def list_projects(): + jd = gh_get('https://api.github.com/orgs/mesonbuild/repos') + entries = [entry['name'] for entry in jd] + entries = [e for e in entries if e not in private_repos] + entries.sort() + for i in entries: + print(i) + return 0 + +def unpack(sproj, branch): + tmpdir = os.path.join(spdir, sproj + '_ghwt') + shutil.rmtree(tmpdir, ignore_errors=True) + subprocess.check_call(['git', 'clone', '-b', branch, f'https://github.com/mesonbuild/{sproj}.git', tmpdir]) + usfile = os.path.join(tmpdir, 'upstream.wrap') + assert(os.path.isfile(usfile)) + config = configparser.ConfigParser(interpolation=None) + config.read(usfile) + outdir = os.path.join(spdir, sproj) + if 'directory' in config['wrap-file']: + outdir = os.path.join(spdir, config['wrap-file']['directory']) + if os.path.isdir(outdir): + print(f'Subproject is already there. To update, nuke the {outdir} dir and reinstall.') + shutil.rmtree(tmpdir) + return 1 + us_url = config['wrap-file']['source_url'] + us = urllib.request.urlopen(us_url, timeout=req_timeout).read() + h = hashlib.sha256() + h.update(us) + dig = h.hexdigest() + should = config['wrap-file']['source_hash'] + if dig != should: + print('Incorrect hash on download.') + print(' expected:', should) + print(' obtained:', dig) + return 1 + ofilename = os.path.join(spdir, config['wrap-file']['source_filename']) + with open(ofilename, 'wb') as ofile: + ofile.write(us) + if 'lead_directory_missing' in config['wrap-file']: + os.mkdir(outdir) + shutil.unpack_archive(ofilename, outdir) + else: + shutil.unpack_archive(ofilename, spdir) + assert(os.path.isdir(outdir)) + shutil.move(os.path.join(tmpdir, '.git'), outdir) + subprocess.check_call(['git', 'reset', '--hard'], cwd=outdir) + shutil.rmtree(tmpdir) + shutil.rmtree(os.path.join(outdir, '.git')) + os.unlink(ofilename) + +def install(sproj, requested_branch=None): + if not os.path.isdir(spdir): + print('Run this in your source root and make sure there is a subprojects directory in it.') + return 1 + blist = gh_get(f'https://api.github.com/repos/mesonbuild/{sproj}/branches') + blist = [b['name'] for b in blist] + blist = [b for b in blist if b != 'master'] + blist.sort() + branch = blist[-1] + if requested_branch is not None: + if requested_branch in blist: + branch = requested_branch + else: + print('Could not find user-requested branch', requested_branch) + print('Available branches for', sproj, ':') + print(blist) + return 1 + print('Using branch', branch) + return unpack(sproj, branch) + +def print_help(): + print('Usage:') + print(sys.argv[0], 'list') + print(sys.argv[0], 'install', 'package_name', '[branch_name]') + +def run(args): + if not args or args[0] == '-h' or args[0] == '--help': + print_help() + return 1 + command = args[0] + args = args[1:] + if command == 'list': + list_projects() + return 0 + elif command == 'install': + if len(args) == 1: + return install(args[0]) + elif len(args) == 2: + return install(args[0], args[1]) + else: + print_help() + return 1 + else: + print('Unknown command') + return 1 + +if __name__ == '__main__': + print('This is an emergency wrap downloader. Use only when wrapdb is down.') + sys.exit(run(sys.argv[1:])) |