* ubuntutools/lp/lpapicache.py: use the new LP API function

archive.checkUpload() to check upload permissions
* Add "import-bug-from-debian" written by James Westby to u-d-t
This commit is contained in:
Michael Bienia 2010-07-11 20:36:15 +02:00
commit 5c5240519b
6 changed files with 215 additions and 47 deletions

6
debian/changelog vendored
View File

@ -14,7 +14,11 @@ ubuntu-dev-tools (0.101) UNRELEASED; urgency=low
* Bump Standards-Version to 3.9.0 (no changes required).
* Switch to dpkg-source 3.0 (native) format.
-- Benjamin Drung <bdrung@ubuntu.com> Tue, 29 Jun 2010 16:43:51 +0200
[ Michael Bienia ]
* Add "import-bug-from-debian" written by James Westby.
* Add python-soappy to Recommends.
-- Michael Bienia <geser@ubuntu.com> Sun, 11 Jul 2010 20:32:49 +0200
ubuntu-dev-tools (0.100) maverick; urgency=low

2
debian/control vendored
View File

@ -35,6 +35,7 @@ Recommends: bzr,
libwww-perl,
pbuilder | cowdancer | sbuild,
perl-modules,
python-soappy,
reportbug (>= 3.39ubuntu1)
Suggests: qemu-kvm-extras-static
Description: useful tools for Ubuntu developers
@ -57,6 +58,7 @@ Description: useful tools for Ubuntu developers
report.
- grab-merge - grabs a merge from merges.ubuntu.com easily.
- hugdaylist - compile HugDay lists from bug list URLs.
- import-bug-from-debian - copy a bug from the Debian BTS to Launchpad
- lp-project-upload - upload a release tarball to a Launchpad project
- lp-set-dup - sets the "duplicate of" bug of a bug and its dups.
- manage-credentials - manage Launchpad token credentials.

18
debian/copyright vendored
View File

