~jelmer/ubuntu-dev-tools/lptools-migration

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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#!/usr/bin/python
#
#   ubuntu-build - command line interface for Launchpad buildd operations.
#
#   Copyright (C) 2007 Canonical Ltd.
#   Authors:
#    - Martin Pitt <martin.pitt@canonical.com>
#    - Jonathan Davies <jpds@ubuntu.com>
#    - Michael Bienia <geser@ubuntu.com>
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# Our modules to import.
import sys
from optparse import OptionGroup
from optparse import OptionParser
from ubuntutools.lp.udtexceptions import (SeriesNotFoundException,
                                          PackageNotFoundException,
                                          PocketDoesNotExistError,)
from ubuntutools.lp.lpapicache import Distribution, PersonTeam
from ubuntutools.misc import split_release_pocket

def main():
    # Usage.
    usage = "%prog <srcpackage> <release> <operation>\n\n"
    usage += "Where operation may be one of: rescore, retry, or status.\n"
    usage += "Only Launchpad Buildd Admins may rescore package builds."

    # Valid architectures.
    valid_archs =  set(["armel", "amd64", "hppa", "i386",
                        "ia64", "lpia", "powerpc", "sparc"])

    # Prepare our option parser.
    opt_parser = OptionParser(usage)

    # Retry options
    retry_rescore_options = OptionGroup(opt_parser, "Retry and rescore options",
                                        "These options may only be used with "
                                        "the 'retry' and 'rescore' operations.")
    retry_rescore_options.add_option("-a", "--arch", type="string",
                                     action="append", dest="architecture",
                                     help="Rebuild or rescore a specific "
                                          "architecture. Valid architectures "
                                          "include: %s." %
                                          ", ".join(valid_archs))

    # Batch processing options
    batch_options = OptionGroup(opt_parser, "Batch processing",
                                "These options and parameter ordering is only "
                                "available in --batch mode.\nUsage: "
                                "ubuntu-build --batch [options] <package>...")
    batch_options.add_option('--batch',
                             action='store_true', dest='batch', default=False,
                             help='Enable batch mode')
    batch_options.add_option('--series',
                             action='store', dest='series', type='string',
                             help='Selects the Ubuntu series to operate on '
                                  '(default: current development series)')
    batch_options.add_option('--retry',
                             action='store_true', dest='retry', default=False,
                             help='Retry builds (give-back).')
    batch_options.add_option('--rescore',
                             action='store', dest='priority', type='int',
                             help='Rescore builds to <priority>.')
    batch_options.add_option('--arch2', action='append', dest='architecture',
                             type='string',
                             help="Affect only 'architecture' (can be used "
                                  "several times). Valid architectures are: %s."
                                  % ', '.join(valid_archs))

    # Add the retry options to the main group.
    opt_parser.add_option_group(retry_rescore_options)
    # Add the batch mode to the main group.
    opt_parser.add_option_group(batch_options)

    # Parse our options.
    (options, args) = opt_parser.parse_args()

    if not len(args):
        opt_parser.print_help()
        sys.exit(1)

    if not options.batch:
        # Check we have the correct number of arguments.
        if len(args) < 3:
            opt_parser.error("Incorrect number of arguments.")

        try:
            package = str(args[0]).lower()
            release = str(args[1]).lower()
            op      = str(args[2]).lower()
        except IndexError:
            opt_parser.print_help()
            sys.exit(1)

        # Check our operation.
        if op not in ("rescore", "retry", "status"):
            print >> sys.stderr, "Invalid operation: %s." % op
            sys.exit(1)

        # If the user has specified an architecture to build, we only wish to
        # rebuild it and nothing else.
        if options.architecture:
            if options.architecture[0] not in valid_archs:
                print >> sys.stderr, ("Invalid architecture specified: %s."
                                      % options.architecture[0])
                sys.exit(1)
            else:
                one_arch = True
        else:
            one_arch = False

        # split release and pocket
        try:
            (release, pocket) = split_release_pocket(release)
        except PocketDoesNotExistError, error:
            print 'E: %s' % error
            sys.exit(1)

        # Get the ubuntu archive
        try:
            ubuntu_archive = Distribution('ubuntu').getArchive()
        # Will fail here if we have no credentials, bail out
        except IOError:
            sys.exit(1)
        # Get list of published sources for package in question.
        try:
            sources = ubuntu_archive.getSourcePackage(package, release, pocket)
            distroseries = Distribution('ubuntu').getSeries(release)
        except (SeriesNotFoundException, PackageNotFoundException), error:
            print error
            sys.exit(1)
        # Get list of builds for that package.
        builds = sources.getBuilds()

        # Find out the version and component in given release.
        version = sources.getVersion()
        component = sources.getComponent()

        # Operations that are remaining may only be done by Ubuntu developers
        # (retry) or buildd admins (rescore). Check if the proper permissions
        # are in place.
        me = PersonTeam.me
        if op == "rescore":
            necessary_privs = me.isLpTeamMember('launchpad-buildd-admins')
        if op == "retry":
            necessary_privs = me.canUploadPackage(ubuntu_archive, distroseries,
                                                  sources.getPackageName(),
                                                  sources.getComponent())

        if op in ('rescore', 'retry') and not necessary_privs:
            print >> sys.stderr, ("You cannot perform the %s operation on a %s "
                                  "package as you do not have the permissions "
                                  "to do this action." % (op, component))
            sys.exit(1)

        # Output details.
        print ("The source version for '%s' in %s (%s) is at %s."
               % (package, release.capitalize(), component, version))

        print "Current build status for this package:"

        # Output list of arches for package and their status.
        done = False
        for build in builds:
            if one_arch and build.arch_tag != options.architecture[0]:
                # Skip this architecture.
                continue

            done = True
            print "%s: %s." % (build.arch_tag, build.buildstate)
            if op == 'rescore':
                if build.can_be_rescored:
                    # FIXME: make priority an option
                    priority = 5000
                    print 'Rescoring build %s to %d...' % \
                          (build.arch_tag, priority)
                    build.rescore(score = priority)
                else:
                    print 'Cannot rescore build on %s.' % build.arch_tag
            if op == 'retry':
                if build.can_be_retried:
                    print 'Retrying build on %s...' % build.arch_tag
                    build.retry()
                else:
                    print 'Cannot retry build on %s.' % build.arch_tag


        # We are done
        if done:
            sys.exit(0)

        print ("No builds for '%s' found in the %s release - it may have been "
               "built in a former release." % (package, release.capitalize()))
        sys.exit(0)

    # Batch mode

    if not options.architecture:
        # no specific architectures specified, assume all valid ones
        archs = valid_archs
    else:
        archs = set(options.architecture)

    # filter out duplicate and invalid architectures
    archs.intersection_update(valid_archs)

    release = (options.series or
               Distribution('ubuntu').getDevelopmentSeries().name)
    try:
        (release, pocket) = split_release_pocket(release)
    except PocketDoesNotExistError, error:
        print 'E: %s' % error
        sys.exit(1)

    ubuntu_archive = Distribution('ubuntu').getArchive()
    try:
        distroseries = Distribution('ubuntu').getSeries(release)
    except SeriesNotFoundException, error:
        print error
        sys.exit(1)
    me = PersonTeam.me

    # Check permisions (part 1): Rescoring can only be done by buildd admins
    can_rescore = ((options.priority
                    and me.isLpTeamMember('launchpad-buildd-admins'))
                   or False)
    if options.priority and not can_rescore:
        print >> sys.stderr, ("You don't have the permissions to rescore "
                              "builds. Ignoring your rescore request.")

    for pkg in args:
        try:
            pkg = ubuntu_archive.getSourcePackage(pkg, release, pocket)
        except PackageNotFoundException, error:
            print error
            continue

        # Check permissions (part 2): check upload permissions for the source
        # package
        can_retry = options.retry and me.canUploadPackage(ubuntu_archive,
                                                          distroseries,
                                                          pkg.getPackageName(),
                                                          pkg.getComponent())
        if options.retry and not can_retry:
            print >> sys.stderr, ("You don't have the permissions to retry the "
                                  "build of '%s'. Ignoring your request."
                                  % pkg.getPackageName())

        print "The source version for '%s' in '%s' (%s) is: %s" % (
                pkg.getPackageName(), release, pocket, pkg.getVersion())

        print pkg.getBuildStates(archs)
        if can_retry:
            print pkg.retryBuilds(archs)
        if options.priority and can_rescore:
            print pkg.rescoreBuilds(archs, options.priority)

        print ''

if __name__ == '__main__':
    main()