~brian-murray/ubuntu-archive-tools/workaround-503

502 by Colin Watson
queue: new script, soon to replace queue in LP
1
#! /usr/bin/python
2
3
# Copyright (C) 2012 Canonical Ltd.
4
# Author: Colin Watson <cjwatson@ubuntu.com>
5
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; version 3 of the License.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
"""Manipulate Ubuntu upload queues."""
19
20
from __future__ import print_function
21
569 by Colin Watson
queue: sort imports
22
import collections
505 by Colin Watson
queue: render item creation dates as an approximate age
23
from datetime import datetime
539 by Colin Watson
queue: when accepting/rejecting multiple items, do so in ID order
24
from operator import attrgetter
969.1.1 by William Grant
Hide deprecated distro/owner/name/partner archive selection options. Use archive references instead.
25
from optparse import OptionParser, SUPPRESS_HELP
625 by Colin Watson
queue fetch: don't overwrite existing files by default; add --overwrite option to restore former behaviour
26
import os
546 by Colin Watson
Importing sys is cheap; just do it at the top rather than on error paths.
27
import sys
502 by Colin Watson
queue: new script, soon to replace queue in LP
28
try:
29
    from urllib.parse import unquote, urlsplit
30
    from urllib.request import urlretrieve
31
except ImportError:
32
    from urllib import unquote, urlretrieve
33
    from urlparse import urlsplit
34
35
from launchpadlib.launchpad import Launchpad
505 by Colin Watson
queue: render item creation dates as an approximate age
36
import pytz
502 by Colin Watson
queue: new script, soon to replace queue in LP
37
506 by Colin Watson
queue: use lputils.setup_location
38
import lputils
39
502 by Colin Watson
queue: new script, soon to replace queue in LP
40
41
CONSUMER_KEY = "queue"
42
43
44
queue_names = (
45
    "New",
46
    "Unapproved",
47
    "Accepted",
48
    "Done",
49
    "Rejected",
677 by Colin Watson
make all scripts pass current stricter pep8(1) in raring
50
)
502 by Colin Watson
queue: new script, soon to replace queue in LP
51
52
505 by Colin Watson
queue: render item creation dates as an approximate age
53
now = datetime.now(pytz.timezone("UTC"))
54
55
502 by Colin Watson
queue: new script, soon to replace queue in LP
56
def queue_item(options, queue_id):
57
    """Load a queue item by its numeric ID."""
58
    return options.launchpad.load('%s%s/%s/+upload/%s' % (
59
        options.launchpad._root_uri.ensureSlash(), options.distribution.name,
60
        options.series.name, queue_id))
61
545 by Colin Watson
Make all scripts pass pep8(1).
62
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
63
def queue_item_allowed(options, item):
617 by Colin Watson
queue: treat copies of custom uploads as binaryful
64
    # Rather than using item.contains_build, treat anything that isn't
65
    # sourceful as binaryful.  This allows us to treat copies of custom
66
    # uploads (which have none of contains_source, contains_copy, or
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
67
    # contains_build) as binaryful.  However, copies may contain both source
68
    # and binaries.
617 by Colin Watson
queue: treat copies of custom uploads as binaryful
69
    sourceful = item.contains_source or item.contains_copy
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
70
    binaryful = not item.contains_source or item.contains_copy
617 by Colin Watson
queue: treat copies of custom uploads as binaryful
71
    if options.source and sourceful:
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
72
        return True
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
73
    elif options.binary and binaryful:
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
74
        return True
75
    else:
76
        return False
77
545 by Colin Watson
Make all scripts pass pep8(1).
78
502 by Colin Watson
queue: new script, soon to replace queue in LP
79
def queue_items(options, args):
80
    if not args:
81
        args = ['']
82
564.1.2 by Steve Langasek
use collections.OrderedDict() instead of a set, so we can still display items in the queue in order
83
    items = collections.OrderedDict()
502 by Colin Watson
queue: new script, soon to replace queue in LP
84
    for arg in args:
85
        arg = arg.strip()
86
        if arg.isdigit():
87
            item = queue_item(options, arg)
88
            if item in items:
89
                continue
90
            if item.status != options.queue:
91
                raise ValueError(
92
                    "Item %s is in queue %s, not requested queue %s" %
93
                    (item.id, item.status, options.queue))
94
            if (item.distroseries != options.series or
677 by Colin Watson
make all scripts pass current stricter pep8(1) in raring
95
                    item.pocket != options.pocket):
