| #!/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, 'https://github.com/mesonbuild/{}.git'.format(sproj), 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('Subproject is already there. To update, nuke the {} dir and reinstall.'.format(outdir)) |
| 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('https://api.github.com/repos/mesonbuild/{}/branches'.format(sproj)) |
| 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:])) |