summaryrefslogtreecommitdiff
path: root/tools/win32/build_release.py
blob: b66fa8fe3f9e66536c05af291aaab53f7a8a79a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/cygdrive/C/Python25/python
"""A script to help automate the build process."""

# When preparing a new release, make sure to set all of these to the latest
# values.
VERSIONS = {
    'bzr': '1.17',
    'qbzr': '0.12',
    'bzrtools': '1.17.0',
    'bzr-svn': '0.6.3',
    'bzr-rewrite': '0.5.2',
    'subvertpy': '0.6.8',
}

# This will be passed to 'make' to ensure we build with the right python
PYTHON='/cygdrive/c/Python25/python'

# Create the final build in this directory
TARGET_ROOT='release'

DEBUG_SUBPROCESS = True


import os
import shutil
import subprocess
import sys


BZR_EXE = None
def bzr():
    global BZR_EXE
    if BZR_EXE is not None:
        return BZR_EXE
    try:
        subprocess.call(['bzr', '--version'], stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
        BZR_EXE = 'bzr'
    except OSError:
        try:
            subprocess.call(['bzr.bat', '--version'], stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
            BZR_EXE = 'bzr.bat'
        except OSError:
            raise RuntimeError('Could not find bzr or bzr.bat on your path.')
    return BZR_EXE


def call_or_fail(*args, **kwargs):
    """Call a subprocess, and fail if the return code is not 0."""
    if DEBUG_SUBPROCESS:
        print '  calling: "%s"' % (' '.join(args[0]),)
    p = subprocess.Popen(*args, **kwargs)
    (out, err) = p.communicate()
    if p.returncode != 0:
        raise RuntimeError('Failed to run: %s, %s' % (args, kwargs))
    return out


TARGET = None
def get_target():
    global TARGET
    if TARGET is not None:
        return TARGET
    out = call_or_fail([sys.executable, get_bzr_dir() + '/bzr',
                        'version', '--short'], stdout=subprocess.PIPE)
    version = out.strip()
    TARGET = os.path.abspath(TARGET_ROOT + '-' + version)
    return TARGET


def clean_target():
    """Nuke the target directory so we know we are starting from scratch."""
    target = get_target()
    if os.path.isdir(target):
        print "Deleting: %s" % (target,)
        shutil.rmtree(target)

def get_bzr_dir():
    return 'bzr.' + VERSIONS['bzr']


def update_bzr():
    """Make sure we have the latest bzr in play."""
    bzr_dir = get_bzr_dir()
    if not os.path.isdir(bzr_dir):
        bzr_version = VERSIONS['bzr']
        bzr_url = 'lp:bzr/' + bzr_version
        print "Getting bzr release %s from %s" % (bzr_version, bzr_url)
        call_or_fail([bzr(), 'co', bzr_url, bzr_dir])
    else:
        print "Ensuring %s is up-to-date" % (bzr_dir,)
        call_or_fail([bzr(), 'update', bzr_dir])


def create_target():
    target = get_target()
    print "Creating target dir: %s" % (target,)
    call_or_fail([bzr(), 'co', get_bzr_dir(), target])


def get_plugin_trunk_dir(plugin_name):
    return '%s/trunk' % (plugin_name,)


def get_plugin_release_dir(plugin_name):
    return '%s/%s' % (plugin_name, VERSIONS[plugin_name])


def get_plugin_trunk_branch(plugin_name):
    return 'lp:%s' % (plugin_name,)


def update_plugin_trunk(plugin_name):
    trunk_dir = get_plugin_trunk_dir(plugin_name)
    if not os.path.isdir(trunk_dir):
        plugin_trunk = get_plugin_trunk_branch(plugin_name)
        print "Getting latest %s trunk" % (plugin_name,)
        call_or_fail([bzr(), 'co', plugin_trunk,
                      trunk_dir])
    else:
        print "Ensuring %s is up-to-date" % (trunk_dir,)
        call_or_fail([bzr(), 'update', trunk_dir])
    return trunk_dir


def _plugin_tag_name(plugin_name):
    if plugin_name in ('bzr-svn', 'bzr-rewrite', 'subvertpy'):
        return '%s-%s' % (plugin_name, VERSIONS[plugin_name])
    # bzrtools and qbzr use 'release-X.Y.Z'
    return 'release-' + VERSIONS[plugin_name]


def update_plugin(plugin_name):
    release_dir = get_plugin_release_dir(plugin_name)
    if not os.path.isdir(plugin_name):
        if plugin_name in ('bzr-svn', 'bzr-rewrite'):
            # bzr-svn uses a different repo format
            call_or_fail([bzr(), 'init-repo', '--rich-root-pack', plugin_name])
        else:
            os.mkdir(plugin_name)
    if os.path.isdir(release_dir):
        print "Removing existing dir: %s" % (release_dir,)
        shutil.rmtree(release_dir)
    # First update trunk
    trunk_dir = update_plugin_trunk(plugin_name)
    # Now create the tagged directory
    tag_name = _plugin_tag_name(plugin_name)
    print "Creating the branch %s" % (release_dir,)
    call_or_fail([bzr(), 'co', '-rtag:%s' % (tag_name,),
                  trunk_dir, release_dir])
    return release_dir


def install_plugin(plugin_name):
    release_dir = update_plugin(plugin_name)
    # at least bzrtools doesn't like you to call 'setup.py' unless you are in
    # that directory specifically, so we cd, rather than calling it from
    # outside
    print "Installing %s" % (release_dir,)
    call_or_fail([sys.executable, 'setup.py', 'install', '-O1',
                  '--install-lib=%s' % (get_target(),)],
                 cwd=release_dir)


def update_tbzr():
    tbzr_loc = os.environ.get('TBZR', None)
    if tbzr_loc is None:
        raise ValueError('You must set TBZR to the location of tortoisebzr.')
    print 'Updating %s' % (tbzr_loc,)
    call_or_fail([bzr(), 'update', tbzr_loc])


def build_installer():
    target = get_target()
    print
    print
    print '*' * 60
    print 'Building standalone installer'
    call_or_fail(['make', 'PYTHON=%s' % (PYTHON,), 'installer'],
                 cwd=target)


def main(args):
    import optparse

    p = optparse.OptionParser(usage='%prog [OPTIONS]')
    opts, args = p.parse_args(args)

    update_bzr()
    update_tbzr()
    clean_target()
    create_target()
    install_plugin('subvertpy')
    install_plugin('bzrtools')
    install_plugin('qbzr')
    install_plugin('bzr-svn')
    install_plugin('bzr-rewrite')

    build_installer()


if __name__ == '__main__':
    main(sys.argv[1:])

# vim: ts=4 sw=4 sts=4 et ai