502 by Colin Watson
queue: new script, soon to replace queue in LP
96
                if item.pocket == "Release":
97
                    item_suite = item.distroseries.name
98
                else:
608 by Colin Watson
queue: fix typo when fetching non-release-pocket items by ID
99
                    item_suite = "%s-%s" % (
502 by Colin Watson
queue: new script, soon to replace queue in LP
100
                        item.distroseries.name, item.pocket.lower())
101
                raise ValueError("Item %s is in %s/%s not in %s/%s" % (
102
                                 item.id, item.distroseries.distribution.name,
103
                                 item_suite, options.distribution.name,
104
                                 options.suite))
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
105
            if queue_item_allowed(options, item):
564.1.2 by Steve Langasek
use collections.OrderedDict() instead of a set, so we can still display items in the queue in order
106
                items[item] = 1
502 by Colin Watson
queue: new script, soon to replace queue in LP
107
        else:
108
            kwargs = {}
109
            if "/" in arg:
110
                kwargs["name"], kwargs["version"] = arg.split("/")
111
            elif arg:
112
                kwargs["name"] = arg
113
            new_items = options.series.getPackageUploads(
577 by Colin Watson
queue: add --ppa, --ppa-name, and -j/--partner options
114
                archive=options.archive, pocket=options.pocket,
115
                status=options.queue, exact_match=options.exact_match,
116
                **kwargs)
502 by Colin Watson
queue: new script, soon to replace queue in LP
117
            for item in new_items:
564.1.1 by Steve Langasek
Use sets instead of lists for queue items, so that we can scale to handling
118
                if queue_item_allowed(options, item):
564.1.2 by Steve Langasek
use collections.OrderedDict() instead of a set, so we can still display items in the queue in order
119
                    items[item] = 1
502 by Colin Watson
queue: new script, soon to replace queue in LP
120
121
    return items
122
123
124
#XXX cprov 2006-09-19: We need to use template engine instead of hardcoded
125
# format variables.
126
HEAD = "-" * 9 + "|----|" + "-" * 22 + "|" + "-" * 22 + "|" + "-" * 15
127
FOOT_MARGIN = " " * (9 + 6 + 1 + 22 + 1 + 22 + 2)
128
545 by Colin Watson
Make all scripts pass pep8(1).
129
502 by Colin Watson
queue: new script, soon to replace queue in LP
130
def make_tag(item):
131
    if item.contains_copy:
132
        return "X-"
133
    else:
134
        return (("S" if item.contains_source else "-") +
135
                ("B" if item.contains_build else "-"))
136
545 by Colin Watson
Make all scripts pass pep8(1).
137
505 by Colin Watson
queue: render item creation dates as an approximate age
138
def approximate_age(time):
139
    """Return a nicely-formatted approximate age."""
140
    seconds = int((now - time).total_seconds())
141
    if seconds == 1:
142
        return "1 second"
143
    elif seconds < 60:
144
        return "%d seconds" % seconds
145
146
    minutes = int(round(seconds / 60.0))
147
    if minutes == 1:
148
        return "1 minute"
149
    elif minutes < 60:
150
        return "%d minutes" % minutes
151
152
    hours = int(round(minutes / 60.0))
153
    if hours == 1:
154
        return "1 hour"
155
    elif hours < 48:
156
        return "%d hours" % hours
157
158
    days = int(round(hours / 24.0))
159
    if days == 1:
160
        return "1 day"
161
    elif days < 14:
162
        return "%d days" % days
163
164
    weeks = int(round(days / 7.0))
165
    if weeks == 1:
166
        return "1 week"
167
    else:
168
        return "%d weeks" % weeks
169
545 by Colin Watson
Make all scripts pass pep8(1).
170
502 by Colin Watson
queue: new script, soon to replace queue in LP
171
def show_item_main(item):
172
    tag = make_tag(item)
173
    # TODO truncation sucks
174
    print("%8d | %s | %s | %s | %s" %
175
          (item.id, tag, item.display_name.ljust(20)[:20],
505 by Colin Watson
queue: render item creation dates as an approximate age
176
           item.display_version.ljust(20)[:20],
177
           approximate_age(item.date_created)))
502 by Colin Watson
queue: new script, soon to replace queue in LP
178
545 by Colin Watson
Make all scripts pass pep8(1).
179
502 by Colin Watson
queue: new script, soon to replace queue in LP
180
def show_source(source):
181
    print("\t | * %s/%s Component: %s Section: %s" %
182
          (source.package_name, source.package_version,
183
           source.component_name, source.section_name))
