python/mozboot/bin/bootstrap.py
author Kyle Machulis <kyle@nonpolynomial.com>
Fri, 29 Mar 2013 15:12:58 -0700
changeset 137136 0db3022ca2e6bec95897850f797f078464a7f529
parent 120023 df3cc14f0ecdc69cc0b8e7a63293673618e636a5
child 138409 f20b0ce9e5280e9add20742262aa90440404f9cc
permissions -rwxr-xr-x
Backout for changeset 03452b187c14 (Bug 855465) due to bustage on a CLOSED TREE; r=qdot

#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

# This script provides one-line bootstrap support to configure systems to build
# the tree.
#
# The role of this script is to load the Python modules containing actual
# bootstrap support. It does this through various means, including fetching
# content from the upstream source repository.

# If we add unicode_literals, optparse breaks on Python 2.6.1 (which is needed
# to support OS X 10.6).
from __future__ import print_function

import os
import shutil
import sys
import tempfile
import urllib2

from optparse import OptionParser

# The next two variables define where in the repository the Python files
# reside. This is used to remotely download file content when it isn't
# available locally.
REPOSITORY_PATH_PREFIX = 'python/mozboot'

REPOSITORY_PATHS = [
    'mozboot/__init__.py',
    'mozboot/base.py',
    'mozboot/bootstrap.py',
    'mozboot/centos.py',
    'mozboot/fedora.py',
    'mozboot/gentoo.py',
    'mozboot/mint.py',
    'mozboot/openbsd.py',
    'mozboot/osx.py',
    'mozboot/ubuntu.py',
]

TEMPDIR = None

def fetch_files(repo_url, repo_type):
    repo_url = repo_url.rstrip('/')

    files = {}

    if repo_type == 'hgweb':
        for path in REPOSITORY_PATHS:
            url = repo_url + '/raw-file/default/python/mozboot/' + path

            req = urllib2.urlopen(url=url, timeout=30)
            files[path] = req.read()
    else:
        raise NotImplementedError('Not sure how to handle repo type.', repo_type)

    return files

def ensure_environment(repo_url=None, repo_type=None):
    """Ensure we can load the Python modules necessary to perform bootstrap."""

    try:
        from mozboot.bootstrap import Bootstrapper
        return Bootstrapper
    except ImportError:
        # The first fallback is to assume we are running from a tree checkout
        # and have the files in a sibling directory.
        pardir = os.path.join(os.path.dirname(__file__), os.path.pardir)
        include = os.path.normpath(pardir)

        sys.path.append(include)
        try:
            from mozboot.bootstrap import Bootstrapper
            return Bootstrapper
        except ImportError:
            sys.path.pop()

            # The next fallback is to download the files from the source
            # repository.
            files = fetch_files(repo_url, repo_type)

            # Install them into a temporary location. They will be deleted
            # after this script has finished executing.
            global TEMPDIR
            TEMPDIR = tempfile.mkdtemp()

            for relpath in files.keys():
                destpath = os.path.join(TEMPDIR, relpath)
                destdir = os.path.dirname(destpath)

                if not os.path.exists(destdir):
                    os.makedirs(destdir)

                with open(destpath, 'wb') as fh:
                    fh.write(files[relpath])

            # This should always work.
            sys.path.append(TEMPDIR)
            from mozboot.bootstrap import Bootstrapper
            return Bootstrapper

def main(args):
    parser = OptionParser()
    parser.add_option('-r', '--repo-url', dest='repo_url',
        default='https://hg.mozilla.org/mozilla-central/',
        help='Base URL of source control repository where bootstrap files can '
             'be downloaded.')

    parser.add_option('--repo-type', dest='repo_type',
        default='hgweb',
        help='The type of the repository. This defines how we fetch file '
             'content. Like --repo, you should not need to set this.')

    options, leftover = parser.parse_args(args)

    try:
        try:
            cls = ensure_environment(options.repo_url, options.repo_type)
        except Exception as e:
            print('Could not load the bootstrap Python environment.\n')
            print('This should never happen. Consider filing a bug.\n')
            print('\n')
            print(e)
            return 1

        dasboot = cls()
        dasboot.bootstrap()

        return 0
    finally:
        if TEMPDIR is not None:
            shutil.rmtree(TEMPDIR)


if __name__ == '__main__':
    sys.exit(main(sys.argv))