OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 import argparse |
| 7 import hashlib |
| 8 import os |
| 9 import shutil |
| 10 import subprocess |
| 11 import sys |
| 12 |
| 13 import bootstrap |
| 14 |
| 15 from util import GIT_REPO, ROOT, WHEELHOUSE, WHEELS_URL, SOURCE_URL |
| 16 |
| 17 from util import tempdir, tempname, read_deps, print_deps, platform_tag |
| 18 |
| 19 |
| 20 def has_custom_build(name): |
| 21 return os.path.exists(os.path.join(ROOT, 'custom_builds', name + '.py')) |
| 22 |
| 23 |
| 24 def pip(*args, **kwargs): |
| 25 subprocess.check_call( |
| 26 (os.path.join(sys.prefix, 'bin', 'pip'),) + args, **kwargs) |
| 27 |
| 28 |
| 29 def wheel(arg, source_sha, build, build_options): |
| 30 with tempdir() as tdir: |
| 31 args = ['wheel', '--no-index', '--no-deps', '--wheel-dir', tdir] |
| 32 for op in build_options: |
| 33 args += ['--global-option', op] |
| 34 args += [arg] |
| 35 pip(*args) |
| 36 grab_wheel(tdir, WHEELHOUSE, source_sha, build) |
| 37 |
| 38 |
| 39 def grab_wheel(src, dst, source_sha, build): |
| 40 # late import lets us grab the virtualenv pip |
| 41 from pip.wheel import Wheel |
| 42 |
| 43 items = os.listdir(src) |
| 44 assert len(items) == 1, 'Wrong number of files in wheel directory: %r' % items |
| 45 |
| 46 wheelfile = items[0] |
| 47 wheel_info = Wheel.wheel_file_re.match(wheelfile) |
| 48 |
| 49 assert wheel_info is not None, 'Not a wheel file? %r' % wheelfile |
| 50 |
| 51 plat_tag = '' |
| 52 if not wheelfile.endswith('none-any.whl'): |
| 53 plat_tag = platform_tag() |
| 54 |
| 55 os.rename(os.path.join(src, wheelfile), |
| 56 os.path.join(dst, '{}-{}_{}{}{}'.format( |
| 57 wheel_info.group('namever'), |
| 58 build, |
| 59 source_sha, |
| 60 plat_tag, |
| 61 wheel_info.group(4), |
| 62 ))) |
| 63 |
| 64 |
| 65 def run_custom_build(name, link, sha, build): |
| 66 from pip.index import Link |
| 67 from pip.download import unpack_file_url, unpack_vcs_link, is_vcs_url |
| 68 |
| 69 assert has_custom_build(name) |
| 70 |
| 71 link = Link(link, trusted=True) |
| 72 unpack = unpack_vcs_link if is_vcs_url(link) else unpack_file_url |
| 73 |
| 74 with tempdir() as tmpd, tempdir() as wheeld: # pylint: disable=C0321 |
| 75 unpack(link, tmpd) |
| 76 m = getattr(__import__('custom_builds.%s' % (name,)), name) |
| 77 m.Build(tmpd, wheeld) |
| 78 grab_wheel(wheeld, WHEELHOUSE, sha, build) |
| 79 |
| 80 |
| 81 def process_git(name, rev, build, build_options): |
| 82 print |
| 83 print 'Processing (git)', name, rev |
| 84 |
| 85 url = GIT_REPO.format(name) + '@' + rev |
| 86 |
| 87 if not has_custom_build(name): |
| 88 wheel(url, rev, build, build_options) |
| 89 else: |
| 90 run_custom_build(name, url, rev, build) |
| 91 |
| 92 |
| 93 def process_gs(name, sha_ext, build, build_options): |
| 94 print |
| 95 print 'Processing (gs)', name, sha_ext |
| 96 |
| 97 sha, ext = sha_ext.split('.', 1) |
| 98 with tempname(ext) as tmp: |
| 99 link = 'file://' + tmp |
| 100 subprocess.check_call(['gsutil', 'cp', SOURCE_URL.format(sha_ext), tmp]) |
| 101 with open(tmp, 'rb') as f: |
| 102 assert hashlib.sha1(f.read()).hexdigest() == sha |
| 103 if not has_custom_build(name): |
| 104 wheel(link, sha, build, build_options) |
| 105 else: |
| 106 run_custom_build(name, link, sha, build) |
| 107 |
| 108 |
| 109 def clear_wheelhouse(): |
| 110 shutil.rmtree(WHEELHOUSE, ignore_errors=True) |
| 111 try: |
| 112 os.makedirs(WHEELHOUSE) |
| 113 except OSError: |
| 114 pass |
| 115 |
| 116 |
| 117 def push_wheelhouse(): |
| 118 return subprocess.call(['gsutil', '-m', 'cp', WHEELHOUSE + '/*', WHEELS_URL]) |
| 119 |
| 120 |
| 121 def main(args): |
| 122 parser = argparse.ArgumentParser() |
| 123 parser.add_argument( |
| 124 'to_build', nargs='*', |
| 125 help='Names of packages to build. Defaults to all packages.') |
| 126 opts = parser.parse_args(args) |
| 127 |
| 128 if 'Ubuntu' in platform_tag() and ROOT.startswith('/usr/local/'): |
| 129 print >> sys.stderr, "\n".join([ |
| 130 "Due to a bug in Ubuntu's python distribution, build_deps.py does not", |
| 131 "work when run from under a path beginning with /usr/local/. Please ", |
| 132 "clone to a different path, and try again.", |
| 133 "", |
| 134 "Bug: https://github.com/pypa/virtualenv/issues/118" |
| 135 ]) |
| 136 return 1 |
| 137 |
| 138 to_build = set(opts.to_build) |
| 139 |
| 140 build_env = os.path.join(ROOT, 'BUILD_ENV') |
| 141 |
| 142 print 'Parsing deps.pyl' |
| 143 deps = read_deps(os.path.join(ROOT, 'deps.pyl')) |
| 144 bootstrap.activate_env(build_env, {'wheel': deps.pop('wheel')}) |
| 145 |
| 146 print 'Finding missing deps' |
| 147 missing_deps = {} |
| 148 for name, entry in deps.iteritems(): |
| 149 if to_build and name not in to_build: |
| 150 continue |
| 151 try: |
| 152 bootstrap.get_links({name: entry}) |
| 153 except bootstrap.NoWheelException: |
| 154 missing_deps[name] = entry |
| 155 |
| 156 if not missing_deps: |
| 157 print 'Nothing to process' |
| 158 return |
| 159 |
| 160 print 'Processing deps:' |
| 161 print_deps(missing_deps) |
| 162 |
| 163 for name, options in missing_deps.iteritems(): |
| 164 clear_wheelhouse() |
| 165 # TODO(iannucci): skip entries which already exist in gs |
| 166 if 'rev' in options: |
| 167 process_git(name, options['rev'], options['build'], |
| 168 options.get('build_options', ())) |
| 169 elif 'gs' in options: |
| 170 process_gs(name, options['gs'], options['build'], |
| 171 options.get('build_options', ())) |
| 172 else: |
| 173 raise Exception('Invalid options %r for %r' % (options, name)) |
| 174 push_wheelhouse() |
| 175 |
| 176 |
| 177 if __name__ == '__main__': |
| 178 sys.exit(main(sys.argv[1:])) |
OLD | NEW |