184
545 by Colin Watson
Make all scripts pass pep8(1).
185
502 by Colin Watson
queue: new script, soon to replace queue in LP
186
def show_binary(binary):
510 by Colin Watson
queue: handle displaying information on custom uploads
187
    if "customformat" in binary:
188
        print("\t | * %s Format: %s" % (
189
              binary["name"], binary["customformat"]))
502 by Colin Watson
queue: new script, soon to replace queue in LP
190
    else:
510 by Colin Watson
queue: handle displaying information on custom uploads
191
        if binary["is_new"]:
192
            status_flag = "N"
193
        else:
194
            status_flag = "*"
195
        print("\t | %s %s/%s/%s "
196
              "Component: %s Section: %s Priority: %s" % (
197
                  status_flag, binary["name"], binary["version"],
198
                  binary["architecture"], binary["component"],
199
                  binary["section"], binary["priority"]))
502 by Colin Watson
queue: new script, soon to replace queue in LP
200
545 by Colin Watson
Make all scripts pass pep8(1).
201
502 by Colin Watson
queue: new script, soon to replace queue in LP
202
def show_item(item):
203
    show_item_main(item)
204
    if item.contains_copy or item.contains_source:
205
        show_source(item)
206
    if item.contains_build:
207
        for binary in item.getBinaryProperties():
208
            show_binary(binary)
209
545 by Colin Watson
Make all scripts pass pep8(1).
210
522 by Colin Watson
queue: show description of each item being fetched
211
def display_name(item):
212
    display = "%s/%s" % (item.display_name, item.display_version)
213
    if item.contains_build:
214
        display += " (%s)" % item.display_arches
215
    return display
216
502 by Colin Watson
queue: new script, soon to replace queue in LP
217
218
def info(options, args):
219
    """Show information on queue items."""
220
    items = queue_items(options, args)
221
    print("Listing %s/%s (%s) %s" %
222
          (options.distribution.name, options.suite, options.queue,
223
           len(items)))
224
    print(HEAD)
225
    for item in items:
226
        show_item(item)
227
    print(HEAD)
228
    print(FOOT_MARGIN + str(len(items)))
547 by Colin Watson
queue: more useful exit codes
229
    return 0
502 by Colin Watson
queue: new script, soon to replace queue in LP
230
231
698.1.2 by Iain Lane
Comment urls as it could be confusing
232
# Get librarian URLs for source_package_publishing_history or package_upload
233
# objects
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
234
def urls(options, item):
710 by Colin Watson
queue: make show-urls work for copies
235
    try:
236
        if item.contains_copy:
237
            archive = item.copy_source_archive
238
            item = archive.getPublishedSources(
239
                exact_match=True, source_name=item.package_name,
240
                version=item.package_version)
241
            if item:
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
242
                return urls(options, item[0])
710 by Colin Watson
queue: make show-urls work for copies
243
            else:
244
                print("Error: Can't find source package for copy")
245
                return []
246
    except AttributeError:
247
        # Not a package_upload
248
        pass
249
250
    ret = []
251
    try:
252
        ret.append(item.changes_file_url)
253
        ret.extend(item.customFileUrls())
724 by Stéphane Graber
PEP-8 fixes
254
    except AttributeError:  # Copies won't have this
710 by Colin Watson
queue: make show-urls work for copies
255
        ret.append(item.changesFileUrl())
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
256
    if options.source:
257
        ret.extend(item.sourceFileUrls())
258
    if options.binary:
259
        ret.extend(item.binaryFileUrls())
523 by Colin Watson
queue: add show-urls command
260
    # On staging we may get None URLs due to missing library files; filter
261
    # these out.
710 by Colin Watson
queue: make show-urls work for copies
262
    ret = list(filter(None, ret))
263
    return ret
523 by Colin Watson
queue: add show-urls command
264
265
502 by Colin Watson
queue: new script, soon to replace queue in LP
266
def fetch(options, args):
267
    """Fetch the contents of a queue item."""
547 by Colin Watson
queue: more useful exit codes
268
    ret = 1
502 by Colin Watson
queue: new script, soon to replace queue in LP
269
    items = queue_items(options, args)
270
    for item in items:
710 by Colin Watson
queue: make show-urls work for copies
271
        print("Fetching %s" % display_name(item))
272
        fetch_item(options, item)
