Index: bootstrap/bootstrap.py |
diff --git a/bootstrap/bootstrap.py b/bootstrap/bootstrap.py |
deleted file mode 100755 |
index df14e858decf8e4bca1d4c713037955d6f3e37e6..0000000000000000000000000000000000000000 |
--- a/bootstrap/bootstrap.py |
+++ /dev/null |
@@ -1,226 +0,0 @@ |
-#!/usr/bin/env python |
-# Copyright 2014 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
- |
-import argparse |
-import contextlib |
-import glob |
-import logging |
-import os |
-import shutil |
-import subprocess |
-import sys |
-import tempfile |
- |
-from util import STORAGE_URL, OBJECT_URL, LOCAL_STORAGE_PATH, LOCAL_OBJECT_URL |
-from util import read_deps, merge_deps, print_deps, platform_tag |
- |
-LOGGER = logging.getLogger(__name__) |
- |
-# /path/to/infra |
-ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
- |
-PYTHON_BAT_WIN = '@%~dp0\\..\\Scripts\\python.exe %*' |
- |
- |
-class NoWheelException(Exception): |
- def __init__(self, name, version, build, source_sha): |
- super(NoWheelException, self).__init__( |
- 'No matching wheel found for (%s==%s (build %s_%s))' % |
- (name, version, build, source_sha)) |
- |
- |
-def check_pydistutils(): |
- if os.path.exists(os.path.expanduser('~/.pydistutils.cfg')): |
- print >> sys.stderr, '\n'.join([ |
- '', |
- '', |
- '=========== ERROR ===========', |
- 'You have a ~/.pydistutils.cfg file, which interferes with the ', |
- 'infra virtualenv environment. Please move it to the side and bootstrap ', |
- 'again. Once infra has bootstrapped, you may move it back.', |
- '', |
- 'Upstream bug: https://github.com/pypa/virtualenv/issues/88/', |
- '' |
- ]) |
- sys.exit(1) |
- |
- |
-def ls(prefix): |
- from pip._vendor import requests # pylint: disable=E0611 |
- data = requests.get(STORAGE_URL, params=dict( |
- prefix=prefix, |
- fields='items(name,md5Hash)' |
- )).json() |
- entries = data.get('items', []) |
- for entry in entries: |
- entry['md5Hash'] = entry['md5Hash'].decode('base64').encode('hex') |
- entry['local'] = False |
- # Also look in the local cache |
- entries.extend([ |
- {'name': fname, 'md5Hash': None, 'local': True} |
- for fname in glob.glob(os.path.join(LOCAL_STORAGE_PATH, |
- prefix.split('/')[-1] + '*'))]) |
- return entries |
- |
- |
-def sha_for(deps_entry): |
- if 'rev' in deps_entry: |
- return deps_entry['rev'] |
- else: |
- return deps_entry['gs'].split('.')[0] |
- |
- |
-def get_links(deps): |
- import pip.wheel # pylint: disable=E0611 |
- plat_tag = platform_tag() |
- |
- links = [] |
- |
- for name, dep in deps.iteritems(): |
- version, source_sha = dep['version'] , sha_for(dep) |
- prefix = 'wheels/{}-{}-{}_{}'.format(name, version, dep['build'], |
- source_sha) |
- generic_link = None |
- binary_link = None |
- local_link = None |
- |
- for entry in ls(prefix): |
- fname = entry['name'].split('/')[-1] |
- md5hash = entry['md5Hash'] |
- wheel_info = pip.wheel.Wheel.wheel_file_re.match(fname) |
- if not wheel_info: |
- LOGGER.warn('Skipping invalid wheel: %r', fname) |
- continue |
- |
- if pip.wheel.Wheel(fname).supported(): |
- if entry['local']: |
- link = LOCAL_OBJECT_URL.format(entry['name']) |
- local_link = link |
- continue |
- else: |
- link = OBJECT_URL.format(entry['name'], md5hash) |
- if fname.endswith('none-any.whl'): |
- if generic_link: |
- LOGGER.error( |
- 'Found more than one generic matching wheel for %r: %r', |
- prefix, dep) |
- continue |
- generic_link = link |
- elif plat_tag in fname: |
- if binary_link: |
- LOGGER.error( |
- 'Found more than one binary matching wheel for %r: %r', |
- prefix, dep) |
- continue |
- binary_link = link |
- |
- if not binary_link and not generic_link and not local_link: |
- raise NoWheelException(name, version, dep['build'], source_sha) |
- |
- links.append(local_link or binary_link or generic_link) |
- |
- return links |
- |
- |
-@contextlib.contextmanager |
-def html_index(links): |
- tf = tempfile.mktemp('.html') |
- try: |
- with open(tf, 'w') as f: |
- print >> f, '<html><body>' |
- for link in links: |
- print >> f, '<a href="%s">wat</a>' % link |
- print >> f, '</body></html>' |
- yield tf |
- finally: |
- os.unlink(tf) |
- |
- |
-def install(deps): |
- bin_dir = 'Scripts' if sys.platform.startswith('win') else 'bin' |
- pip = os.path.join(sys.prefix, bin_dir, 'pip') |
- |
- links = get_links(deps) |
- with html_index(links) as ipath: |
- requirements = [] |
- # TODO(iannucci): Do this as a requirements.txt |
- for name, deps_entry in deps.iteritems(): |
- if not deps_entry.get('implicit'): |
- requirements.append('%s==%s' % (name, deps_entry['version'])) |
- subprocess.check_call( |
- [pip, 'install', '--no-index', '--download-cache', |
- os.path.join(ROOT, '.wheelcache'), '-f', ipath] + requirements) |
- |
- |
-def activate_env(env, deps): |
- if hasattr(sys, 'real_prefix'): |
- LOGGER.error('Already activated environment!') |
- return |
- |
- print 'Activating environment: %r' % env |
- assert isinstance(deps, dict) |
- |
- manifest_path = os.path.join(env, 'manifest.pyl') |
- cur_deps = read_deps(manifest_path) |
- if cur_deps != deps: |
- print ' Removing old environment: %r' % cur_deps |
- shutil.rmtree(env, ignore_errors=True) |
- cur_deps = None |
- |
- if cur_deps is None: |
- check_pydistutils() |
- |
- print ' Building new environment' |
- # Add in bundled virtualenv lib |
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'virtualenv')) |
- import virtualenv # pylint: disable=F0401 |
- virtualenv.create_environment( |
- env, search_dirs=virtualenv.file_search_dirs()) |
- |
- print ' Activating environment' |
- # Ensure hermeticity during activation. |
- os.environ.pop('PYTHONPATH', None) |
- bin_dir = 'Scripts' if sys.platform.startswith('win') else 'bin' |
- activate_this = os.path.join(env, bin_dir, 'activate_this.py') |
- execfile(activate_this, dict(__file__=activate_this)) |
- |
- if cur_deps is None: |
- print ' Installing deps' |
- print_deps(deps, indent=2, with_implicit=False) |
- install(deps) |
- virtualenv.make_environment_relocatable(env) |
- with open(manifest_path, 'wb') as f: |
- f.write(repr(deps) + '\n') |
- |
- # Create bin\python.bat on Windows to unify path where Python is found. |
- if sys.platform.startswith('win'): |
- bin_path = os.path.join(env, 'bin') |
- if not os.path.isdir(bin_path): |
- os.makedirs(bin_path) |
- python_bat_path = os.path.join(bin_path, 'python.bat') |
- if not os.path.isfile(python_bat_path): |
- with open(python_bat_path, 'w') as python_bat_file: |
- python_bat_file.write(PYTHON_BAT_WIN) |
- |
- print 'Done creating environment' |
- |
- |
-def main(args): |
- parser = argparse.ArgumentParser() |
- parser.add_argument('--deps-file', '--deps_file', action='append', |
- help='Path to deps.pyl file (may be used multiple times)') |
- parser.add_argument('env_path', |
- help='Path to place environment (default: %(default)s)', |
- default='ENV') |
- opts = parser.parse_args(args) |
- |
- deps = merge_deps(opts.deps_file) |
- activate_env(opts.env_path, deps) |
- |
- |
-if __name__ == '__main__': |
- logging.basicConfig() |
- LOGGER.setLevel(logging.DEBUG) |
- sys.exit(main(sys.argv[1:])) |