Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
michael@0 | 1 | #!/usr/bin/env python |
michael@0 | 2 | # This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 4 | # You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 5 | |
michael@0 | 6 | # This script provides one-line bootstrap support to configure systems to build |
michael@0 | 7 | # the tree. |
michael@0 | 8 | # |
michael@0 | 9 | # The role of this script is to load the Python modules containing actual |
michael@0 | 10 | # bootstrap support. It does this through various means, including fetching |
michael@0 | 11 | # content from the upstream source repository. |
michael@0 | 12 | |
michael@0 | 13 | # If we add unicode_literals, optparse breaks on Python 2.6.1 (which is needed |
michael@0 | 14 | # to support OS X 10.6). |
michael@0 | 15 | from __future__ import print_function |
michael@0 | 16 | |
michael@0 | 17 | import os |
michael@0 | 18 | import shutil |
michael@0 | 19 | import sys |
michael@0 | 20 | import tempfile |
michael@0 | 21 | try: |
michael@0 | 22 | from urllib2 import urlopen |
michael@0 | 23 | except ImportError: |
michael@0 | 24 | from urllib.request import urlopen |
michael@0 | 25 | |
michael@0 | 26 | from optparse import OptionParser |
michael@0 | 27 | |
michael@0 | 28 | # The next two variables define where in the repository the Python files |
michael@0 | 29 | # reside. This is used to remotely download file content when it isn't |
michael@0 | 30 | # available locally. |
michael@0 | 31 | REPOSITORY_PATH_PREFIX = 'python/mozboot' |
michael@0 | 32 | |
michael@0 | 33 | REPOSITORY_PATHS = [ |
michael@0 | 34 | 'mozboot/__init__.py', |
michael@0 | 35 | 'mozboot/base.py', |
michael@0 | 36 | 'mozboot/bootstrap.py', |
michael@0 | 37 | 'mozboot/centos.py', |
michael@0 | 38 | 'mozboot/debian.py', |
michael@0 | 39 | 'mozboot/fedora.py', |
michael@0 | 40 | 'mozboot/freebsd.py', |
michael@0 | 41 | 'mozboot/gentoo.py', |
michael@0 | 42 | 'mozboot/openbsd.py', |
michael@0 | 43 | 'mozboot/osx.py', |
michael@0 | 44 | 'mozboot/ubuntu.py', |
michael@0 | 45 | ] |
michael@0 | 46 | |
michael@0 | 47 | TEMPDIR = None |
michael@0 | 48 | |
michael@0 | 49 | def setup_proxy(): |
michael@0 | 50 | # Some Linux environments define ALL_PROXY, which is a SOCKS proxy |
michael@0 | 51 | # intended for all protocols. Python doesn't currently automatically |
michael@0 | 52 | # detect this like it does for http_proxy and https_proxy. |
michael@0 | 53 | if 'ALL_PROXY' in os.environ and 'https_proxy' not in os.environ: |
michael@0 | 54 | os.environ['https_proxy'] = os.environ['ALL_PROXY'] |
michael@0 | 55 | if 'ALL_PROXY' in os.environ and 'http_proxy' not in os.environ: |
michael@0 | 56 | os.environ['http_proxy'] = os.environ['ALL_PROXY'] |
michael@0 | 57 | |
michael@0 | 58 | def fetch_files(repo_url, repo_type): |
michael@0 | 59 | setup_proxy() |
michael@0 | 60 | repo_url = repo_url.rstrip('/') |
michael@0 | 61 | |
michael@0 | 62 | files = {} |
michael@0 | 63 | |
michael@0 | 64 | if repo_type == 'hgweb': |
michael@0 | 65 | for path in REPOSITORY_PATHS: |
michael@0 | 66 | url = repo_url + '/raw-file/default/python/mozboot/' + path |
michael@0 | 67 | |
michael@0 | 68 | req = urlopen(url=url, timeout=30) |
michael@0 | 69 | files[path] = req.read() |
michael@0 | 70 | else: |
michael@0 | 71 | raise NotImplementedError('Not sure how to handle repo type.', repo_type) |
michael@0 | 72 | |
michael@0 | 73 | return files |
michael@0 | 74 | |
michael@0 | 75 | def ensure_environment(repo_url=None, repo_type=None): |
michael@0 | 76 | """Ensure we can load the Python modules necessary to perform bootstrap.""" |
michael@0 | 77 | |
michael@0 | 78 | try: |
michael@0 | 79 | from mozboot.bootstrap import Bootstrapper |
michael@0 | 80 | return Bootstrapper |
michael@0 | 81 | except ImportError: |
michael@0 | 82 | # The first fallback is to assume we are running from a tree checkout |
michael@0 | 83 | # and have the files in a sibling directory. |
michael@0 | 84 | pardir = os.path.join(os.path.dirname(__file__), os.path.pardir) |
michael@0 | 85 | include = os.path.normpath(pardir) |
michael@0 | 86 | |
michael@0 | 87 | sys.path.append(include) |
michael@0 | 88 | try: |
michael@0 | 89 | from mozboot.bootstrap import Bootstrapper |
michael@0 | 90 | return Bootstrapper |
michael@0 | 91 | except ImportError: |
michael@0 | 92 | sys.path.pop() |
michael@0 | 93 | |
michael@0 | 94 | # The next fallback is to download the files from the source |
michael@0 | 95 | # repository. |
michael@0 | 96 | files = fetch_files(repo_url, repo_type) |
michael@0 | 97 | |
michael@0 | 98 | # Install them into a temporary location. They will be deleted |
michael@0 | 99 | # after this script has finished executing. |
michael@0 | 100 | global TEMPDIR |
michael@0 | 101 | TEMPDIR = tempfile.mkdtemp() |
michael@0 | 102 | |
michael@0 | 103 | for relpath in files.keys(): |
michael@0 | 104 | destpath = os.path.join(TEMPDIR, relpath) |
michael@0 | 105 | destdir = os.path.dirname(destpath) |
michael@0 | 106 | |
michael@0 | 107 | if not os.path.exists(destdir): |
michael@0 | 108 | os.makedirs(destdir) |
michael@0 | 109 | |
michael@0 | 110 | with open(destpath, 'wb') as fh: |
michael@0 | 111 | fh.write(files[relpath]) |
michael@0 | 112 | |
michael@0 | 113 | # This should always work. |
michael@0 | 114 | sys.path.append(TEMPDIR) |
michael@0 | 115 | from mozboot.bootstrap import Bootstrapper |
michael@0 | 116 | return Bootstrapper |
michael@0 | 117 | |
michael@0 | 118 | def main(args): |
michael@0 | 119 | parser = OptionParser() |
michael@0 | 120 | parser.add_option('-r', '--repo-url', dest='repo_url', |
michael@0 | 121 | default='https://hg.mozilla.org/mozilla-central/', |
michael@0 | 122 | help='Base URL of source control repository where bootstrap files can ' |
michael@0 | 123 | 'be downloaded.') |
michael@0 | 124 | |
michael@0 | 125 | parser.add_option('--repo-type', dest='repo_type', |
michael@0 | 126 | default='hgweb', |
michael@0 | 127 | help='The type of the repository. This defines how we fetch file ' |
michael@0 | 128 | 'content. Like --repo, you should not need to set this.') |
michael@0 | 129 | |
michael@0 | 130 | options, leftover = parser.parse_args(args) |
michael@0 | 131 | |
michael@0 | 132 | try: |
michael@0 | 133 | try: |
michael@0 | 134 | cls = ensure_environment(options.repo_url, options.repo_type) |
michael@0 | 135 | except Exception as e: |
michael@0 | 136 | print('Could not load the bootstrap Python environment.\n') |
michael@0 | 137 | print('This should never happen. Consider filing a bug.\n') |
michael@0 | 138 | print('\n') |
michael@0 | 139 | print(e) |
michael@0 | 140 | return 1 |
michael@0 | 141 | |
michael@0 | 142 | dasboot = cls() |
michael@0 | 143 | dasboot.bootstrap() |
michael@0 | 144 | |
michael@0 | 145 | return 0 |
michael@0 | 146 | finally: |
michael@0 | 147 | if TEMPDIR is not None: |
michael@0 | 148 | shutil.rmtree(TEMPDIR) |
michael@0 | 149 | |
michael@0 | 150 | |
michael@0 | 151 | if __name__ == '__main__': |
michael@0 | 152 | sys.exit(main(sys.argv)) |