273
        ret = 0
547 by Colin Watson
queue: more useful exit codes
274
    return ret
502 by Colin Watson
queue: new script, soon to replace queue in LP
275
724 by Stéphane Graber
PEP-8 fixes
276
698.1.1 by Iain Lane
Extend 'queue fetch' to work for copies too.
277
def fetch_item(options, item):
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
278
    for url in urls(options, item):
698.1.1 by Iain Lane
Extend 'queue fetch' to work for copies too.
279
        path = urlsplit(url)[2]
280
        filename = unquote(path.split("/")[-1])
281
        exists = os.path.exists(filename)
282
        if options.overwrite or not exists:
706 by Colin Watson
queue: fix indentation
283
            print("Constructing %s (%s)" % (filename, url))
284
            urlretrieve(url, filename)
698.1.1 by Iain Lane
Extend 'queue fetch' to work for copies too.
285
        elif exists:
286
            print("Not overwriting existing %s with %s" %
287
                  (filename, url))
502 by Colin Watson
queue: new script, soon to replace queue in LP
288
724 by Stéphane Graber
PEP-8 fixes
289
523 by Colin Watson
queue: add show-urls command
290
def show_urls(options, args):
291
    """Show the URLs from which a queue item may be downloaded."""
292
    items = queue_items(options, args)
293
    for item in items:
711 by Colin Watson
queue: make fetch and show-urls honour --source and --binary options
294
        for url in urls(options, item):
523 by Colin Watson
queue: add show-urls command
295
            print(url)
547 by Colin Watson
queue: more useful exit codes
296
    return 0 if items else 1
523 by Colin Watson
queue: add show-urls command
297
298
502 by Colin Watson
queue: new script, soon to replace queue in LP
299
def accept(options, args):
300
    """Accept a queue item."""
301
    items = queue_items(options, args)
539 by Colin Watson
queue: when accepting/rejecting multiple items, do so in ID order
302
    for item in sorted(items, key=attrgetter("id")):
502 by Colin Watson
queue: new script, soon to replace queue in LP
303
        if options.dry_run:
522 by Colin Watson
queue: show description of each item being fetched
304
            print("Would accept %s" % display_name(item))
502 by Colin Watson
queue: new script, soon to replace queue in LP
305
        else:
522 by Colin Watson
queue: show description of each item being fetched
306
            print("Accepting %s" % display_name(item))
502 by Colin Watson
queue: new script, soon to replace queue in LP
307
            item.acceptFromQueue()
547 by Colin Watson
queue: more useful exit codes
308
    return 0 if items else 1
502 by Colin Watson
queue: new script, soon to replace queue in LP
309
310
311
def reject(options, args):
312
    """Reject a queue item."""
313
    items = queue_items(options, args)
539 by Colin Watson
queue: when accepting/rejecting multiple items, do so in ID order
314
    for item in sorted(items, key=attrgetter("id")):
502 by Colin Watson
queue: new script, soon to replace queue in LP
315
        if options.dry_run:
522 by Colin Watson
queue: show description of each item being fetched
316
            print("Would reject %s" % display_name(item))
502 by Colin Watson
queue: new script, soon to replace queue in LP
317
        else:
522 by Colin Watson
queue: show description of each item being fetched
318
            print("Rejecting %s" % display_name(item))
718 by Adam Conrad
Require a rejection comment in the queue tool
319
            item.rejectFromQueue(comment=options.reject_comment)
547 by Colin Watson
queue: more useful exit codes
320
    return 0 if items else 1
502 by Colin Watson
queue: new script, soon to replace queue in LP
321
322
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
323
def override_source(options, item):
324
    """Override properties of source packages in a queue item."""
502 by Colin Watson
queue: new script, soon to replace queue in LP
325
    kwargs = {}
326
    if options.component:
327
        kwargs["new_component"] = options.component
328
    if options.section:
329
        kwargs["new_section"] = options.section
330
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
331
    print("Overriding %s_%s (%s/%s)" % (
332
        item.package_name, item.package_version,
333
        item.component_name, item.section_name))
334
    item.overrideSource(**kwargs)
335
    show_item(options.launchpad.load(item.self_link))
336
    return set((item.package_name,))
337
338
339
def override_binary(options, args, item):
340
    """Override properties of binary packages in a queue item."""
341
    overridden = set()
342
    changes = []
343
    show_binaries = []
344
    for binary in item.getBinaryProperties():
345
        if binary["name"] in args:
