|  | #!/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:])) |