~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to bootstrap.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2009-07-16 03:44:09 UTC
  • mfrom: (8827.2.7 buildout-sitepackage)
  • Revision ID: launchpad@pqm.canonical.com-20090716034409-2zc27qubsc8dtd5z
[r=flacoste][ui=none] integrate my zc.buildout branches to fix a
        variety of problems of using buildout with a system Python

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
# FOR A PARTICULAR PURPOSE.
12
12
#
13
13
##############################################################################
14
 
 
15
 
# NOTE TO LAUNCHPAD DEVELOPERS: This is a bootstrapping file from the
16
 
# zc.buildout project, which we have hacked slightly: look for the string
17
 
# "HACK" below.   See the docstring below for usage.
18
 
 
19
14
"""Bootstrap a buildout-based project
20
15
 
21
16
Simply run this script in a directory containing a buildout.cfg.
22
17
The script accepts buildout command-line options, so you can
23
18
use the -c option to specify an alternate configuration file.
24
19
 
25
 
$Id$
 
20
$Id: bootstrap.py 101879 2009-07-14 01:24:48Z gary $
26
21
"""
27
22
 
28
 
import os, shutil, sys, tempfile, urllib2
29
 
 
30
 
tmpeggs = tempfile.mkdtemp()
31
 
 
32
 
is_jython = sys.platform.startswith('java')
 
23
import os, re, shutil, sys, tempfile, textwrap, urllib, urllib2
 
24
 
 
25
# We have to manually parse our options rather than using one of the stdlib
 
26
# tools because we want to pass the ones we don't recognize along to
 
27
# zc.buildout.buildout.main.
 
28
 
 
29
configuration = {
 
30
    '--ez_setup-source': 'http://peak.telecommunity.com/dist/ez_setup.py',
 
31
    '--version': '',
 
32
    '--download-base': None,
 
33
    '--eggs': None}
 
34
 
 
35
helpstring = __doc__ + textwrap.dedent('''
 
36
    This script recognizes the following options itself.  The first option it
 
37
    encounters that is not one of these will cause the script to stop parsing
 
38
    options and pass the rest on to buildout.  Therefore, if you want to use
 
39
    any of the following options *and* buildout command-line options like
 
40
    -c, first use the following options, and then use the buildout options.
 
41
 
 
42
    Options: 
 
43
      --version=ZC_BUILDOUT_VERSION
 
44
                Specify a version number of the zc.buildout to use
 
45
      --ez_setup-source=URL_OR_FILE
 
46
                Specify a URL or file location for the ez_setup file.
 
47
                Defaults to
 
48
                %(--ez_setup-source)s
 
49
      --download-base=URL_OR_DIRECTORY
 
50
                Specify a URL or directory for downloading setuptools and
 
51
                zc.buildout.  Defaults to PyPI.
 
52
      --eggs=DIRECTORY
 
53
                Specify a directory for storing eggs.  Defaults to a temporary
 
54
                directory that is deleted when the bootstrap script completes.
 
55
 
 
56
    By using --ez_setup-source and --download-base to point to local resources,
 
57
    you can keep this script from going over the network.
 
58
    ''' % configuration)
 
59
match_equals = re.compile(r'(%s)=(.*)' % ('|'.join(configuration),)).match
 
60
args = sys.argv[1:]
 
61
if args == ['--help']:
 
62
    print helpstring
 
63
    sys.exit(0)
 
64
 
 
65
# If we end up using a temporary directory for storing our eggs, this will
 
66
# hold the path of that directory.  On the other hand, if an explicit directory
 
67
# is specified in the argv, this will remain None.
 
68
tmpeggs = None
 
69
 
 
70
while args:
 
71
    val = args[0]
 
72
    if val in configuration:
 
73
        del args[0]
 
74
        if not args or args[0].startswith('-'):
 
75
            print "ERROR: %s requires an argument."
 
76
            print helpstring
 
77
            sys.exit(1)
 
78
        configuration[val] = args[0]
 
79
    else:
 
80
        match = match_equals(val)
 
81
        if match and match.group(1) in configuration:
 
82
            configuration[match.group(1)] = match.group(2)
 
83
        else:
 
84
            break
 
85
    del args[0]
 
86
 
 
87
for name in ('--ez_setup-source', '--download-base'):
 
88
    val = configuration[name]
 
89
    if val is not None and '://' not in val: # We're being lazy.
 
90
        configuration[name] = 'file://%s' % (
 
91
            urllib.pathname2url(os.path.abspath(os.path.expanduser(val))),)
 