346
            overridden.add(binary["name"])
347
            print("Overriding %s_%s (%s/%s/%s)" % (
348
                binary["name"], binary["version"],
349
                binary["component"], binary["section"], binary["priority"]))
350
            change = {"name": binary["name"]}
351
            if options.component is not None:
352
                change["component"] = options.component
353
            if options.section is not None:
354
                change["section"] = options.section
355
            if options.priority is not None:
356
                change["priority"] = options.priority
357
            changes.append(change)
509 by Colin Watson
queue: fix display of overridden binaries after applying overrides
358
            show_binaries.append(binary["name"])
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
359
    if changes:
360
        item.overrideBinaries(changes=changes)
361
    if show_binaries:
362
        show_item_main(item)
509 by Colin Watson
queue: fix display of overridden binaries after applying overrides
363
        for binary in item.getBinaryProperties():
364
            if binary["name"] in show_binaries:
365
                show_binary(binary)
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
366
    return overridden
367
368
369
def override(options, args):
370
    """Override properties of packages in the queue.
371
372
    You may override the component (-c) or the section (-x).  In the case of
373
    binary packages, you may also override the priority (-p).
374
    """
375
    overridden = set()
502 by Colin Watson
queue: new script, soon to replace queue in LP
376
    items = queue_items(options, args)
377
    for item in items:
378
        if item.contains_source or item.contains_copy:
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
379
            overridden.update(override_source(options, item))
502 by Colin Watson
queue: new script, soon to replace queue in LP
380
        if item.contains_build:
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
381
            overridden.update(override_binary(options, args, item))
502 by Colin Watson
queue: new script, soon to replace queue in LP
382
    not_overridden = set(args) - overridden
383
    if not_overridden:
384
        print("No matches for %s" % ",".join(sorted(not_overridden)))
547 by Colin Watson
queue: more useful exit codes
385
        return 1
386
    else:
387
        return 0
502 by Colin Watson
queue: new script, soon to replace queue in LP
388
389
390
def report(options, args):
391
    """Show a report on the sizes of available queues."""
392
    print("Report for %s/%s" % (options.distribution.name, options.suite))
393
    for queue_name in queue_names:
394
        items = options.series.getPackageUploads(
577 by Colin Watson
queue: add --ppa, --ppa-name, and -j/--partner options
395
            archive=options.archive, pocket=options.pocket, status=queue_name)
502 by Colin Watson
queue: new script, soon to replace queue in LP
396
        print(" %s -> %s entries" % (queue_name, len(items)))
547 by Colin Watson
queue: more useful exit codes
397
    return 0
502 by Colin Watson
queue: new script, soon to replace queue in LP
398
399
400
queue_actions = {
401
    'info': info,
402
    'fetch': fetch,
523 by Colin Watson
queue: add show-urls command
403
    'show-urls': show_urls,
502 by Colin Watson
queue: new script, soon to replace queue in LP
404
    'accept': accept,
405
    'reject': reject,
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
406
    'override': override,
502 by Colin Watson
queue: new script, soon to replace queue in LP
407
    'report': report,
677 by Colin Watson
make all scripts pass current stricter pep8(1) in raring
408
}
502 by Colin Watson
queue: new script, soon to replace queue in LP
409
410
411
def main():
412
    parser = OptionParser(
413
        usage="usage: %prog [options] ACTION [...]",
414
        description=(
523 by Colin Watson
queue: add show-urls command
415
            "ACTION may be one of info, fetch, show-urls, accept, reject, "
969.1.3 by William Grant
Document archive reference syntax on scripts that take one.
416
            "override, or report."),
417
        epilog=lputils.ARCHIVE_REFERENCE_DESCRIPTION)
502 by Colin Watson
queue: new script, soon to replace queue in LP
418
    parser.add_option(
419
        "-l", "--launchpad", dest="launchpad_instance", default="production")
871.1.14 by William Grant
Fix queue --archive's help.
420
    parser.add_option("-A", "--archive", help="look in ARCHIVE")
502 by Colin Watson
queue: new script, soon to replace queue in LP
421
    parser.add_option(
969.1.2 by William Grant
Move archive and suite options next to each other.
422
        "-s", "--suite", dest="suite", metavar="SUITE",
423
        help="look in suite SUITE")
424
    parser.add_option(
502 by Colin Watson
queue: new script, soon to replace queue in LP
425
        "-Q", "--queue", dest="queue", metavar="QUEUE", default="new",
426
        help="consider packages in QUEUE")
