From 677e1b8e4ea57fd67eb432812f8a7f6cf406d862 Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Sun, 27 Nov 2011 22:14:05 +0100 Subject: [PATCH 01/29] requestsync: Give user option to retry in case of temporary error (LP: #850360) --- debian/changelog | 3 ++- ubuntutools/requestsync/mail.py | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/debian/changelog b/debian/changelog index 8aeb5f3..b8041d7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -18,8 +18,9 @@ ubuntu-dev-tools (0.137) UNRELEASED; urgency=low [ Andreas Moog ] * sponsor-patch: Check permission to unsubscribe sponsors-team (LP: #896884) + * requestsync: Give user option to retry in case of temporary error (LP: #850360) - -- Andreas Moog Sun, 27 Nov 2011 16:47:05 +0100 + -- Andreas Moog Sun, 27 Nov 2011 22:13:22 +0100 ubuntu-dev-tools (0.136) unstable; urgency=low diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index c6607d6..4708b7a 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -163,13 +163,20 @@ Content-Type: text/plain; charset=UTF-8 confirmation_prompt() # connect to the server - try: - Logger.info('Connecting to %s:%s ...', mailserver_host, mailserver_port) - s = smtplib.SMTP(mailserver_host, mailserver_port) - except socket.error, s: - Logger.error('Could not connect to %s:%s: %s (%i)', - mailserver_host, mailserver_port, s[1], s[0]) - return + while True: + try: + Logger.info('Connecting to %s:%s ...', mailserver_host, mailserver_port) + s = smtplib.SMTP(mailserver_host, mailserver_port) + break + except socket.error, s: + Logger.error('Could not connect to %s:%s: %s (%i)', + mailserver_host, mailserver_port, s[1], s[0]) + return + except smtplib.SMTPConnectError, s: + Logger.error('Could not connect to %s:%s: %s (%i)', + mailserver_host, mailserver_port, s[1], s[0]) + if s[0] == 421: + confirmation_prompt(message="This is a temporary error, press [Enter] to retry. Press [Ctrl-C] to abort now.") if mailserver_user and mailserver_pass: try: From d9c00752c063a4c6740fafc99536c166c519f1b1 Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Mon, 28 Nov 2011 19:53:23 +0100 Subject: [PATCH 02/29] Wrap long line --- ubuntutools/requestsync/mail.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 4708b7a..88a4bef 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -175,8 +175,9 @@ Content-Type: text/plain; charset=UTF-8 except smtplib.SMTPConnectError, s: Logger.error('Could not connect to %s:%s: %s (%i)', mailserver_host, mailserver_port, s[1], s[0]) - if s[0] == 421: - confirmation_prompt(message="This is a temporary error, press [Enter] to retry. Press [Ctrl-C] to abort now.") + if s.smtp_code == 421: + confirmation_prompt(message='This is a temporary error, press' + '[Enter] to retry. Press [Ctrl-C] to abort now.') if mailserver_user and mailserver_pass: try: From 10e9b18ca7fcde4549d606810ebdd16cd2d5bd2f Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Mon, 28 Nov 2011 20:50:28 +0100 Subject: [PATCH 03/29] Save a temporary file in case sending fails --- ubuntutools/requestsync/mail.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 88a4bef..a95f911 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -162,6 +162,16 @@ Content-Type: text/plain; charset=UTF-8 print 'The final report is:\n%s' % mail confirmation_prompt() + # save mail in temporary file + f=open("/tmp/requestsync-" + srcpkg,"w") + f.write(mail) + f.close() + + print ''' +The e-mail has been saved in %s and will be deleted +after succesful transmission +''' % f.name + # connect to the server while True: try: @@ -176,8 +186,8 @@ Content-Type: text/plain; charset=UTF-8 Logger.error('Could not connect to %s:%s: %s (%i)', mailserver_host, mailserver_port, s[1], s[0]) if s.smtp_code == 421: - confirmation_prompt(message='This is a temporary error, press' - '[Enter] to retry. Press [Ctrl-C] to abort now.') + confirmation_prompt(message='This is a temporary error, press ' + '[Enter] to retry. Press [Ctrl-C] to abort now.') if mailserver_user and mailserver_pass: try: @@ -192,6 +202,10 @@ Content-Type: text/plain; charset=UTF-8 s.quit() return - s.sendmail(myemailaddr, to, mail.encode('utf-8')) - s.quit() - Logger.normal('Sync request mailed.') + try: + s.sendmail(myemailaddr, to, mail.encode('utf-8')) + s.quit() + os.remove(f.name) + Logger.normal('Sync request mailed.') + except: + Logger.error('Unknown error while sending the mail.') From 0e3a831df988b68837781bc7784594956f576496 Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Tue, 29 Nov 2011 20:20:25 +0100 Subject: [PATCH 04/29] Use Logger.normal --- ubuntutools/requestsync/mail.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index a95f911..7ce536b 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -167,10 +167,8 @@ Content-Type: text/plain; charset=UTF-8 f.write(mail) f.close() - print ''' -The e-mail has been saved in %s and will be deleted -after succesful transmission -''' % f.name + Logger.normal('The e-mail has been saved in %s and will be deleted ' + 'after succesful transmission', f.name) # connect to the server while True: From e556fdae0057bbf6a81b890431c1887f1dff0f25 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Fri, 2 Dec 2011 18:59:46 +0200 Subject: [PATCH 05/29] New Tool: who-can-upload (LP: #876554) --- debian/changelog | 1 + ubuntutools/lp/lpapicache.py | 77 ++++++++++++++++++++++++++-- who-can-upload | 97 ++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 5 deletions(-) create mode 100755 who-can-upload diff --git a/debian/changelog b/debian/changelog index b0db2d1..0bcc159 100644 --- a/debian/changelog +++ b/debian/changelog @@ -18,6 +18,7 @@ ubuntu-dev-tools (0.137) UNRELEASED; urgency=low * mk-sbuild, pbuilder-dist, ubuntu-build: Add armhf. * pull-debian-source, pull-lp-source: Resolve the source package (via DDE), if a binary package was requested (LP: #617349) + * New Tool: who-can-upload (LP: #876554) [ Andreas Moog ] * sponsor-patch: Check permission to unsubscribe sponsors-team (LP: #896884) diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index f284d09..dedda24 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -278,11 +278,11 @@ class Archive(BaseWrapper): resource_type = 'archive' def __init__(self, *args): - # Don't share between different Archives - if '_binpkgs' not in self.__dict__: - self._binpkgs = dict() - if '_srcpkgs' not in self.__dict__: - self._srcpkgs = dict() + self._binpkgs = {} + self._srcpkgs = {} + self._pkg_uploaders = {} + self._pkgset_uploaders = {} + self._component_uploaders = {} def getSourcePackage(self, name, series=None, pocket=None): ''' @@ -400,6 +400,40 @@ class Archive(BaseWrapper): include_binaries=include_binaries ) + def getUploadersForComponent(self, component_name): + '''Get the list of PersonTeams who can upload packages in the + specified component. + ''' + if component_name not in self._component_uploaders: + self._component_uploaders[component_name] = sorted(set( + PersonTeam(permission.person_link) + for permission in self._lpobject.getUploadersForComponent( + component_name=component_name + ))) + return self._component_uploaders[component_name] + + def getUploadersForPackage(self, source_package_name): + '''Get the list of PersonTeams who can upload source_package_name)''' + if source_package_name not in self._pkg_uploaders: + self._pkg_uploaders[source_package_name] = sorted(set( + PersonTeam(permission.person_link) + for permission in self._lpobject.getUploadersForPackage( + source_package_name=source_package_name + ))) + return self._pkg_uploaders[source_package_name] + + def getUploadersForPackageset(self, packageset, direct_permissions=False): + '''Get the list of PersonTeams who can upload packages in packageset''' + key = (packageset, direct_permissions) + if key not in self._pkgset_uploaders: + self._pkgset_uploaders[key] = sorted(set( + PersonTeam(permission.person_link) + for permission in self._lpobject.getUploadersForPackageset( + packageset=packageset._lpobject, + direct_permissions=direct_permissions, + ))) + return self._pkgset_uploaders[key] + class SourcePackagePublishingHistory(BaseWrapper): ''' @@ -703,3 +737,36 @@ class DistributionSourcePackage(BaseWrapper): Caching class for distribution_source_package objects. ''' resource_type = 'distribution_source_package' + + +class Packageset(BaseWrapper): + ''' + Caching class for packageset objects. + ''' + resource_type = 'packageset' + _lp_packagesets = None + _source_sets = {} + + @classmethod + def setsIncludingSource(cls, sourcepackagename, distroseries=None, + direct_inclusion=False): + '''Get the package sets including sourcepackagename''' + + if cls._lp_packagesets is None: + cls._lp_packagesets = Launchpad.packagesets + + key = (sourcepackagename, distroseries, direct_inclusion) + if key not in cls._source_sets: + params = { + 'sourcepackagename': sourcepackagename, + 'direct_inclusion': direct_inclusion, + } + if distroseries is not None: + params['distroseries'] = distroseries._lpobject + + cls._source_sets[key] = [ + Packageset(packageset) for packageset + in cls._lp_packagesets.setsIncludingSource(**params) + ] + + return cls._source_sets[key] diff --git a/who-can-upload b/who-can-upload new file mode 100755 index 0000000..04ea9f5 --- /dev/null +++ b/who-can-upload @@ -0,0 +1,97 @@ +#!/usr/bin/python +# +# Copyright (C) 2011, Stefano Rivera +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import optparse + +from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam, + Packageset, + SeriesNotFoundException) + + +def main(): + parser = optparse.OptionParser('%prog [options] package') + parser.add_option('-r', '--release', default=None, metavar='RELEASE', + help='Use RELEASE, rather than the current development ' + 'release') + parser.add_option('-t', '--list-team-members', + default=False, action='store_true', + help='List all team members of teams with upload rights') + options, args = parser.parse_args() + + if len(args) != 1: + parser.error("One (and only one) package must be specified") + package = args[0] + + # Need to be logged in to see uploaders: + Launchpad.login() + + ubuntu = Distribution('ubuntu') + archive = ubuntu.getArchive() + if options.release is None: + series = ubuntu.getDevelopmentSeries() + else: + try: + series = ubuntu.getSeries(options.release) + except SeriesNotFoundException, e: + parser.error(str(e)) + + spph = archive.getSourcePackage(package) + component = spph.getComponent() + component_uploader = archive.getUploadersForComponent( + component_name=component)[0] + print "Component (%s)" % component + print "============" + ("=" * len(component)) + print_uploaders([component_uploader], options.list_team_members) + + packagesets = sorted(Packageset.setsIncludingSource(distroseries=series, + sourcepackagename=package)) + if packagesets: + print + print "Packagesets" + print "===========" + for packageset in packagesets: + print + print "%s:" % packageset.name + print_uploaders(archive.getUploadersForPackageset( + packageset=packageset), options.list_team_members) + + ppu_uploaders = archive.getUploadersForPackage(source_package_name=package) + if ppu_uploaders: + print + print "Per-Package-Uploaders" + print "=====================" + print + print_uploaders(ppu_uploaders, options.list_team_members) + + print + if PersonTeam.me.canUploadPackage(archive, series, package, component): + print "You can upload this package" + else: + print "You can not upload this package, yourself." + print ("But you can still contribute to it via the sponsorship " + "process: https://wiki.ubuntu.com/SponsorshipProcess") + + +def print_uploaders(uploaders, expand_teams=False, prefix=''): + for uploader in sorted(uploaders, key=lambda p: p.display_name): + print ("%s* %s (%s)%s" + % (prefix, uploader.display_name, uploader.name, + ' [team]' if uploader.is_team else '')) + if expand_teams and uploader.is_team: + print_uploaders(uploader.participants, True, prefix=prefix + ' ') + +if __name__ == '__main__': + main() From 9199747fc35cc35b4c69b14e1adc5370e3ee7a2b Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Fri, 2 Dec 2011 20:06:57 +0100 Subject: [PATCH 06/29] Space after comma --- ubuntutools/requestsync/mail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 7ce536b..2d3cac2 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -163,7 +163,7 @@ Content-Type: text/plain; charset=UTF-8 confirmation_prompt() # save mail in temporary file - f=open("/tmp/requestsync-" + srcpkg,"w") + f=open("/tmp/requestsync-" + srcpkg, "w") f.write(mail) f.close() From 12030d99e9818366a8258dcd19ad7123dac29c77 Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Sat, 3 Dec 2011 11:12:11 +0100 Subject: [PATCH 07/29] Use bugtitle as temporary filename --- ubuntutools/requestsync/mail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 2d3cac2..748d216 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -163,7 +163,7 @@ Content-Type: text/plain; charset=UTF-8 confirmation_prompt() # save mail in temporary file - f=open("/tmp/requestsync-" + srcpkg, "w") + f=open("/tmp/requestsync-" + bugtitle.replace(" ","_"), "w") f.write(mail) f.close() From d18a35c449ddfb017a5f4fd25ac4e6bc41b8d11a Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Sat, 3 Dec 2011 11:57:18 +0100 Subject: [PATCH 08/29] Also allow retry if recipient got rejected --- ubuntutools/requestsync/mail.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 748d216..dce0cac 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -200,10 +200,18 @@ Content-Type: text/plain; charset=UTF-8 s.quit() return - try: - s.sendmail(myemailaddr, to, mail.encode('utf-8')) - s.quit() - os.remove(f.name) - Logger.normal('Sync request mailed.') - except: - Logger.error('Unknown error while sending the mail.') + while True: + try: + s.sendmail(myemailaddr, to, mail.encode('utf-8')) + s.quit() + os.remove(f.name) + Logger.normal('Sync request mailed.') + break + except smtplib.SMTPRecipientsRefused, smtperror: + smtp_code, smtp_message = smtperror.recipients[to] + Logger.error('Error while sending: %i, %s', smtp_code, smtp_message) + if smtp_code == 450: + confirmation_prompt(message='This is a temporary error, press ' + '[Enter] to retry. Press [Ctrl-C] to abort now.') + else: + return From 32a85dc1729eceee27561531cbb680ae585e7cb8 Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Sat, 3 Dec 2011 18:01:55 +0100 Subject: [PATCH 09/29] Add a exception for disconnected server --- ubuntutools/requestsync/mail.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index dce0cac..70801f3 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -215,3 +215,6 @@ Content-Type: text/plain; charset=UTF-8 '[Enter] to retry. Press [Ctrl-C] to abort now.') else: return + except smtplib.SMTPServerDisconnected: + Logger.error('Server disconnected while sending the mail.') + return From 8a6502aaa49478e56fe867917d7edc293efd3329 Mon Sep 17 00:00:00 2001 From: Andreas Moog Date: Sat, 3 Dec 2011 18:09:49 +0100 Subject: [PATCH 10/29] Use regex to filter unwanted characters in filename --- ubuntutools/requestsync/mail.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 70801f3..a1684ce 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -21,6 +21,7 @@ # of the GNU General Public License license. import os +import re import sys import smtplib import socket @@ -163,7 +164,7 @@ Content-Type: text/plain; charset=UTF-8 confirmation_prompt() # save mail in temporary file - f=open("/tmp/requestsync-" + bugtitle.replace(" ","_"), "w") + f=open("/tmp/requestsync-" + re.sub("[^a-zA-Z0-9_\-]","",bugtitle.replace(" ","_")), "w") f.write(mail) f.close() From 899d1b5361900f3560568d2827d27e4b229627b4 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 21:57:11 +0200 Subject: [PATCH 11/29] Use tempfile --- ubuntutools/requestsync/mail.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index a1684ce..723ee15 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -25,6 +25,7 @@ import re import sys import smtplib import socket +import tempfile from debian.changelog import Changelog, Version from devscripts.logger import Logger @@ -164,12 +165,14 @@ Content-Type: text/plain; charset=UTF-8 confirmation_prompt() # save mail in temporary file - f=open("/tmp/requestsync-" + re.sub("[^a-zA-Z0-9_\-]","",bugtitle.replace(" ","_")), "w") - f.write(mail) - f.close() + backup = tempfile.NamedTemporaryFile(mode='w', delete=False, + prefix='requestsync-' + re.sub(r'[^a-zA-Z0-9_-]', '', + bugtitle.replace(' ', '_'))) + with backup: + backup.write(mail) Logger.normal('The e-mail has been saved in %s and will be deleted ' - 'after succesful transmission', f.name) + 'after succesful transmission', backup.name) # connect to the server while True: @@ -205,7 +208,7 @@ Content-Type: text/plain; charset=UTF-8 try: s.sendmail(myemailaddr, to, mail.encode('utf-8')) s.quit() - os.remove(f.name) + os.remove(backup.name) Logger.normal('Sync request mailed.') break except smtplib.SMTPRecipientsRefused, smtperror: From 9442e2ea30f898812743f4b13a46e458067b3195 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 22:06:49 +0200 Subject: [PATCH 12/29] Catch response exceptions in the DATA phase --- ubuntutools/requestsync/mail.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 723ee15..769af10 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -219,6 +219,10 @@ Content-Type: text/plain; charset=UTF-8 '[Enter] to retry. Press [Ctrl-C] to abort now.') else: return + except smtplib.SMTPResponseException, e: + Logger.error('Error while sending: %i, %s', + e.smtp_code, e.smtp_error) + return except smtplib.SMTPServerDisconnected: Logger.error('Server disconnected while sending the mail.') return From e68d3a699dc31b1da659f583149379aac2add677 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 22:07:18 +0200 Subject: [PATCH 13/29] Bump logging level of 'connecting' message --- ubuntutools/requestsync/mail.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 769af10..1d94876 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -177,7 +177,8 @@ Content-Type: text/plain; charset=UTF-8 # connect to the server while True: try: - Logger.info('Connecting to %s:%s ...', mailserver_host, mailserver_port) + Logger.normal('Connecting to %s:%s ...', mailserver_host, + mailserver_port) s = smtplib.SMTP(mailserver_host, mailserver_port) break except socket.error, s: From 89192f4e69b053f1e60780d0530d0812eb4f3406 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 22:37:55 +0200 Subject: [PATCH 14/29] UI tweaks --- who-can-upload | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/who-can-upload b/who-can-upload index 04ea9f5..a0a9f23 100755 --- a/who-can-upload +++ b/who-can-upload @@ -52,6 +52,8 @@ def main(): component = spph.getComponent() component_uploader = archive.getUploadersForComponent( component_name=component)[0] + print "All upload permissions for %s:" % package + print print "Component (%s)" % component print "============" + ("=" * len(component)) print_uploaders([component_uploader], options.list_team_members) @@ -86,6 +88,11 @@ def main(): def print_uploaders(uploaders, expand_teams=False, prefix=''): + """Given a list of uploaders, pretty-print them all + Each line is prefixed with prefix. + If expand_teams is set, recurse, adding more spaces to prefix on each + recursion. + """ for uploader in sorted(uploaders, key=lambda p: p.display_name): print ("%s* %s (%s)%s" % (prefix, uploader.display_name, uploader.name, @@ -93,5 +100,6 @@ def print_uploaders(uploaders, expand_teams=False, prefix=''): if expand_teams and uploader.is_team: print_uploaders(uploader.participants, True, prefix=prefix + ' ') + if __name__ == '__main__': main() From 3ea5038905ae3a773ffc01a36ae5333017f0c238 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 22:44:13 +0200 Subject: [PATCH 15/29] PEP8 and docstring improments --- ubuntutools/lp/lpapicache.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index dedda24..5906c48 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -54,6 +54,7 @@ __all__ = [ _POCKETS = ('Release', 'Security', 'Updates', 'Proposed', 'Backports') + class _Launchpad(object): '''Singleton for LP API access.''' @@ -116,7 +117,7 @@ class BaseWrapper(object): A base class from which other wrapper classes are derived. ''' __metaclass__ = MetaWrapper - resource_type = None # it's a base class after all + resource_type = None # it's a base class after all def __new__(cls, data): if (isinstance(data, basestring) and @@ -403,6 +404,7 @@ class Archive(BaseWrapper): def getUploadersForComponent(self, component_name): '''Get the list of PersonTeams who can upload packages in the specified component. + [Note: the permission records, themselves, aren't exposed] ''' if component_name not in self._component_uploaders: self._component_uploaders[component_name] = sorted(set( @@ -413,7 +415,9 @@ class Archive(BaseWrapper): return self._component_uploaders[component_name] def getUploadersForPackage(self, source_package_name): - '''Get the list of PersonTeams who can upload source_package_name)''' + '''Get the list of PersonTeams who can upload source_package_name) + [Note: the permission records, themselves, aren't exposed] + ''' if source_package_name not in self._pkg_uploaders: self._pkg_uploaders[source_package_name] = sorted(set( PersonTeam(permission.person_link) @@ -423,7 +427,9 @@ class Archive(BaseWrapper): return self._pkg_uploaders[source_package_name] def getUploadersForPackageset(self, packageset, direct_permissions=False): - '''Get the list of PersonTeams who can upload packages in packageset''' + '''Get the list of PersonTeams who can upload packages in packageset + [Note: the permission records, themselves, aren't exposed] + ''' key = (packageset, direct_permissions) if key not in self._pkgset_uploaders: self._pkgset_uploaders[key] = sorted(set( @@ -619,6 +625,7 @@ class MetaPersonTeam(MetaWrapper): raise return cls._me + class PersonTeam(BaseWrapper): ''' Wrapper class around a LP person or team object. @@ -721,7 +728,7 @@ class Build(BaseWrapper): def rescore(self, score): if self.can_be_rescored: - self().rescore(score = score) + self().rescore(score=score) return True return False From 710aa8aa5a34bb4bc4f5d17e2e4048a00f653cac Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 23:26:12 +0200 Subject: [PATCH 16/29] Rename tool, and make output less verbose by default --- debian/changelog | 4 +- who-can-upload => upload-permission | 67 ++++++++++++++++++----------- 2 files changed, 43 insertions(+), 28 deletions(-) rename who-can-upload => upload-permission (63%) diff --git a/debian/changelog b/debian/changelog index 0bcc159..d4d8f1d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -18,11 +18,11 @@ ubuntu-dev-tools (0.137) UNRELEASED; urgency=low * mk-sbuild, pbuilder-dist, ubuntu-build: Add armhf. * pull-debian-source, pull-lp-source: Resolve the source package (via DDE), if a binary package was requested (LP: #617349) - * New Tool: who-can-upload (LP: #876554) + * New Tool: upload-permission: Query upload permissions (LP: #876554) [ Andreas Moog ] * sponsor-patch: Check permission to unsubscribe sponsors-team (LP: #896884) - * grep-merges: We already require a UTF-8 enabled terminal, so encode + * grep-merges: We already require a UTF-8 enabled terminal, so encode package and uploader name in UTF-8 (LP: #694388) -- Andreas Moog Wed, 30 Nov 2011 21:04:39 +0100 diff --git a/who-can-upload b/upload-permission similarity index 63% rename from who-can-upload rename to upload-permission index a0a9f23..b48018b 100755 --- a/who-can-upload +++ b/upload-permission @@ -15,6 +15,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import optparse +import sys from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam, Packageset, @@ -26,15 +27,22 @@ def main(): parser.add_option('-r', '--release', default=None, metavar='RELEASE', help='Use RELEASE, rather than the current development ' 'release') + parser.add_option('-a', '--list-uploaders', + default=False, action='store_true', + help='List all the people/teams with upload rights') parser.add_option('-t', '--list-team-members', default=False, action='store_true', - help='List all team members of teams with upload rights') + help='List all team members of teams with upload rights ' + '(implies --list-uploaders)') options, args = parser.parse_args() if len(args) != 1: parser.error("One (and only one) package must be specified") package = args[0] + if options.list_team_members: + options.list_uploaders = True + # Need to be logged in to see uploaders: Launchpad.login() @@ -50,41 +58,48 @@ def main(): spph = archive.getSourcePackage(package) component = spph.getComponent() - component_uploader = archive.getUploadersForComponent( - component_name=component)[0] - print "All upload permissions for %s:" % package - print - print "Component (%s)" % component - print "============" + ("=" * len(component)) - print_uploaders([component_uploader], options.list_team_members) - - packagesets = sorted(Packageset.setsIncludingSource(distroseries=series, - sourcepackagename=package)) - if packagesets: + if options.list_uploaders: + component_uploader = archive.getUploadersForComponent( + component_name=component)[0] + print "All upload permissions for %s:" % package print - print "Packagesets" - print "===========" - for packageset in packagesets: + print "Component (%s)" % component + print "============" + ("=" * len(component)) + print_uploaders([component_uploader], options.list_team_members) + + packagesets = sorted(Packageset.setsIncludingSource( + distroseries=series, + sourcepackagename=package)) + if packagesets: print - print "%s:" % packageset.name - print_uploaders(archive.getUploadersForPackageset( - packageset=packageset), options.list_team_members) + print "Packagesets" + print "===========" + for packageset in packagesets: + print + print "%s:" % packageset.name + print_uploaders(archive.getUploadersForPackageset( + packageset=packageset), options.list_team_members) - ppu_uploaders = archive.getUploadersForPackage(source_package_name=package) - if ppu_uploaders: + ppu_uploaders = archive.getUploadersForPackage( + source_package_name=package) + if ppu_uploaders: + print + print "Per-Package-Uploaders" + print "=====================" + print + print_uploaders(ppu_uploaders, options.list_team_members) print - print "Per-Package-Uploaders" - print "=====================" - print - print_uploaders(ppu_uploaders, options.list_team_members) - print if PersonTeam.me.canUploadPackage(archive, series, package, component): - print "You can upload this package" + print "You can upload this package." else: print "You can not upload this package, yourself." print ("But you can still contribute to it via the sponsorship " "process: https://wiki.ubuntu.com/SponsorshipProcess") + if not options.list_uploaders: + print ("To see who has the necessary upload rights, " + "use the --list-uploaders option.") + sys.exit(1) def print_uploaders(uploaders, expand_teams=False, prefix=''): From 6ef82feac4ce3bfee1cd69bcba671b8b0c1d416f Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 23:36:10 +0200 Subject: [PATCH 17/29] Manpage and other accoutrements --- debian/control | 1 + debian/copyright | 2 ++ doc/upload-permission.1 | 60 +++++++++++++++++++++++++++++++++++++++++ setup.py | 1 + 4 files changed, 64 insertions(+) create mode 100644 doc/upload-permission.1 diff --git a/debian/control b/debian/control index e15fd97..19cec22 100644 --- a/debian/control +++ b/debian/control @@ -106,3 +106,4 @@ Description: useful tools for Ubuntu developers command line. - ubuntu-iso - output information of an Ubuntu ISO image. - update-maintainer - script to update maintainer field in ubuntu packages. + - upload-permission - query / list the upload permissions for a package. diff --git a/debian/copyright b/debian/copyright index d3963b3..5933bf2 100644 --- a/debian/copyright +++ b/debian/copyright @@ -151,6 +151,7 @@ Files: doc/pull-debian-debdiff.1 doc/sponsor-patch.1 doc/ubuntu-dev-tools.5 doc/update-maintainer.1 + doc/upload-permission.1 pull-debian-debdiff pull-debian-source requestbackport @@ -166,6 +167,7 @@ Files: doc/pull-debian-debdiff.1 ubuntutools/test/* ubuntutools/update_maintainer.py update-maintainer + upload-permission Copyright: 2009-2011, Benjamin Drung 2010, Evan Broder 2008, Siegfried-Angel Gevatter Pujals diff --git a/doc/upload-permission.1 b/doc/upload-permission.1 new file mode 100644 index 0000000..742b95d --- /dev/null +++ b/doc/upload-permission.1 @@ -0,0 +1,60 @@ +.\" Copyright (C) 2011, Stefano Rivera +.\" +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +.\" OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +.\" PERFORMANCE OF THIS SOFTWARE. +.TH upload\-permission 1 "November 2011" ubuntu\-dev\-tools + +.SH NAME +upload\-permission \- Query upload rights and (optionally) list the +people and teams with upload rights for a package + +.SH SYNOPSIS +.B upload\-permission \fR[\fIoptions\fR] \fIpackage + +.SH DESCRIPTION +\fBupload\-permission\fR checks if the user has upload permissions for +\fIpackage\fR. +If the \fB\-\-list\-uploaders\fR option is provided, all the people and +teams that do have upload rights for \fIpackage\fR will be listed. + +.SH OPTIONS +.TP +\fB\-r\fR \fIRELEASE\fR, \fB\-\-release\fR=\fIRELEASE\fR +Query permissions in \fIRELEASE\fR. +Default: current development release. +.TP +\fB\-a\fR, \fB\-\-list\-uploaders\fR +List all the people and teams who have upload rights for \fIpackage\fR. +.TP +\fB\-t\fR, \fB\-\-list\-team\-members\fR +List all the members of every team with rights. (Implies +\fB\-\-list\-uploaders\fR) +.TP +\fB\-h\fR, \fB\-\-help\fR +Display a help message and exit + +.SH EXIT STATUS +.TP +.B 0 +You have the necessary upload rights. +.TP +.B 1 +You don't have the necessary upload rights. +.TP +.B 2 +There was an error. + +.SH AUTHORS +\fBupload\-permission\fR and this manpage were written by Stefano Rivera +. +.PP +Both are released under the terms of the ISC License. diff --git a/setup.py b/setup.py index 36dd05a..92d9c96 100755 --- a/setup.py +++ b/setup.py @@ -42,6 +42,7 @@ scripts = ['404main', 'ubuntu-build', 'ubuntu-iso', 'update-maintainer', + 'upload-permission', ] if __name__ == '__main__': From 0d2d356ddb7a18dbe7ddb58606566b11c025b58e Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 23:50:11 +0200 Subject: [PATCH 18/29] Break up main() --- upload-permission | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/upload-permission b/upload-permission index b48018b..2b1437c 100755 --- a/upload-permission +++ b/upload-permission @@ -17,12 +17,15 @@ import optparse import sys +from devscripts.logger import Logger + from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam, Packageset, SeriesNotFoundException) -def main(): +def parse_arguments(): + '''Parse arguments and return (options, package)''' parser = optparse.OptionParser('%prog [options] package') parser.add_option('-r', '--release', default=None, metavar='RELEASE', help='Use RELEASE, rather than the current development ' @@ -43,6 +46,12 @@ def main(): if options.list_team_members: options.list_uploaders = True + return (options, package) + + +def main(): + '''Query upload permissions''' + options, package = parse_arguments() # Need to be logged in to see uploaders: Launchpad.login() @@ -54,7 +63,8 @@ def main(): try: series = ubuntu.getSeries(options.release) except SeriesNotFoundException, e: - parser.error(str(e)) + Logger.error(str(e)) + sys.exit(2) spph = archive.getSourcePackage(package) component = spph.getComponent() From 58ee0de242533aa5fe9e7dc263fca12c86cb646e Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 3 Dec 2011 23:51:24 +0200 Subject: [PATCH 19/29] Catch PackageNotFoundException --- upload-permission | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/upload-permission b/upload-permission index 2b1437c..47e6350 100755 --- a/upload-permission +++ b/upload-permission @@ -20,7 +20,7 @@ import sys from devscripts.logger import Logger from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam, - Packageset, + Packageset, PackageNotFoundException, SeriesNotFoundException) @@ -66,7 +66,11 @@ def main(): Logger.error(str(e)) sys.exit(2) - spph = archive.getSourcePackage(package) + try: + spph = archive.getSourcePackage(package) + except PackageNotFoundException, e: + Logger.error(str(e)) + sys.exit(2) component = spph.getComponent() if options.list_uploaders: component_uploader = archive.getUploadersForComponent( From d420a25b947ab9554d980d5fec852944b5792a6e Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:08:08 +0200 Subject: [PATCH 20/29] Pocket awareness --- upload-permission | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/upload-permission b/upload-permission index 47e6350..0518572 100755 --- a/upload-permission +++ b/upload-permission @@ -22,6 +22,7 @@ from devscripts.logger import Logger from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam, Packageset, PackageNotFoundException, SeriesNotFoundException) +from ubuntutools.misc import split_release_pocket def parse_arguments(): @@ -59,9 +60,11 @@ def main(): archive = ubuntu.getArchive() if options.release is None: series = ubuntu.getDevelopmentSeries() + pocket = 'Release' else: try: - series = ubuntu.getSeries(options.release) + release, pocket = split_release_pocket(options.release) + series = ubuntu.getSeries(release) except SeriesNotFoundException, e: Logger.error(str(e)) sys.exit(2) @@ -104,15 +107,21 @@ def main(): print_uploaders(ppu_uploaders, options.list_team_members) print - if PersonTeam.me.canUploadPackage(archive, series, package, component): - print "You can upload this package." + if PersonTeam.me.canUploadPackage(archive, series, package, component, + pocket): + print "You can upload %s." % package else: - print "You can not upload this package, yourself." + print "You can not upload %s, yourself." % package print ("But you can still contribute to it via the sponsorship " "process: https://wiki.ubuntu.com/SponsorshipProcess") if not options.list_uploaders: print ("To see who has the necessary upload rights, " "use the --list-uploaders option.") + if (series.status in ('Current Stable Release', 'Supported', 'Obsolete') + and pocket == 'Release'): + print ("%s is in the '%s' state. " + "You may want to query the %s-proposed pocket." + % (release, series.status, release)) sys.exit(1) From 3a403daf6b0e4001c0cc09a5b5949c95367c3b99 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:18:23 +0200 Subject: [PATCH 21/29] Tweak minimal output --- upload-permission | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/upload-permission b/upload-permission index 0518572..e29b3ec 100755 --- a/upload-permission +++ b/upload-permission @@ -109,19 +109,21 @@ def main(): if PersonTeam.me.canUploadPackage(archive, series, package, component, pocket): - print "You can upload %s." % package + print "You can upload %s to %s." % (package, options.release) else: - print "You can not upload %s, yourself." % package - print ("But you can still contribute to it via the sponsorship " - "process: https://wiki.ubuntu.com/SponsorshipProcess") - if not options.list_uploaders: - print ("To see who has the necessary upload rights, " - "use the --list-uploaders option.") + print ("You can not upload %s to %s, yourself." + % (package, options.release)) if (series.status in ('Current Stable Release', 'Supported', 'Obsolete') and pocket == 'Release'): print ("%s is in the '%s' state. " "You may want to query the %s-proposed pocket." % (release, series.status, release)) + else: + print ("But you can still contribute to it via the sponsorship " + "process: https://wiki.ubuntu.com/SponsorshipProcess") + if not options.list_uploaders: + print ("To see who has the necessary upload rights, " + "use the --list-uploaders option.") sys.exit(1) From dcef46eeea2af3cd6f8f59eb8b990ba750551cf2 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:20:06 +0200 Subject: [PATCH 22/29] Don't list component upload rights for non-dev series --- upload-permission | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/upload-permission b/upload-permission index e29b3ec..437463b 100755 --- a/upload-permission +++ b/upload-permission @@ -76,13 +76,15 @@ def main(): sys.exit(2) component = spph.getComponent() if options.list_uploaders: - component_uploader = archive.getUploadersForComponent( - component_name=component)[0] - print "All upload permissions for %s:" % package - print - print "Component (%s)" % component - print "============" + ("=" * len(component)) - print_uploaders([component_uploader], options.list_team_members) + if series.status in ('Experimental', 'Active Development', + 'Pre-release Freeze'): + component_uploader = archive.getUploadersForComponent( + component_name=component)[0] + print "All upload permissions for %s:" % package + print + print "Component (%s)" % component + print "============" + ("=" * len(component)) + print_uploaders([component_uploader], options.list_team_members) packagesets = sorted(Packageset.setsIncludingSource( distroseries=series, From 25694bdfdda3e9f6fd9499ebef6ae96c3af03c51 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:26:39 +0200 Subject: [PATCH 23/29] Don't list None as a release --- upload-permission | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/upload-permission b/upload-permission index 437463b..4e1c7e8 100755 --- a/upload-permission +++ b/upload-permission @@ -59,15 +59,13 @@ def main(): ubuntu = Distribution('ubuntu') archive = ubuntu.getArchive() if options.release is None: - series = ubuntu.getDevelopmentSeries() - pocket = 'Release' - else: - try: - release, pocket = split_release_pocket(options.release) - series = ubuntu.getSeries(release) - except SeriesNotFoundException, e: - Logger.error(str(e)) - sys.exit(2) + options.release = ubuntu.getDevelopmentSeries().name + try: + release, pocket = split_release_pocket(options.release) + series = ubuntu.getSeries(release) + except SeriesNotFoundException, e: + Logger.error(str(e)) + sys.exit(2) try: spph = archive.getSourcePackage(package) @@ -123,9 +121,9 @@ def main(): else: print ("But you can still contribute to it via the sponsorship " "process: https://wiki.ubuntu.com/SponsorshipProcess") - if not options.list_uploaders: - print ("To see who has the necessary upload rights, " - "use the --list-uploaders option.") + if not options.list_uploaders: + print ("To see who has the necessary upload rights, " + "use the --list-uploaders option.") sys.exit(1) From ff644a2ca1cb746c3b7c1620c0b057098a04b9bc Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:26:59 +0200 Subject: [PATCH 24/29] Actually, skip all upload rights when the release is non-dev --- upload-permission | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/upload-permission b/upload-permission index 4e1c7e8..d27e363 100755 --- a/upload-permission +++ b/upload-permission @@ -73,16 +73,16 @@ def main(): Logger.error(str(e)) sys.exit(2) component = spph.getComponent() - if options.list_uploaders: - if series.status in ('Experimental', 'Active Development', - 'Pre-release Freeze'): - component_uploader = archive.getUploadersForComponent( - component_name=component)[0] - print "All upload permissions for %s:" % package - print - print "Component (%s)" % component - print "============" + ("=" * len(component)) - print_uploaders([component_uploader], options.list_team_members) + if (options.list_uploaders and series.status in + ('Experimental', 'Active Development', 'Pre-release Freeze')): + + component_uploader = archive.getUploadersForComponent( + component_name=component)[0] + print "All upload permissions for %s:" % package + print + print "Component (%s)" % component + print "============" + ("=" * len(component)) + print_uploaders([component_uploader], options.list_team_members) packagesets = sorted(Packageset.setsIncludingSource( distroseries=series, From 405a3c3327b6edbf40b180fe50806ab9f47d8760 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:31:23 +0200 Subject: [PATCH 25/29] non-release pockets are ok for non-dev releases --- upload-permission | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/upload-permission b/upload-permission index d27e363..2df06bd 100755 --- a/upload-permission +++ b/upload-permission @@ -73,8 +73,8 @@ def main(): Logger.error(str(e)) sys.exit(2) component = spph.getComponent() - if (options.list_uploaders and series.status in - ('Experimental', 'Active Development', 'Pre-release Freeze')): + if (options.list_uploaders and (pocket != 'Release' or series.status in + ('Experimental', 'Active Development', 'Pre-release Freeze'))): component_uploader = archive.getUploadersForComponent( component_name=component)[0] From a22f4eebab9aabd9459a2d5041c1c6c21f73aacc Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:35:49 +0200 Subject: [PATCH 26/29] Rename again --- debian/changelog | 2 +- debian/control | 4 +++- debian/copyright | 4 ++-- ...d-permission.1 => ubuntu-upload-permission.1} | 16 ++++++++-------- setup.py | 2 +- upload-permission => ubuntu-upload-permission | 0 6 files changed, 15 insertions(+), 13 deletions(-) rename doc/{upload-permission.1 => ubuntu-upload-permission.1} (78%) rename upload-permission => ubuntu-upload-permission (100%) diff --git a/debian/changelog b/debian/changelog index d4d8f1d..cf07842 100644 --- a/debian/changelog +++ b/debian/changelog @@ -18,7 +18,7 @@ ubuntu-dev-tools (0.137) UNRELEASED; urgency=low * mk-sbuild, pbuilder-dist, ubuntu-build: Add armhf. * pull-debian-source, pull-lp-source: Resolve the source package (via DDE), if a binary package was requested (LP: #617349) - * New Tool: upload-permission: Query upload permissions (LP: #876554) + * New Tool: ubuntu-upload-permission: Query upload permissions (LP: #876554) [ Andreas Moog ] * sponsor-patch: Check permission to unsubscribe sponsors-team (LP: #896884) diff --git a/debian/control b/debian/control index 19cec22..b70af40 100644 --- a/debian/control +++ b/debian/control @@ -106,4 +106,6 @@ Description: useful tools for Ubuntu developers command line. - ubuntu-iso - output information of an Ubuntu ISO image. - update-maintainer - script to update maintainer field in ubuntu packages. - - upload-permission - query / list the upload permissions for a package. + - ubuntu-upload-permission - query / list the upload permissions for a + package. + - update-maintainer - Set the Ubuntu-policy Maintainer in debian/control. diff --git a/debian/copyright b/debian/copyright index 5933bf2..67276b4 100644 --- a/debian/copyright +++ b/debian/copyright @@ -150,14 +150,15 @@ Files: doc/pull-debian-debdiff.1 doc/reverse-depends.1 doc/sponsor-patch.1 doc/ubuntu-dev-tools.5 + doc/ubuntu-upload-permission.1 doc/update-maintainer.1 - doc/upload-permission.1 pull-debian-debdiff pull-debian-source requestbackport reverse-depends sponsor-patch test-data/* + ubuntu-upload-permission ubuntutools/archive.py ubuntutools/builder.py ubuntutools/config.py @@ -167,7 +168,6 @@ Files: doc/pull-debian-debdiff.1 ubuntutools/test/* ubuntutools/update_maintainer.py update-maintainer - upload-permission Copyright: 2009-2011, Benjamin Drung 2010, Evan Broder 2008, Siegfried-Angel Gevatter Pujals diff --git a/doc/upload-permission.1 b/doc/ubuntu-upload-permission.1 similarity index 78% rename from doc/upload-permission.1 rename to doc/ubuntu-upload-permission.1 index 742b95d..4d97b03 100644 --- a/doc/upload-permission.1 +++ b/doc/ubuntu-upload-permission.1 @@ -11,18 +11,18 @@ .\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR .\" OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. -.TH upload\-permission 1 "November 2011" ubuntu\-dev\-tools +.TH ubuntu\-upload\-permission 1 "November 2011" ubuntu\-dev\-tools .SH NAME -upload\-permission \- Query upload rights and (optionally) list the -people and teams with upload rights for a package +ubuntu\-upload\-permission \- Query upload rights and (optionally) list +the people and teams with upload rights for a package .SH SYNOPSIS -.B upload\-permission \fR[\fIoptions\fR] \fIpackage +.B ubuntu\-upload\-permission \fR[\fIoptions\fR] \fIpackage .SH DESCRIPTION -\fBupload\-permission\fR checks if the user has upload permissions for -\fIpackage\fR. +\fBubuntu\-upload\-permission\fR checks if the user has upload +permissions for \fIpackage\fR. If the \fB\-\-list\-uploaders\fR option is provided, all the people and teams that do have upload rights for \fIpackage\fR will be listed. @@ -54,7 +54,7 @@ You don't have the necessary upload rights. There was an error. .SH AUTHORS -\fBupload\-permission\fR and this manpage were written by Stefano Rivera -. +\fBubuntu\-upload\-permission\fR and this manpage were written by +Stefano Rivera . .PP Both are released under the terms of the ISC License. diff --git a/setup.py b/setup.py index 92d9c96..2efa54f 100755 --- a/setup.py +++ b/setup.py @@ -41,8 +41,8 @@ scripts = ['404main', 'syncpackage', 'ubuntu-build', 'ubuntu-iso', + 'ubuntu-upload-permission', 'update-maintainer', - 'upload-permission', ] if __name__ == '__main__': diff --git a/upload-permission b/ubuntu-upload-permission similarity index 100% rename from upload-permission rename to ubuntu-upload-permission From 973e1b51c127e3ac67a2f7db880b930820acb265 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:42:09 +0200 Subject: [PATCH 27/29] Missed update-maintainer --- debian/control | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/control b/debian/control index b70af40..0cfbe5b 100644 --- a/debian/control +++ b/debian/control @@ -105,7 +105,6 @@ Description: useful tools for Ubuntu developers - ubuntu-build - give commands to the Launchpad build daemons from the command line. - ubuntu-iso - output information of an Ubuntu ISO image. - - update-maintainer - script to update maintainer field in ubuntu packages. - ubuntu-upload-permission - query / list the upload permissions for a package. - - update-maintainer - Set the Ubuntu-policy Maintainer in debian/control. + - update-maintainer - script to update maintainer field in ubuntu packages. From 2da0560c686e4330c411917c9cd193426a703f0e Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 4 Dec 2011 00:45:26 +0200 Subject: [PATCH 28/29] Mention backportpackage in debian/control --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index 0cfbe5b..7255fb1 100644 --- a/debian/control +++ b/debian/control @@ -68,6 +68,7 @@ Description: useful tools for Ubuntu developers . - 404main - used to check what components a package's deps are in, for doing a main inclusion report for example. + - backportpackage - helper to test package backports - bitesize - add the 'bitesize' tag to a bug and comment that you are willing to help fix it. - check-mir - check support status of build/binary dependencies From 6ad66e3d42b9b889eff9bd25002d42fc23151366 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 7 Dec 2011 01:09:07 +0200 Subject: [PATCH 29/29] re-wrap changelog --- debian/changelog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index d6b53ca..c88bce0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -28,7 +28,8 @@ ubuntu-dev-tools (0.137) UNRELEASED; urgency=low * sponsor-patch: Check permission to unsubscribe sponsors-team (LP: #896884) * grep-merges: We already require a UTF-8 enabled terminal, so encode package and uploader name in UTF-8 (LP: #694388) - * requestsync: Give user option to retry in case of temporary error (LP: #850360) + * requestsync: Give user option to retry in case of temporary error + (LP: #850360) -- Andreas Moog Wed, 30 Nov 2011 21:04:39 +0100