@ -10,6 +10,7 @@ Upstream Authors:
Daniel Holbach <daniel.holbach@ubuntu.com>
Emmet Hikory <persia@ubuntu.com>
Iain Lane <iain@orangesquash.org.uk>
James Westby <james.westby@ubuntu.com>
Jamin W. Collins <jcollins@asgardsrealm.net>
Jonathan Davies <jpds@ubuntu.com>
Jordan Mantha <mantha@ubuntu.com>
@ -35,6 +36,7 @@ Copyright:
(C) 2006-2007, Albin Tonnerre <lut1n.tne@gmail.com>
(C) 2006-2007, Daniel Holbach <daniel.holbach@ubuntu.com>
(C) 2008, Iain Lane <iain@orangesquash.org.uk>
© 2009, James Westby <james.westby@ubuntu.com>
(C) Jamin W. Collins <jcollins@asgardsrealm.net>
(C) 2008-2009, Jonathan Davies <jpds@ubuntu.com>
(C) Jordan Mantha <mantha@ubuntu.com>
@ -54,9 +56,10 @@ Copyright:
Licenses:
404main, check-symbols, dgetlp, lp-project-upload, lp-set-dup, pbuilder-dist,
pbuilder-dist-simple, requestsync, reverse-build-depends, submittodebian, ubuntuiso,
and update-maintainer are licensed under the GNU General Public License, version 2:
404main, check-symbols, dgetlp, import-bug-from-debian, lp-project-upload,
lp-set-dup, pbuilder-dist, pbuilder-dist-simple, requestsync,
reverse-build-depends, submittodebian, ubuntuiso, and update-maintainer are
licensed under the GNU General Public License, version 2:
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -90,7 +93,8 @@ License v3 can be found in `/usr/share/common-licenses/GPL-3'.
The following scripts can be used, at your option, regarding any later
version of the previously specified license: 404main, dch-repeat, dgetlp,
get-build-deps, lp-project-upload, lp-set-dup, manage-credentials, mk-sbuild-lv,
pbuilder-dist, pull-debian-debdiff, pull-debian-source, pull-lp-source,
pull-revu-source, reverse-build-depends, setup-packaging-environment, submittodebian,
suspicious-source, syncpackage, ubuntu-build, what-patch.
get-build-deps, import-bug-from-debian, lp-project-upload, lp-set-dup,
manage-credentials, mk-sbuild-lv, pbuilder-dist, pull-debian-debdiff,
pull-debian-source, pull-lp-source, pull-revu-source, reverse-build-depends,
setup-packaging-environment, submittodebian, suspicious-source, syncpackage,
ubuntu-build, what-patch.

173
import-bug-from-debian Executable file
View File

@ -0,0 +1,173 @@
#!/usr/bin/python
# Copyright © 2009 James Westby <james.westby@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 2
# 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ##################################################################
from launchpadlib.launchpad import (
STAGING_SERVICE_ROOT,
EDGE_SERVICE_ROOT,
)
from optparse import OptionParser
import re
import SOAPpy
import sys
import subprocess
import ubuntutools.lp.libsupport as lp_libsupport
bug_re = re.compile(r"bug=(\d+)")
url = 'http://bugs.debian.org/cgi-bin/soap.cgi'
namespace = 'Debbugs/SOAP'
debbugs = SOAPpy.SOAPProxy(url, namespace)
# debug
#debbugs.config.dumpSOAPOut = 1
#debbugs.config.dumpSOAPIn = 1
parser = OptionParser()
parser.add_option("-n", "--dry-run",
help="Use the staging server so that changes are not permanent",
dest="dry_run", action="store_true")
parser.add_option("-b", "--browserless",
help="Don't open the bug in the browser at the end",
dest="browserless", action="store_true")
(options, args) = parser.parse_args()
if options.dry_run:
lp_server = STAGING_SERVICE_ROOT
lp_web_base = "https://staging.launchpad.net/"
else:
lp_server = EDGE_SERVICE_ROOT
lp_web_base = "https://staging.launchpad.net/"
try:
lp = lp_libsupport.get_launchpad("ubuntu-dev-tools", lp_server)
except IOError, msg:
print msg
print "No credentials, can't continue"
sys.exit(1)
debian = lp.distributions['debian']
ubuntu = lp.distributions['ubuntu']
lp_debbugs = lp.bugs[262256].bug_watches[0].bug_tracker
bug_nums = []
for bug_num in args:
if bug_num.startswith("http"):
# bug URL
match = bug_re.search(bug_num)
if match is None:
raise ValueError("Can't determine bug number from %s" % bug_num)
bug_num = match.groups()[0]
bug_num = bug_num.lstrip("#")
bug_num = int(bug_num)
bug_nums.append(bug_num)
bugs = debbugs.get_status(*bug_nums)
if len(bug_nums) > 1:
bugs = bugs[0]
import pdb; pdb.set_trace()
for bug in bugs:
bug = bug.value
package = bug.package
bug_num = bug.bug_num
subject = bug.subject
log = debbugs.get_bug_log(bug_num)
summary = log[0][0]
target = ubuntu.getSourcePackage(name=package)
u_bug = lp.bugs.createBug(target=target, title=subject,
description="Imported from Debian bug %d:\n\n%s"
% (bug_num, summary))
d_task = u_bug.addTask(target=debian.getSourcePackage(name=package))
d_watch = u_bug.addWatch(remote_bug=bug_num, bug_tracker=lp_debbugs)
d_task.bug_watch = d_watch
d_task.lp_save()
web_url = "%s/ubuntu/+source/%s/+bug/%d" % (lp_web_base, package, u_bug.id)
print "Opened %s" % web_url
if not options.browserless:
subprocess.call(["xdg-open", web_url])
#def get_status(*args):
# result = server.get_status(*args)
# return result
#
#def get_bugs(*args):
# result = server.get_bugs(*args)
# return result
#
#def get_usertag(email, *tags):
# result = server.get_usertag(email, *tags)
# return result
#
#def get_bug_log(bugnumber):
# result = server.get_bug_log(bugnumber)
# return result
#
#def newest_bugs(amount):
# result = server.newest_bugs(amount)
# return result
#
#if __name__ == "__main__":
# # Demonstration
#
# # some debug output
#
# # All bugs from one package (returns a list of bugnumbers)
# print get_bugs("package", "gtk-qt-engine")
#
# # All bugs of a maintainer
# print get_bugs("maint", "debian-qa@lists.debian.org")
#
# # returns the status of those bugs
# print get_status(409909, 419920, 421581, 417044, 397993)
#
# # get_status and get_bugs combined:
# print get_status(get_bugs("package", "gtk-qt-engine"))
#
# # returns the full log for the given bug number
# print get_bug_log(202526)
#
# # retrives the newest 20 bugs
# print newest_bugs(20)
#
# # All bugs of a maintainer
# print get_bugs("maint", "debian-qa@lists.debian.org")
#
# # returns the status of those bugs
# print get_status(409909, 419920, 421581, 417044, 397993)
#
# # get_status and get_bugs combined:
# print get_status(get_bugs("package", "gtk-qt-engine"))
#
# # returns the full log for the given bug number
# print get_bug_log(202526)
#
# # retrives the newest 20 bugs
# print newest_bugs(20)
#
# # returns bugs tagged by the given email
# print get_usertag("debian-qa@lists.debian.org")
#
# # returns bugs tagged by the given email, with the given tag
# print get_usertag("debian-qa@lists.debian.org", "qa-ftbfs-20070708")
#

View File

@ -24,6 +24,7 @@ setup(name='ubuntu-dev-tools',
'grab-attachments',
'grab-merge',
'hugdaylist',
'import-bug-from-debian',
'lp-project-upload',
'lp-set-dup',
'lp-shell',

View File

@ -408,11 +408,9 @@ class PersonTeam(BaseWrapper):
)
def __init__(self, *args):
# Don't share _upload_{pkg,comp} between different PersonTeams
if '_upload_pkg' not in self.__dict__:
self._upload_pkg = dict()
if '_upload_comp' not in self.__dict__:
self._upload_comp = dict()
# Don't share _upload between different PersonTeams
if '_upload' not in self.__dict__:
self._upload = dict()
def __str__(self):
return u'%s (%s)' % (self.display_name, self.name)
@ -440,54 +438,40 @@ class PersonTeam(BaseWrapper):
'''
return any(t.name == team for t in self.super_teams)
def canUploadPackage(self, archive, distroseries, package, component):
def canUploadPackage(self, archive, distroseries, package, component, pocket='Release'):
'''Check if the person or team has upload rights for the source
package to the specified 'archive' and 'distrorelease' either
through package sets, component or or per-package upload rights.
Either a source package name or a component has the specified.
package to the specified 'archive' and 'distrorelease'.
A source package name and a component have to be specified.
'archive' has to be a Archive object.
'distroseries' has to be an DistroSeries object.
'distroseries' has to be an DistroSeries object.
'''
if not isinstance(archive, Archive):
raise TypeError("'%r' is not an Archive object." % archive)
if not isinstance(distroseries, DistroSeries):
raise TypeError("'%r' is not a DistroSeries object." % distroseries)
if not isinstance(distroseries, DistroSeries):
raise TypeError("'%r' is not a DistroSeries object." % distroseries)
if package is not None and not isinstance(package, basestring):
raise TypeError('A source package name expected.')
if component is not None and not isinstance(component, basestring):
raise TypeError('A component name expected.')
if package is None and component is None:
raise ValueError('Either a source package name or a component has to be specified.')
if pocket not in ('Release', 'Security', 'Updates', 'Proposed', 'Backports'):
raise PocketDoesNotExistError("Pocket '%s' does not exist." % pocket)
upload_comp = self._upload_comp.get((archive, component))
upload_pkg = self._upload_pkg.get((archive, package))
canUpload = self._upload.get((archive, distroseries, pocket, package, component))
if upload_comp is None and upload_pkg is None:
# archive.isSourceUploadAllowed() checks only package sets permission
if package is not None and archive.isSourceUploadAllowed(
distroseries=distroseries(), person=self(), sourcepackagename=package):
# TODO: also cache the release it applies to
self._upload_pkg[(archive, package)] = True
return True
# check for component or per-package upload rights
for perm in archive.getPermissionsForPerson(person=self()):
if perm.permission != 'Archive Upload Rights':
continue
if component and perm.component_name == component:
self._upload_comp[(archive, component)] = True
return True
if package and perm.source_package_name == package:
self._upload_pkg[(archive, package)] = True
return True
# don't have upload rights
if package:
self._upload_pkg[(archive, package)] = False
if component:
self._upload_comp[(archive, component)] = False
return False
else:
return upload_comp or upload_pkg
if canUpload is None:
canUpload = archive.checkUpload(
component=component,
distroseries=distroseries(),
person=self(),
pocket=pocket,
sourcepackagename=package,
)
self._upload[(archive, distroseries, pocket, package, component)] = canUpload
return canUpload
class Build(BaseWrapper):