427
    parser.add_option(
428
        "-n", "--dry-run", dest="dry_run", default=False, action="store_true",
429
        help="don't make any modifications")
430
    parser.add_option(
431
        "-e", "--exact-match", dest="exact_match",
679 by Colin Watson
queue: switch default for -e/--exact-match to True (and add -E/--no-exact-match) now that LP #33700 is fixed
432
        default=True, action="store_true",
502 by Colin Watson
queue: new script, soon to replace queue in LP
433
        help="treat name filter as an exact match")
434
    parser.add_option(
679 by Colin Watson
queue: switch default for -e/--exact-match to True (and add -E/--no-exact-match) now that LP #33700 is fixed
435
        "-E", "--no-exact-match", dest="exact_match", action="store_false",
436
        help="treat name filter as a prefix match")
437
    parser.add_option(
502 by Colin Watson
queue: new script, soon to replace queue in LP
438
        "-c", "--component", dest="component", metavar="COMPONENT",
439
        help="when overriding, move package to COMPONENT")
440
    parser.add_option(
441
        "-x", "--section", dest="section", metavar="SECTION",
442
        help="when overriding, move package to SECTION")
443
    parser.add_option(
444
        "-p", "--priority", dest="priority", metavar="PRIORITY",
445
        help="when overriding, move package to PRIORITY")
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
446
    parser.add_option(
447
        "--source", dest="source", default=False, action="store_true",
448
        help="only operate on source packages")
449
    parser.add_option(
450
        "--binary", dest="binary", default=False, action="store_true",
451
        help="only operate on binary packages")
625 by Colin Watson
queue fetch: don't overwrite existing files by default; add --overwrite option to restore former behaviour
452
    parser.add_option(
453
        "--overwrite", dest="overwrite", default=False, action="store_true",
454
        help="when fetching, overwrite existing files")
718 by Adam Conrad
Require a rejection comment in the queue tool
455
    parser.add_option("-m", "--reject-comment", help="rejection comment")
969.1.1 by William Grant
Hide deprecated distro/owner/name/partner archive selection options. Use archive references instead.
456
457
    # Deprecated in favour of -A.
458
    parser.add_option(
459
        "-d", "--distribution", dest="distribution", default="ubuntu",
460
        help=SUPPRESS_HELP)
461
    parser.add_option("--ppa", help=SUPPRESS_HELP)
462
    parser.add_option("--ppa-name", help=SUPPRESS_HELP)
871.1.9 by William Grant
Bestow the power of -A upon queue and remove-package
463
    parser.add_option(
464
        "-j", "--partner", default=False, action="store_true",
969.1.1 by William Grant
Hide deprecated distro/owner/name/partner archive selection options. Use archive references instead.
465
        help=SUPPRESS_HELP)
502 by Colin Watson
queue: new script, soon to replace queue in LP
466
    options, args = parser.parse_args()
467
468
    if not args:
469
        parser.error("must select an action")
470
    action = args.pop(0)
471
    try:
472
        queue_action = queue_actions[action]
473
    except KeyError:
474
        parser.error("unknown action: %s" % action)
475
718 by Adam Conrad
Require a rejection comment in the queue tool
476
    if action == "reject" and options.reject_comment is None:
477
        parser.error("rejections must supply a rejection comment")
478
502 by Colin Watson
queue: new script, soon to replace queue in LP
479
    options.launchpad = Launchpad.login_with(
480
        CONSUMER_KEY, options.launchpad_instance, version="devel")
481
482
    options.queue = options.queue.title()
646 by Colin Watson
queue: look in -proposed by default
483
    lputils.setup_location(options, default_pocket="Proposed")
502 by Colin Watson
queue: new script, soon to replace queue in LP
484
504 by Colin Watson
queue: simplify and generalise source vs. binary package selection
485
    if not options.source and not options.binary:
486
        options.source = True
487
        options.binary = True
488
540 by Scott Kitterman
queue: Catch ValueError and exit instead of just dieing with a traceback.
489
    try:
547 by Colin Watson
queue: more useful exit codes
490
        sys.exit(queue_action(options, args))
540 by Scott Kitterman
queue: Catch ValueError and exit instead of just dieing with a traceback.
491
    except ValueError as x:
492
        print(x)
493
        sys.exit(1)
502 by Colin Watson
queue: new script, soon to replace queue in LP
494
495
496
if __name__ == '__main__':
497
    main()