92
 
 
93
if (configuration['--download-base'] and
 
94
    not configuration['--download-base'].endswith('/')):
 
95
    # Download base needs a trailing slash to make the world happy.
 
96
    configuration['--download-base'] += '/'
 
97
 
 
98
if not configuration['--eggs']:
 
99
    configuration['--eggs'] = tmpeggs = tempfile.mkdtemp()
 
100
else:
 
101
    configuration['--eggs'] = os.path.abspath(
 
102
        os.path.expanduser(configuration['--eggs']))
 
103
 
 
104
# The requirement is what we will pass to setuptools to specify zc.buildout.
 
105
requirement = 'zc.buildout'
 
106
if configuration['--version']:
 
107
    requirement += '==' + configuration['--version']
33
108
 
34
109
try:
35
110
    import pkg_resources
36
111
except ImportError:
37
112
    ez = {}
38
 
    # HACK: the next two logical lines have been hacked for Launchpad to make
39
 
    # bootstrapping not get any files over the network.  This is useful for
40
 
    # development because it speeds up the build and makes it possible to
41
 
    # make a new branch when you don't have network access.  It is essential
42
 
    # for deployment because we currently do not allow network access on PQM
43
 
    # or our deployment boxes.
44
 
    exec open('ez_setup.py').read() in ez
45
 
    ez['use_setuptools'](
46
 
        to_dir=tmpeggs,
47
 
        download_base='file://%s/download-cache/dist/' % (os.getcwd(),),
48
 
        download_delay=0)
 
113
    exec urllib2.urlopen(configuration['--ez_setup-source']).read() in ez
 
114
    setuptools_args = dict(to_dir=configuration['--eggs'], download_delay=0)
 
115
    if configuration['--download-base']:
 
116
        setuptools_args['download_base'] = configuration['--download-base']
 
117
    ez['use_setuptools'](**setuptools_args)
49
118
 
50
119
    import pkg_resources
51
120
 
58
127
else:
59
128
    def quote (c):
60
129
        return c
61
 
 
62
 
cmd = 'from setuptools.command.easy_install import main; main()'
63
 
ws  = pkg_resources.working_set
64
 
 
 
130
cmd = [quote(sys.executable),
 
131
       '-c',
 
132
       quote('from setuptools.command.easy_install import main; main()'),
 
133
       '-mqNxd',
 
134
       quote(configuration['--eggs'])]
 
135
 
 
136
if configuration['--download-base']:
 
137
    cmd.extend(['-f', quote(configuration['--download-base'])])
 
138
 
 
139
cmd.append(requirement)
 
140
 
 
141
ws = pkg_resources.working_set
 
142
env = dict(
 
143
    os.environ,
 
144
    PYTHONPATH=ws.find(pkg_resources.Requirement.parse('setuptools')).location)
 
145
 
 
146
is_jython = sys.platform.startswith('java')
65
147
if is_jython:
66
148
    import subprocess
67
 
    
68
 
    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', 
69
 
           quote(tmpeggs), 'zc.buildout'], 
70
 
           env=dict(os.environ,
71
 
               PYTHONPATH=
72
 
               ws.find(pkg_resources.Requirement.parse('setuptools')).location
73
 
               ),
74
 
           ).wait() == 0
75
 
 
76
 
else:
77
 
    assert os.spawnle(
78
 
        os.P_WAIT, sys.executable, quote (sys.executable),
79
 
        '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
80
 
        dict(os.environ,
81
 
            PYTHONPATH=
82
 
            ws.find(pkg_resources.Requirement.parse('setuptools')).location
83
 
            ),
84
 
        ) == 0
85
 
 
86
 
ws.add_entry(tmpeggs)
87
 
ws.require('zc.buildout')
 
149
    exitcode = subprocess.Popen(cmd, env=env).wait()
 
150
else: # Windows needs this, apparently; otherwise we would prefer subprocess
 
151
    exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
 
152
if exitcode != 0:
 
153
    sys.stdout.flush()
 
154
    print ("An error occured when trying to install zc.buildout. "
 
155
           "Look above this message for any errors that "
 
156
           "were output by easy_install.")
 
157
    sys.exit(exitcode)
 
158
 
 
159
ws.add_entry(configuration['--eggs'])
 
160
ws.require(requirement)
88
161
import zc.buildout.buildout
89
 
zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
90
 
shutil.rmtree(tmpeggs)
 
162
args.append('bootstrap')
 
163
zc.buildout.buildout.main(args)
 
164
if tmpeggs is not None:
 
165
    shutil.rmtree(tmpeggs)