From 4779d7b1a77a0270be391e71c71df9705c7cc482 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Tue, 4 Aug 2009 12:44:17 +0200 Subject: [PATCH 01/18] requestsync: remove unneeded modules --- requestsync | 2 -- 1 file changed, 2 deletions(-) diff --git a/requestsync b/requestsync index 5065b58..98ef6f2 100755 --- a/requestsync +++ b/requestsync @@ -29,11 +29,9 @@ import os import subprocess import sys -import urllib import urllib2 from debian_bundle.changelog import Version from optparse import OptionParser -from time import sleep # ubuntu-dev-tools modules. import ubuntutools.lp.libsupport as lp_libsupport From df881ec2dad37e27b08603bcac8c79da9954b048 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Tue, 4 Aug 2009 13:43:31 +0200 Subject: [PATCH 02/18] requestsync: refactor some code into its own module and provide versions of the methods w/ and w/o LP API usage --- requestsync | 40 +++---------------- ubuntutools/requestsync/__init__.py | 0 ubuntutools/requestsync/common.py | 50 +++++++++++++++++++++++ ubuntutools/requestsync/lp.py | 32 +++++++++++++++ ubuntutools/requestsync/mail.py | 61 +++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 35 deletions(-) create mode 100644 ubuntutools/requestsync/__init__.py create mode 100644 ubuntutools/requestsync/common.py create mode 100644 ubuntutools/requestsync/lp.py create mode 100644 ubuntutools/requestsync/mail.py diff --git a/requestsync b/requestsync index 98ef6f2..4c99203 100755 --- a/requestsync +++ b/requestsync @@ -41,6 +41,8 @@ from ubuntutools.lp.lpapiwrapper import Launchpad, LpApiWrapper import ubuntutools.common import ubuntutools.packages +from ubuntutools.requestsync.mail import getDebianSrcPkg + def checkNeedsSponsorship(srcpkg): """ Check that the user has the appropriate permissions by checking what @@ -127,21 +129,6 @@ def cur_version_component(sourcepkg, release): print "%s doesn't appear to exist in %s, specify -n for a package not in Ubuntu." % (sourcepkg, release) sys.exit(1) -def cur_deb_version(sourcepkg, distro): - '''Return the current debian version of a package in a Debian distro.''' - out = ubuntutools.packages.checkIsInDebian(sourcepkg, distro) - if not out: - print "%s doesn't appear to exist in Debian." % sourcepkg - sys.exit(0) - - # Work-around for a bug in Debians madison.php script not returning - # only the source line - for line in out.splitlines(): - if line.find('source') > 0: - out = line - - return out.split('|')[1].rstrip('[]''').strip() - def debian_changelog(sourcepkg, component, version): '''Return the Debian changelog from the latest up to the given version (exclusive).''' @@ -171,24 +158,6 @@ def debian_changelog(sourcepkg, component, version): return ch -def debian_component(sourcepkg, distro): - '''Return the Debian component for the source package.''' - madison = subprocess.Popen(['rmadison', '-u', 'debian', '-a', 'source', '-s', distro, \ - sourcepkg], stdout=subprocess.PIPE) - out = madison.communicate()[0] - assert (madison.returncode == 0) - - try: - assert out - except AssertionError: - print "%s doesn't appear to exist in Debian." % sourcepkg - sys.exit(1) - raw_comp = out.split('|')[2].split('/') - component = 'main' - if len(raw_comp) == 2: - component = raw_comp[1].strip() - return component - def raw_input_exit_on_ctrlc(*args, **kwargs): """A wrapper around raw_input() to exit with a normalized message on Control-C""" try: @@ -489,9 +458,10 @@ if __name__ == '__main__': # Find Ubuntu release's package version. if not newsource: (cur_ver, component) = cur_version_component(srcpkg, release) - debiancomponent = debian_component(srcpkg, distro) + debsrcpkg = getDebianSrcPkg(srcpkg, distro) + debiancomponent = debsrcpkg.getComponent() # Find Debian release's package version. - deb_version = cur_deb_version(srcpkg, distro) + deb_version = debsrcpkg.getVersion() # Debian and Ubuntu versions are the same - stop. if deb_version == cur_ver: diff --git a/ubuntutools/requestsync/__init__.py b/ubuntutools/requestsync/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ubuntutools/requestsync/common.py b/ubuntutools/requestsync/common.py new file mode 100644 index 0000000..ecfcbe4 --- /dev/null +++ b/ubuntutools/requestsync/common.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +# common.py - common methods used by requestsync +# +# Copyright © 2009 Michael Bienia +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# Please see the /usr/share/common-licenses/GPL file for the full text +# of the GNU General Public License license. + +import sys +import urllib2 +from debian_bundle.changelog import Changelog + +def debian_changelog(srcpkg, version): + ''' + Return the new changelog entries upto 'version'. + ''' + pkgname = srcpkg.getPackageName() + component = srcpkg.getComponent() + if pkgname.startswith('lib'): + subdir = 'lib%s' % pkgname[3] + else: + subdir = pkgname[0] + + # Get the debian changelog file from packages.debian.org + try: + changelog = urllib2.urlopen( + 'http://packages.debian.org/changelogs/pool/%s/%s/%s/current/changelog.txt' % \ + (component, subdir, pkgname)) + except urllib2.HTTPError, error: + print >> sys.stderr, 'Unable to connect to packages.debian.org: %s' % error + return None + + new_entries = '' + changelog = Changelog(changelog.read()) + for block in changelog._blocks: + if block.version > version: + new_entries += str(block) + + return new_entries diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py new file mode 100644 index 0000000..c093650 --- /dev/null +++ b/ubuntutools/requestsync/lp.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# +# lp.py - methods used by requestsync while interacting +# directly with Launchpad +# +# Copyright © 2009 Michael Bienia +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# Please see the /usr/share/common-licenses/GPL file for the full text +# of the GNU General Public License license. + +from ..lp.lpapiwrapper import Distribution +from ..lp.udtexceptions import * + +def getDebianSrcPkg(name, release): + debian = Distribution('debian') + debian_archive = debian.getArchive() + + # Map 'unstable' to 'sid' as LP doesn't know 'unstable' but only 'sid' + if release == 'unstable': + release = 'sid' + + return debian_archive.getSourcePackage(name, release) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py new file mode 100644 index 0000000..1723066 --- /dev/null +++ b/ubuntutools/requestsync/mail.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# +# mail.py - methods used by requestsync when used in "mail" mode +# +# Copyright © 2009 Michael Bienia +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# Please see the /usr/share/common-licenses/GPL file for the full text +# of the GNU General Public License license. + +from ..packages import checkIsInDebian +from ..lp.udtexceptions import PackageNotFoundException + +# Simulate the SourcePackage class from lpapiwrapper +class SourcePackage(object): + ''' + Simulate a SourcePackage class from the LP API wrapper module. + ''' + def __init__(self, name, version, component): + self.name = name + self.version = version + self.component = component + + def getPackageName(self): + return self.name + + def getVersion(self): + return self.version + + def getComponent(self): + return self.component + +def getDebianSrcPkg(name, release): + out = checkIsInDebian(name, release) + if not out: + raise PackageNotFoundException( + "'%s' doesn't appear to exist in Debian '%s'" % \ + (name, release)) + + # Work-around for a bug in Debians madison.php script not returning + # only the source line + for line in out.splitlines(): + if line.find('source') > 0: + out = line.split('|') + + version = out[1].strip() + component = 'main' + raw_comp = out[2].split('/') + if len(raw_comp) == 2: + component = raw_comp[1].strip() + + return SourcePackage(name, version, component) From fa0b10c274d1047660be916a4b36d9abc803ff90 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Tue, 4 Aug 2009 14:24:04 +0200 Subject: [PATCH 03/18] requestsync: more refactoring --- requestsync | 36 +++++-------------------------- ubuntutools/requestsync/common.py | 2 +- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/requestsync b/requestsync index 4c99203..12b162a 100755 --- a/requestsync +++ b/requestsync @@ -29,7 +29,6 @@ import os import subprocess import sys -import urllib2 from debian_bundle.changelog import Version from optparse import OptionParser @@ -42,6 +41,7 @@ import ubuntutools.common import ubuntutools.packages from ubuntutools.requestsync.mail import getDebianSrcPkg +from ubuntutools.requestsync.common import getDebianChangelog def checkNeedsSponsorship(srcpkg): """ @@ -129,35 +129,6 @@ def cur_version_component(sourcepkg, release): print "%s doesn't appear to exist in %s, specify -n for a package not in Ubuntu." % (sourcepkg, release) sys.exit(1) -def debian_changelog(sourcepkg, component, version): - '''Return the Debian changelog from the latest up to the given version - (exclusive).''' - - base_version = Version(version) - - ch = '' - subdir = sourcepkg[0] - - if sourcepkg.startswith('lib'): - subdir = 'lib%s' % sourcepkg[3] - - # Get the debian/changelog file from packages.debian.org. - try: - debianChangelogPage = urllib2.urlopen('http://packages.debian.org/changelogs/pool/%s/%s/%s/current/changelog.txt' % (component, subdir, sourcepkg)) - except urllib2.HTTPError, error: - print >> sys.stderr, "Unable to connect to packages.debian.org. " \ - "Received a %s." % error.code - sys.exit(1) - - for l in debianChangelogPage: - if l.startswith(sourcepkg): - ch_version = l[ l.find("(")+1 : l.find(")") ] - if Version(ch_version) <= base_version: - break - ch += l - - return ch - def raw_input_exit_on_ctrlc(*args, **kwargs): """A wrapper around raw_input() to exit with a normalized message on Control-C""" try: @@ -535,7 +506,10 @@ if __name__ == '__main__': base_ver = force_base_ver report += 'Changelog since current %s version %s:\n\n' % (release, cur_ver) - report += debian_changelog(srcpkg, debiancomponent, base_ver) + '\n' + changelog = getDebianChangelog(debsrcpkg, Version(base_ver)) + if not changelog: + sys.exit(1) + report += changelog + '\n' if need_interaction: (title, report) = edit_report(title, report, changes_required=True) diff --git a/ubuntutools/requestsync/common.py b/ubuntutools/requestsync/common.py index ecfcbe4..9ce2da9 100644 --- a/ubuntutools/requestsync/common.py +++ b/ubuntutools/requestsync/common.py @@ -21,7 +21,7 @@ import sys import urllib2 from debian_bundle.changelog import Changelog -def debian_changelog(srcpkg, version): +def getDebianChangelog(srcpkg, version): ''' Return the new changelog entries upto 'version'. ''' From c30c4865a477efc2781f7a0c1f866e63438c3a8d Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Wed, 5 Aug 2009 23:10:05 +0200 Subject: [PATCH 04/18] ubuntutools/requestsync/*.py: update copyright notices and license to match the requestsync script --- ubuntutools/requestsync/common.py | 8 +++++--- ubuntutools/requestsync/lp.py | 8 +++++--- ubuntutools/requestsync/mail.py | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ubuntutools/requestsync/common.py b/ubuntutools/requestsync/common.py index 9ce2da9..80b029b 100644 --- a/ubuntutools/requestsync/common.py +++ b/ubuntutools/requestsync/common.py @@ -4,17 +4,19 @@ # # Copyright © 2009 Michael Bienia # +# This module may contain code written by other authors/contributors to +# the main requestsync script. See there for their names. +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. +# as published by the Free Software Foundation; version 2 # # 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. # -# Please see the /usr/share/common-licenses/GPL file for the full text +# Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. import sys diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index c093650..19ca82b 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -5,17 +5,19 @@ # # Copyright © 2009 Michael Bienia # +# This module may contain code written by other authors/contributors to +# the main requestsync script. See there for their names. +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. +# as published by the Free Software Foundation; version 2 # # 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. # -# Please see the /usr/share/common-licenses/GPL file for the full text +# Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. from ..lp.lpapiwrapper import Distribution diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 1723066..a70684f 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -4,17 +4,19 @@ # # Copyright © 2009 Michael Bienia # +# This module may contain code written by other authors/contributors to +# the main requestsync script. See there for their names. +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. +# as published by the Free Software Foundation; version 2 # # 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. # -# Please see the /usr/share/common-licenses/GPL file for the full text +# Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. from ..packages import checkIsInDebian From 5e3e368bb83e952e1185a8e4bf003cda057af804 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Thu, 6 Aug 2009 00:23:58 +0200 Subject: [PATCH 05/18] requestsync: some more refactoring --- requestsync | 14 +++-------- ubuntutools/requestsync/common.py | 10 ++++++++ ubuntutools/requestsync/lp.py | 6 +++++ ubuntutools/requestsync/mail.py | 42 ++++++++++++++++++++++--------- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/requestsync b/requestsync index 67d7272..edce8a0 100755 --- a/requestsync +++ b/requestsync @@ -40,8 +40,8 @@ from ubuntutools.lp.lpapicache import Launchpad, LpApiWrapper, Distribution, Per import ubuntutools.common import ubuntutools.packages -from ubuntutools.requestsync.mail import getDebianSrcPkg -from ubuntutools.requestsync.common import getDebianChangelog +from ubuntutools.requestsync.mail import * +from ubuntutools.requestsync.common import * def checkNeedsSponsorship(srcpkg): """ @@ -121,7 +121,7 @@ def checkExistingReports(package): def cur_version_component(sourcepkg, release): try: - src = Distribution('ubuntu').getArchive().getSourcePackage(sourcepkg, release) + src = getUbuntuSrcPkg(sourcepkg, release) return (src.getVersion(), src.getComponent()) except udtexceptions.PackageNotFoundException: @@ -129,14 +129,6 @@ def cur_version_component(sourcepkg, release): print "%s doesn't appear to exist in %s, specify -n for a package not in Ubuntu." % (sourcepkg, release) sys.exit(1) -def raw_input_exit_on_ctrlc(*args, **kwargs): - """A wrapper around raw_input() to exit with a normalized message on Control-C""" - try: - return raw_input(*args, **kwargs) - except KeyboardInterrupt: - print 'Abort requested. No sync request filed.' - sys.exit(1) - def get_email_address(): '''Get the DEBEMAIL environment variable or give an error.''' myemailaddr = os.getenv('DEBEMAIL') diff --git a/ubuntutools/requestsync/common.py b/ubuntutools/requestsync/common.py index 80b029b..2eb305b 100644 --- a/ubuntutools/requestsync/common.py +++ b/ubuntutools/requestsync/common.py @@ -23,6 +23,16 @@ import sys import urllib2 from debian_bundle.changelog import Changelog +def raw_input_exit_on_ctrlc(*args, **kwargs): + ''' + A wrapper around raw_input() to exit with a normalized message on Control-C + ''' + try: + return raw_input(*args, **kwargs) + except KeyboardInterrupt: + print 'Abort requested. No sync request filed.' + sys.exit(1) + def getDebianChangelog(srcpkg, version): ''' Return the new changelog entries upto 'version'. diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index 19ca82b..f69080e 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -32,3 +32,9 @@ def getDebianSrcPkg(name, release): release = 'sid' return debian_archive.getSourcePackage(name, release) + +def getUbuntuSrcPkg(name, release): + ubuntu = Distribution('ubuntu') + ubuntu_archive = ubuntu.getArchive() + + return ubuntu_archive.getSourcePackage(name, release) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index a70684f..3410034 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -19,9 +19,11 @@ # Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. -from ..packages import checkIsInDebian +import subprocess from ..lp.udtexceptions import PackageNotFoundException +__all__ = ['getDebianSrcPkg', 'getUbuntuSrcPkg'] + # Simulate the SourcePackage class from lpapiwrapper class SourcePackage(object): ''' @@ -41,23 +43,39 @@ class SourcePackage(object): def getComponent(self): return self.component -def getDebianSrcPkg(name, release): - out = checkIsInDebian(name, release) - if not out: - raise PackageNotFoundException( - "'%s' doesn't appear to exist in Debian '%s'" % \ - (name, release)) +def rmadison(distro, package, release): + rmadison_cmd = subprocess.Popen( + ['rmadison', '-u', distro, '-a', 'source', '-s', release, package], + stdout = subprocess.PIPE) + + rmadison_out = rmadison_cmd.communicate()[0] + assert (rmadison_cmd.returncode == 0) # Work-around for a bug in Debians madison.php script not returning # only the source line - for line in out.splitlines(): + for line in rmadison_out.splitlines(): if line.find('source') > 0: - out = line.split('|') + return map(lambda x: x.strip(), line.split('|')) - version = out[1].strip() + return None + +def getSrcPkg(distro, name, release): + out = rmadison(distro, name, release) + if not out: + raise PackageNotFoundException( + "'%s' doesn't appear to exist in %s '%s'" % \ + (name, distro.capitalize(), release)) + + version = out[1] component = 'main' raw_comp = out[2].split('/') if len(raw_comp) == 2: - component = raw_comp[1].strip() - + component = raw_comp[1] + return SourcePackage(name, version, component) + +def getDebianSrcPkg(name, release): + return getSrcPkg('debian', name, release) + +def getUbuntuSrcPkg(name, release): + return getSrcPkg('ubuntu', name, release) From ce4e0932a5c40a339060140b7428e72ea7476418 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Thu, 6 Aug 2009 16:26:29 +0200 Subject: [PATCH 06/18] ubuntutools/requestsync/mail.py: Rename SourcePackage to SourcePackagePublishingHistory to be in line with the lpapicache module. --- ubuntutools/requestsync/mail.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 3410034..46b73e6 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -24,10 +24,10 @@ from ..lp.udtexceptions import PackageNotFoundException __all__ = ['getDebianSrcPkg', 'getUbuntuSrcPkg'] -# Simulate the SourcePackage class from lpapiwrapper -class SourcePackage(object): +class SourcePackagePublishingHistory(object): ''' - Simulate a SourcePackage class from the LP API wrapper module. + Simulate a SourcePackagePublishingHistory class from the LP API caching + module. ''' def __init__(self, name, version, component): self.name = name @@ -72,7 +72,7 @@ def getSrcPkg(distro, name, release): if len(raw_comp) == 2: component = raw_comp[1] - return SourcePackage(name, version, component) + return SourcePackagePublishingHistory(name, version, component) def getDebianSrcPkg(name, release): return getSrcPkg('debian', name, release) From ba14d22954dad64884e0160817cd73e40db8bd17 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Fri, 7 Aug 2009 12:53:33 +0200 Subject: [PATCH 07/18] requestsync: more refactoring --- requestsync | 11 ----------- ubuntutools/requestsync/mail.py | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/requestsync b/requestsync index edce8a0..b500514 100755 --- a/requestsync +++ b/requestsync @@ -129,17 +129,6 @@ def cur_version_component(sourcepkg, release): print "%s doesn't appear to exist in %s, specify -n for a package not in Ubuntu." % (sourcepkg, release) sys.exit(1) -def get_email_address(): - '''Get the DEBEMAIL environment variable or give an error.''' - myemailaddr = os.getenv('DEBEMAIL') - if not myemailaddr: - myemailaddr = os.getenv('EMAIL') - if not myemailaddr: - print >> sys.stderr, 'The environment variable DEBEMAIL or ' +\ - 'EMAIL needs to be set to make use of this script, unless ' +\ - 'you use option --lp.' - return myemailaddr - def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None): '''Submit the sync request per email. Return True if email successfully send, otherwise False.''' diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 46b73e6..1a7a724 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -19,6 +19,8 @@ # Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. +import os +import sys import subprocess from ..lp.udtexceptions import PackageNotFoundException @@ -79,3 +81,15 @@ def getDebianSrcPkg(name, release): def getUbuntuSrcPkg(name, release): return getSrcPkg('ubuntu', name, release) + +def get_email_address(): + ''' + Get the From email address from the DEBEMAIL or EMAIL environment + variable or give an error. + ''' + myemailaddr = os.getenv('DEBEMAIL') or os.getenv('EMAIL') + if not myemailaddr: + print >> sys.stderr, 'The environment variable DEBEMAIL or ' \ + 'EMAIL needs to be set to let this script mail the ' \ + 'sync request.' + return myemailaddr From 5748f9d64fd40caacf66b10b1bfa1062d9d097bd Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Fri, 7 Aug 2009 13:27:45 +0200 Subject: [PATCH 08/18] requestsync: more refactoring --- requestsync | 50 ------------------------------- ubuntutools/requestsync/common.py | 49 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/requestsync b/requestsync index b500514..0c34bf7 100755 --- a/requestsync +++ b/requestsync @@ -38,7 +38,6 @@ import ubuntutools.lp.udtexceptions as udtexceptions from ubuntutools.lp.lpapicache import Launchpad, LpApiWrapper, Distribution, PersonTeam # https_proxy fix import ubuntutools.common -import ubuntutools.packages from ubuntutools.requestsync.mail import * from ubuntutools.requestsync.common import * @@ -294,55 +293,6 @@ def post_bug(source_package, subscribe, status, bugtitle, bugtext): lp_libsupport.translate_api_web(bug.self_link)) return True -def edit_report(subject, body, changes_required=False): - """Edit a report (consisting of subject and body) in sensible-editor. - - subject and body get decorated, before they are written to the temporary - file and undecorated after editing again. - If changes_required is True and the file has not been edited - (according to its mtime), an error is written to STDERR and the - program exits. - Returns (new_subject, new_body). - """ - import re - import string - - report = "Summary (one line):\n%s\n\nDescription:\n%s" % (subject, body) - - # Create tempfile and remember mtime - import tempfile - report_file = tempfile.NamedTemporaryFile( prefix='requestsync_' ) - report_file.file.write(report) - report_file.file.flush() - mtime_before = os.stat( report_file.name ).st_mtime - - # Launch editor - try: - editor = subprocess.check_call( ['sensible-editor', report_file.name] ) - except subprocess.CalledProcessError, e: - print >> sys.stderr, 'Error calling sensible-editor: %s\nAborting.' % (e,) - sys.exit(1) - - # Check if the tempfile has been changed - if changes_required: - report_file_info = os.stat( report_file.name ) - if mtime_before == os.stat( report_file.name ).st_mtime: - print >> sys.stderr, 'The temporary file %s has not been changed, but you have\nto explain why the Ubuntu changes can be dropped. Aborting. [Press ENTER]' % (report_file.name,) - raw_input() - sys.exit(1) - - report_file.file.seek(0) - report = report_file.file.read() - report_file.file.close() - - # Undecorate report again: - (new_subject, new_body) = report.split("\nDescription:\n", 1) - # Remove prefix and whitespace for subject: - new_subject = string.rstrip( re.sub("\n", " ", re.sub("^Summary \(one line\):\s*", "", new_subject, 1)) ) - - return (new_subject, new_body) - - # # entry point # diff --git a/ubuntutools/requestsync/common.py b/ubuntutools/requestsync/common.py index 2eb305b..149513f 100644 --- a/ubuntutools/requestsync/common.py +++ b/ubuntutools/requestsync/common.py @@ -19,8 +19,12 @@ # Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. +import os import sys import urllib2 +import re +import tempfile +import subprocess from debian_bundle.changelog import Changelog def raw_input_exit_on_ctrlc(*args, **kwargs): @@ -60,3 +64,48 @@ def getDebianChangelog(srcpkg, version): new_entries += str(block) return new_entries + +def edit_report(subject, body, changes_required = False): + '''Edit a report (consisting of subject and body) in sensible-editor. + + subject and body get decorated, before they are written to the + temporary file and undecorated after editing again. + If changes_required is True and the file has not been edited (according + to its mtime), an error is written to STDERR and the program exits. + + Returns (new_subject, new_body). + ''' + + report = 'Summary (one line):\n%s\n\nDescription:\n%s' % (subject, body) + + # Create tempfile and remember mtime + report_file = tempfile.NamedTemporaryFile(prefix='requestsync_') + report_file.file.write(report) + report_file.file.flush() + mtime_before = os.stat(report_file.name).st_mtime + + # Launch editor + try: + editor = subprocess.check_call(['sensible-editor', report_file.name]) + except subprocess.CalledProcessError, e: + print >> sys.stderr, 'Error calling sensible-editor: %s\nAborting.' % (e,) + sys.exit(1) + + # Check if the tempfile has been changed + if changes_required: + report_file_info = os.stat(report_file.name) + if mtime_before == os.stat(report_file.name).st_mtime: + print >> sys.stderr, 'The temporary file %s has not been changed, but you have\nto explain why the Ubuntu changes can be dropped. Aborting. [Press ENTER]' % (report_file.name,) + raw_input() + sys.exit(1) + + report_file.file.seek(0) + report = report_file.file.read() + report_file.file.close() + + # Undecorate report again + (new_subject, new_body) = report.split("\nDescription:\n", 1) + # Remove prefix and whitespace from subject + new_subject = re.sub('^Summary \(one line\):\s*', '', new_subject, 1).strip() + + return (new_subject, new_body) From 6d924143c08b608ad11f67dca2ccc251b83d6869 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Fri, 7 Aug 2009 14:07:46 +0200 Subject: [PATCH 09/18] requestsync: refactor 'checkNeedsSponsorship' --- requestsync | 28 +--------------------------- ubuntutools/requestsync/lp.py | 21 ++++++++++++++++++++- ubuntutools/requestsync/mail.py | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/requestsync b/requestsync index 0c34bf7..b3b51d6 100755 --- a/requestsync +++ b/requestsync @@ -42,32 +42,6 @@ import ubuntutools.common from ubuntutools.requestsync.mail import * from ubuntutools.requestsync.common import * -def checkNeedsSponsorship(srcpkg): - """ - Check that the user has the appropriate permissions by checking what - Launchpad returns when we check if someone can upload a package or not. - - If they are an indirect or direct member of the ~ubuntu-dev team on - Launchpad - sponsorship is not required if the package is in the - universe / multiverse component. - - If they are in the ~ubuntu-core-dev team, no sponsorship required. - """ - if not LpApiWrapper.canUploadPackage(srcpkg): - - print "You are not able to upload this package directly to Ubuntu.\n" \ - "Your sync request shall require an approval by a member of " \ - "the appropriate sponsorship team, who shall be subscribed to " \ - "this bug report.\n" \ - "This must be done before it can be processed by a member of " \ - "the Ubuntu Archive team." - print "If the above is correct please press Enter." - raw_input_exit_on_ctrlc() # Abort if necessary. - return True # Sponsorship required. - - # Is a team member, no sponsorship required. - return False - def checkExistingReports(package): """ Check existing bug reports on Launchpad for a possible sync request. @@ -371,7 +345,7 @@ if __name__ == '__main__': sys.exit(1) # -s flag not specified - check if we do need sponsorship. - if not sponsorship: sponsorship = checkNeedsSponsorship(srcpkg) + if not sponsorship: sponsorship = needSponsorship(srcpkg, component) # Check for existing package reports. if not newsource and use_lp_bugs: checkExistingReports(srcpkg) diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index f69080e..541854e 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -20,7 +20,8 @@ # Please see the /usr/share/common-licenses/GPL-2 file for the full text # of the GNU General Public License license. -from ..lp.lpapiwrapper import Distribution +from .common import raw_input_exit_on_ctrlc +from ..lp.lpapiwrapper import Distribution, PersonTeam from ..lp.udtexceptions import * def getDebianSrcPkg(name, release): @@ -38,3 +39,21 @@ def getUbuntuSrcPkg(name, release): ubuntu_archive = ubuntu.getArchive() return ubuntu_archive.getSourcePackage(name, release) + +def needSponsorship(name, component): + ''' + Check if the user has upload permissions for either the package + itself or the component + ''' + archive = Distribution('ubuntu').getArchive() + + need_sponsor = not PersonTeam.getMe().canUploadPackage(archive, name, component) + if need_sponsor: + print '''You are not able to upload this package directly to Ubuntu. +Your sync request shall require an approval by a member of the appropriate +sponsorship team, who shall be subscribed to this bug report. +This must be done before it can be processed by a member of the Ubuntu Archive +team.''' + raw_input_exit_on_ctrlc('If the above is correct please press [Enter]: ' + + return need_sponsor diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 1a7a724..fd61eb3 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -22,6 +22,7 @@ import os import sys import subprocess +from .common import raw_input_exit_on_ctrlc from ..lp.udtexceptions import PackageNotFoundException __all__ = ['getDebianSrcPkg', 'getUbuntuSrcPkg'] @@ -93,3 +94,20 @@ def get_email_address(): 'EMAIL needs to be set to let this script mail the ' \ 'sync request.' return myemailaddr + +def needSponsorship(name, component): + ''' + Ask the user if he has upload permissions for the package or the + component. + ''' + + while 1: + print "Do you have upload permissions for the '%s' component " \ + "or the package '%s'?" % (component, name) + val = raw_input_exit_on_ctrlc("If in doubt answer 'no'. [y/N]? ") + if val.lower() in ('y', 'yes'): + return False + elif val.lower() in ('n', 'no', ''): + return True + else: + print 'Invalid answer' From 7ff9aa777afc101dac4c06c672807d9201f9ece2 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Wed, 12 Aug 2009 13:14:50 +0200 Subject: [PATCH 10/18] requestsync, ubuntutools/requestsync/common.py: Move the asking about editing the report to edit_report() --- requestsync | 53 ++++++-------------- ubuntutools/requestsync/common.py | 80 ++++++++++++++++++------------- ubuntutools/requestsync/mail.py | 2 +- 3 files changed, 63 insertions(+), 72 deletions(-) diff --git a/requestsync b/requestsync index d0257c7..acb1c22 100755 --- a/requestsync +++ b/requestsync @@ -133,15 +133,13 @@ def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None) if keyid: gpg_command.extend(('-u', keyid)) - in_confirm_loop = True - while in_confirm_loop: - # sign it - gpg = subprocess.Popen(gpg_command, stdin = subprocess.PIPE, stdout = subprocess.PIPE) - signed_report = gpg.communicate(mailbody)[0] - assert gpg.returncode == 0 + # sign it + gpg = subprocess.Popen(gpg_command, stdin = subprocess.PIPE, stdout = subprocess.PIPE) + signed_report = gpg.communicate(mailbody)[0] + assert gpg.returncode == 0 - # generate email - mail = '''\ + # generate email + mail = '''\ From: %s To: %s Subject: %s @@ -149,19 +147,10 @@ Content-Type: text/plain; charset=UTF-8 %s''' % (myemailaddr, to, bugtitle, signed_report) - # ask for confirmation and allow to edit: - print mail - print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' - while 1: - val = raw_input_exit_on_ctrlc() - if val.lower() in ('y', 'yes'): - (bugtitle, mailbody) = edit_report(bugtitle, mailbody) - break - elif val.lower() in ('n', 'no', ''): - in_confirm_loop = False - break - else: - print "Invalid answer" + # ask for confirmation and allow to edit: + print mail + print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' + raw_input_exit_on_ctrlc() # get server address mailserver = os.getenv('DEBSMTP') @@ -232,22 +221,11 @@ def post_bug(source_package, subscribe, status, bugtitle, bugtext): # new source package product_url = "%subuntu" %launchpad._root_uri - in_confirm_loop = True - while in_confirm_loop: - print 'Summary:\n%s\n\nDescription:\n%s' % (bugtitle, bugtext) + print 'Summary:\n%s\n\nDescription:\n%s' % (bugtitle, bugtext) - # ask for confirmation and allow to edit: - print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' - while 1: - val = raw_input_exit_on_ctrlc() - if val.lower() in ('y', 'yes'): - (bugtitle, bugtext) = edit_report(bugtitle, bugtext) - break - elif val.lower() in ('n', 'no', ''): - in_confirm_loop = False - break - else: - print "Invalid answer." + # ask for confirmation and allow to edit: + print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' + raw_input_exit_on_ctrlc() # Create bug bug = launchpad.bugs.createBug(description=bugtext, title=bugtitle, target=product_url) @@ -420,8 +398,7 @@ if __name__ == '__main__': sys.exit(1) report += changelog + '\n' - if need_interaction: - (title, report) = edit_report(title, report, changes_required=True) + (title, report) = edit_report(title, report, changes_required = need_interaction) # Post sync request using Launchpad interface: srcpkg = not newsource and srcpkg or None diff --git a/ubuntutools/requestsync/common.py b/ubuntutools/requestsync/common.py index 149513f..8833ddd 100644 --- a/ubuntutools/requestsync/common.py +++ b/ubuntutools/requestsync/common.py @@ -66,46 +66,60 @@ def getDebianChangelog(srcpkg, version): return new_entries def edit_report(subject, body, changes_required = False): - '''Edit a report (consisting of subject and body) in sensible-editor. + ''' + Ask if the user wants to edit a report (consisting of subject and body) + in sensible-editor. - subject and body get decorated, before they are written to the - temporary file and undecorated after editing again. - If changes_required is True and the file has not been edited (according - to its mtime), an error is written to STDERR and the program exits. + If changes_required is True then the file has to be edited before we + can proceed. Returns (new_subject, new_body). ''' - report = 'Summary (one line):\n%s\n\nDescription:\n%s' % (subject, body) + editing_finished = False + while not editing_finished: + report = 'Summary (one line):\n%s\n\nDescription:\n%s' % (subject, body) - # Create tempfile and remember mtime - report_file = tempfile.NamedTemporaryFile(prefix='requestsync_') - report_file.file.write(report) - report_file.file.flush() - mtime_before = os.stat(report_file.name).st_mtime + if not changes_required: + print 'Currently the report looks as follows:\n%s' % report + while True: + val = raw_input_exit_on_ctrlc('Do you want to edit the report [y/N]? ') + if val.lower() in ('y', 'yes'): + break + elif val.lower() in ('n', 'no', ''): + editing_finished = True + break + else: + print 'Invalid answer.' - # Launch editor - try: - editor = subprocess.check_call(['sensible-editor', report_file.name]) - except subprocess.CalledProcessError, e: - print >> sys.stderr, 'Error calling sensible-editor: %s\nAborting.' % (e,) - sys.exit(1) + if not editing_finished: + # Create tempfile and remember mtime + report_file = tempfile.NamedTemporaryFile(prefix='requestsync_') + report_file.write(report) + report_file.flush() + mtime_before = os.stat(report_file.name).st_mtime - # Check if the tempfile has been changed - if changes_required: - report_file_info = os.stat(report_file.name) - if mtime_before == os.stat(report_file.name).st_mtime: - print >> sys.stderr, 'The temporary file %s has not been changed, but you have\nto explain why the Ubuntu changes can be dropped. Aborting. [Press ENTER]' % (report_file.name,) - raw_input() - sys.exit(1) + # Launch editor + try: + editor = subprocess.check_call(['sensible-editor', report_file.name]) + except subprocess.CalledProcessError, e: + print >> sys.stderr, 'Error calling sensible-editor: %s\nAborting.' % e + sys.exit(1) - report_file.file.seek(0) - report = report_file.file.read() - report_file.file.close() - - # Undecorate report again - (new_subject, new_body) = report.split("\nDescription:\n", 1) - # Remove prefix and whitespace from subject - new_subject = re.sub('^Summary \(one line\):\s*', '', new_subject, 1).strip() + # Check if the tempfile has been changed + if changes_required: + if mtime_before == os.stat(report_file.name).st_mtime: + print 'The report has not been changed, but you have to explain why ' \ + 'the Ubuntu changes can be dropped.' + raw_input_exit_on_ctrlc('Press [Enter] to retry or [Control-C] to abort. ') - return (new_subject, new_body) + report_file.seek(0) + report = report_file.read() + report_file.close() + + # Undecorate report again + (subject, body) = report.split("\nDescription:\n", 1) + # Remove prefix and whitespace from subject + subject = re.sub('^Summary \(one line\):\s*', '', subject, 1).strip() + + return (subject, body) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index fd61eb3..c9c2ac8 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -101,7 +101,7 @@ def needSponsorship(name, component): component. ''' - while 1: + while True: print "Do you have upload permissions for the '%s' component " \ "or the package '%s'?" % (component, name) val = raw_input_exit_on_ctrlc("If in doubt answer 'no'. [y/N]? ") From d96e4af643a1cd0d483f46842a54b770994eb26f Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Wed, 12 Aug 2009 13:46:21 +0200 Subject: [PATCH 11/18] requestsync: move post_bug() to ubuntutools/requestsync/lp.py --- requestsync | 48 ++--------------------------------- ubuntutools/requestsync/lp.py | 36 ++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 48 deletions(-) diff --git a/requestsync b/requestsync index acb1c22..6892165 100755 --- a/requestsync +++ b/requestsync @@ -41,6 +41,7 @@ import ubuntutools.common from ubuntutools.requestsync.mail import * from ubuntutools.requestsync.common import * +from ubuntutools.requestsync.lp import postBug def checkExistingReports(package): """ Check existing bug reports on Launchpad for a possible sync request. @@ -199,51 +200,6 @@ Content-Type: text/plain; charset=UTF-8 return True -def post_bug(source_package, subscribe, status, bugtitle, bugtext): - '''Use python-launchpadlib to submit the sync request. - Return True if successfully posted, otherwise False.''' - - import glob, os.path - - try: - launchpad = Launchpad.login() - except ImportError: - print >> sys.stderr, 'Importing launchpadlib failed. Is python-launchpadlib installed?' - return False - except IOError, msg: - # No credentials found. - print msg - sys.exit(1) - - if source_package: - product_url = "%subuntu/+source/%s" %(launchpad._root_uri, source_package) - else: - # new source package - product_url = "%subuntu" %launchpad._root_uri - - print 'Summary:\n%s\n\nDescription:\n%s' % (bugtitle, bugtext) - - # ask for confirmation and allow to edit: - print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' - raw_input_exit_on_ctrlc() - - # Create bug - bug = launchpad.bugs.createBug(description=bugtext, title=bugtitle, target=product_url) - - #newly created bugreports have one task - task = bug.bug_tasks[0] - # Only members of ubuntu-bugcontrol can set importance - if PersonTeam.getMe().isLpTeamMember('ubuntu-bugcontrol'): - task.importance = 'Wishlist' - task.status = status - task.lp_save() - - subscribe_url = "%s~%s" %(launchpad._root_uri, subscribe) - bug.subscribe(person=subscribe_url) - - print 'Sync request filed as bug #%i: %s' % (bug.id, - lp_libsupport.translate_api_web(bug.self_link)) - return True # # entry point @@ -405,7 +361,7 @@ if __name__ == '__main__': if use_lp_bugs: # Map status to the values expected by lp-bugs mapping = {'new': 'New', 'confirmed': 'Confirmed'} - if post_bug(srcpkg, subscribe, mapping[status], title, report): + if postBug(srcpkg, subscribe, mapping[status], title, report): sys.exit(0) # Abort on error: print 'Something went wrong. No sync request filed.' diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index 541854e..d88ffbf 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -21,8 +21,9 @@ # of the GNU General Public License license. from .common import raw_input_exit_on_ctrlc -from ..lp.lpapiwrapper import Distribution, PersonTeam +from ..lp.lpapiwrapper import Launchpad, Distribution, PersonTeam, DistributionSourcePackage from ..lp.udtexceptions import * +from ..lp.lp_libsupport import translate_api_web def getDebianSrcPkg(name, release): debian = Distribution('debian') @@ -54,6 +55,37 @@ Your sync request shall require an approval by a member of the appropriate sponsorship team, who shall be subscribed to this bug report. This must be done before it can be processed by a member of the Ubuntu Archive team.''' - raw_input_exit_on_ctrlc('If the above is correct please press [Enter]: ' + raw_input_exit_on_ctrlc('If the above is correct please press [Enter]: ') return need_sponsor + +def postBug(srcpkg, subscribe, status, bugtitle, bugtext): + ''' + Use the LP API to file the sync request. + ''' + + print 'The final report is:\nSummary: %s\nDescription:\n%s\n' % (bugtitle, bugtext) + raw_input_exit_on_ctrlc('Press [Enter] to continue and [Ctrl-C] to abort. ') + + if srcpkg: + bug_target = DistributionSourcePackage( + '%subuntu/+source/%s' % (Launchpad._root_uri, srcpkg)) + else: + # new source package + bug_target = Distribution('ubuntu') + + # create bug + bug = Launchpad.bugs.createBug(title = bugtitle, description = bugtext, target = bug_target) + + # newly created bugreports have only one task + task = bug.bug_tasks[0] + # only members of ubuntu-bugcontrol can set importance + if PersonTeam.getMe().isLpTeamMember('ubuntu-bugcontrol'): + task.importance = 'Wishlist' + task.status = status + task.lp_save() + + bug.subscribe(person = PersonTeam(subscribe)) + + print 'Sync request filed as bug #%i: %s' % (bug.id, + translate_api_web(bug.self_link)) From ec92bb5d754c5147db8b272a1a6ba1a4cdc09cbb Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Sat, 22 Aug 2009 11:59:22 +0200 Subject: [PATCH 12/18] requestsync: move the remaining code of cur_version_component() into the __main__ code. --- requestsync | 24 +++++++++++------------- ubuntutools/requestsync/lp.py | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/requestsync b/requestsync index bf63546..e73b39c 100755 --- a/requestsync +++ b/requestsync @@ -92,17 +92,6 @@ def checkExistingReports(package): "please press enter." raw_input_exit_on_ctrlc() -def cur_version_component(sourcepkg, release): - - try: - src = getUbuntuSrcPkg(sourcepkg, release) - return (src.getVersion(), src.getComponent()) - - except udtexceptions.PackageNotFoundException: - - print "%s doesn't appear to exist in %s, specify -n for a package not in Ubuntu." % (sourcepkg, release) - sys.exit(1) - def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None): '''Submit the sync request per email. Return True if email successfully send, otherwise False.''' @@ -265,8 +254,17 @@ if __name__ == '__main__': (cur_ver, component) = ('0', 'universe') # Let's assume universe - # Find Ubuntu release's package version. - if not newsource: (cur_ver, component) = cur_version_component(srcpkg, release) + # Find Ubuntu release's package version. + try: + ubuntusrcpkg = getUbuntuSrcPkg(srcpkg, release) + cur_ver = ubuntusrcpkg.getVersion() + component = ubuntusrcpkg.getComponent() + except udtexceptions.PackageNotFoundException: + if not newsource: + print "'%s' doesn't exist in 'Ubuntu %s'.\nDo you want to sync a new package?" % \ + (srcpkg, release) + raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') + newsource = True # TODO: set it for now, but check code if it's needed debsrcpkg = getDebianSrcPkg(srcpkg, distro) debiancomponent = debsrcpkg.getComponent() diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index d88ffbf..c8cf5ff 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -65,7 +65,7 @@ def postBug(srcpkg, subscribe, status, bugtitle, bugtext): ''' print 'The final report is:\nSummary: %s\nDescription:\n%s\n' % (bugtitle, bugtext) - raw_input_exit_on_ctrlc('Press [Enter] to continue and [Ctrl-C] to abort. ') + raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') if srcpkg: bug_target = DistributionSourcePackage( From e628bfbe348b24d63a89cf43fe4f42a62cef03a1 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Sat, 22 Aug 2009 17:12:55 +0200 Subject: [PATCH 13/18] requestsync: - move mail_bug() to ubuntutools.requestsync.mail - implement support for UBU* environment variables (lp: #400133) --- debian/changelog | 4 +- requestsync | 101 +------------------------------- ubuntutools/requestsync/mail.py | 94 +++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 104 deletions(-) diff --git a/debian/changelog b/debian/changelog index ba79c1c..eaf805a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,8 @@ ubuntu-dev-tools (0.76) UNRELEASED; urgency=low [ Michael Bienia ] * Drop python-launchpad-bugs from Depends. * buildd: Add a --batch mode for batch retrying/rescoring of packages. + * requestsync: + - Use UBU* environment variables before the DEB* ones (lp: #400133) [ Iain Lane ] * requestsync: @@ -39,7 +41,7 @@ ubuntu-dev-tools (0.76) UNRELEASED; urgency=low - debian/rules: set DEB_PYTHON_SYSTEM to pysupport. - ubuntu-dev-tools.preinst: remove stale pycentral files on upgrades. - -- Luca Falavigna Fri, 21 Aug 2009 17:30:05 +0200 + -- Michael Bienia Sat, 22 Aug 2009 17:10:13 +0200 ubuntu-dev-tools (0.75) karmic; urgency=low diff --git a/requestsync b/requestsync index e73b39c..87ee6c8 100755 --- a/requestsync +++ b/requestsync @@ -92,103 +92,6 @@ def checkExistingReports(package): "please press enter." raw_input_exit_on_ctrlc() -def mail_bug(source_package, subscribe, status, bugtitle, bugtext, keyid = None): - '''Submit the sync request per email. - Return True if email successfully send, otherwise False.''' - - import smtplib - import socket - - to = 'new@bugs.launchpad.net' - - myemailaddr = get_email_address() - if not myemailaddr: - return False - - # generate initial mailbody - mailbody = '' - if source_package: - mailbody += ' affects ubuntu/%s\n' % source_package - else: - mailbody += ' affects ubuntu\n' - mailbody = mailbody + ' status %s\n importance wishlist\n subscribe %s\n done\n\n%s' % (status, subscribe, bugtext) - - # prepare sign_command - sign_command = 'gpg' - for cmd in ('gpg2', 'gnome-gpg'): - if os.access('/usr/bin/%s' % cmd, os.X_OK): - sign_command = cmd - - gpg_command = [sign_command, '--clearsign'] - if keyid: - gpg_command.extend(('-u', keyid)) - - # sign it - gpg = subprocess.Popen(gpg_command, stdin = subprocess.PIPE, stdout = subprocess.PIPE) - signed_report = gpg.communicate(mailbody)[0] - assert gpg.returncode == 0 - - # generate email - mail = '''\ -From: %s -To: %s -Subject: %s -Content-Type: text/plain; charset=UTF-8 - -%s''' % (myemailaddr, to, bugtitle, signed_report) - - # ask for confirmation and allow to edit: - print mail - print 'Do you want to edit the report before sending [y/N]? Press Control-C to abort.' - raw_input_exit_on_ctrlc() - - # get server address - mailserver = os.getenv('DEBSMTP') - if mailserver: - print 'Using custom SMTP server:', mailserver - else: - mailserver = 'fiordland.ubuntu.com' - - # get server port - mailserver_port = os.getenv('DEBSMTP_PORT') - if mailserver_port: - print 'Using custom SMTP port:', mailserver_port - else: - mailserver_port = 25 - - # connect to the server - try: - s = smtplib.SMTP(mailserver, mailserver_port) - except socket.error, s: - print >> sys.stderr, "Could not connect to mailserver %s at port %s: %s (%i)" % \ - (mailserver, mailserver_port, s[1], s[0]) - print "The port %s may be firewalled. Please try using requestsync with" \ - % mailserver_port - print "the '--lp' flag to file a sync request with the launchpadlib " \ - "module." - return False - - # authenticate to the server - mailserver_user = os.getenv('DEBSMTP_USER') - mailserver_pass = os.getenv('DEBSMTP_PASS') - if mailserver_user and mailserver_pass: - try: - s.login(mailserver_user, mailserver_pass) - except smtplib.SMTPAuthenticationError: - print 'Error authenticating to the server: invalid username and password.' - s.quit() - return False - except: - print 'Unknown SMTP error.' - s.quit() - return False - - s.sendmail(myemailaddr, to, mail) - s.quit() - print 'Sync request mailed.' - - return True - # # entry point @@ -232,7 +135,7 @@ if __name__ == '__main__': distro = options.dist ffe = options.ffe - if not use_lp_bugs and not get_email_address(): + if not use_lp_bugs and not getEmailAddress(): sys.exit(1) if len(args) == 0: @@ -366,7 +269,7 @@ if __name__ == '__main__': sys.exit(1) # Mail sync request: - if mail_bug(srcpkg, subscribe, status, title, report, keyid): + if mailBug(srcpkg, subscribe, status, title, report, keyid): sys.exit(0) print 'Something went wrong. No sync request filed.' diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index c9c2ac8..1e00081 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -22,6 +22,8 @@ import os import sys import subprocess +import smtplib +import socket from .common import raw_input_exit_on_ctrlc from ..lp.udtexceptions import PackageNotFoundException @@ -83,12 +85,12 @@ def getDebianSrcPkg(name, release): def getUbuntuSrcPkg(name, release): return getSrcPkg('ubuntu', name, release) -def get_email_address(): +def getEmailAddress(): ''' - Get the From email address from the DEBEMAIL or EMAIL environment - variable or give an error. + Get the From email address from the UBUMAIL, DEBEMAIL or EMAIL + environment variable or give an error. ''' - myemailaddr = os.getenv('DEBEMAIL') or os.getenv('EMAIL') + myemailaddr = os.getenv('UBUMAIL') or os.getenv('DEBEMAIL') or os.getenv('EMAIL') if not myemailaddr: print >> sys.stderr, 'The environment variable DEBEMAIL or ' \ 'EMAIL needs to be set to let this script mail the ' \ @@ -111,3 +113,87 @@ def needSponsorship(name, component): return True else: print 'Invalid answer' + +def mailBug(srcpkg, subscribe, status, bugtitle, bugtext, keyid = None): + ''' + Submit the sync request per email. + ''' + + to = 'new@bugs.launchpad.net' + + # getEmailAddress() can't fail here as the main code in requestsync + # already checks its return value + myemailaddr = getEmailAddress() + + # generate mailbody + if srcpkg: + mailbody = ' affects ubuntu/%s\n' % srcpkg.getPackageName() + else: + mailbody = ' affects ubuntu\n' + mailbody += '''\ + status %s + importance wishlist + subscribe %s + done + +%s''' % (status, subscribe, bugtext) + + # prepare sign command + gpg_command = None + for cmd in ('gpg', 'gpg2', 'gnome-gpg'): + if os.access('/usr/bin/%s' % cmd, os.X_OK): + gpg_command = [cmd] + assert gpg_command # TODO: catch exception and produce error message + + gpg_command.append('--clearsign') + if keyid: + gpg_command.extend(('-u', keyid)) + + # sign the mail body + gpg = subprocess.Popen(gpg_command, stdin = subprocess.PIPE, stdout = subprocess.PIPE) + signed_report = gpg.communicate(mailbody)[0] + assert gpg.returncode == 0 + + # generate email + mail = '''\ +From: %s +To: %s +Subject: %s +Content-Type: text/plain; charset=UTF-8 + +%s''' % (myemailaddr, to, bugtitle, signed_report) + + print 'The final report is:\n%s' % mail + raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') + + # get server address and port + mailserver_host = os.getenv('UBUSMTP') or os.getenv('DEBSMTP') or 'fiordland.ubuntu.com' + mailserver_port = os.getenv('UBUSMTP_PORT') or os.getenv('DEBSMTP_PORT') or 25 + + # connect to the server + try: + print 'Connecting to %s:%s ...' % (mailserver_host, mailserver_port) + s = smtplib.SMTP(mailserver_host, mailserver_port) + except socket.error, s: + print >> sys.stderr, "Could not connect to %s:%s: %s (%i)" % \ + (mailserver_host, mailserver_port, s[1], s[0]) + return + + # authenticate to the server + mailserver_user = os.getenv('UBUSMTP_USER') or os.getenv('DEBSMTP_USER') + mailserver_pass = os.getenv('UBUSMTP_PASS') or os.getenv('DEBSMTP_PASS') + if mailserver_user and mailserver_pass: + try: + s.login(mailserver_user, mailserver_pass) + except smtplib.SMTPAuthenticationError: + print 'Error authenticating to the server: invalid username and password.' + s.quit() + return + except: + print 'Unknown SMTP error.' + s.quit() + return + + s.sendmail(myemailaddr, to, mail) + s.quit() + print 'Sync request mailed.' From 5448add7543c25dbde41435b59bbb9b226ae6a38 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Sat, 22 Aug 2009 17:39:38 +0200 Subject: [PATCH 14/18] requestsync: make a "mail" and "lp" version of checkExistingReports and move it to the correct module --- requestsync | 50 --------------------------------- ubuntutools/requestsync/lp.py | 21 ++++++++++++++ ubuntutools/requestsync/mail.py | 14 ++++++++- 3 files changed, 34 insertions(+), 51 deletions(-) diff --git a/requestsync b/requestsync index 87ee6c8..125e19f 100755 --- a/requestsync +++ b/requestsync @@ -43,56 +43,6 @@ from ubuntutools.requestsync.mail import * from ubuntutools.requestsync.common import * from ubuntutools.requestsync.lp import postBug -def checkExistingReports(package): - """ Check existing bug reports on Launchpad for a possible sync request. - - If found ask for confirmation on filing a request. - """ - - launchpad = None - - try: - launchpad = Launchpad.login() - except ImportError: - print >> sys.stderr, 'Importing launchpadlib failed. Is ' \ - 'python-launchpadlib installed?' - except IOError, msg: - # No credentials found. - print msg - - # Failed to get Launchpad credentials. - if launchpad is None: - print >> sys.stderr, "Skipping existing report check, you should "\ - "manually see if there are any at:" - print "- https://bugs.launchpad.net/ubuntu/+source/%s" % package - print "" - return False - - # Fetch the package's bug list from Launchpad. - pkg = Distribution('ubuntu').getSourcePackage(name=package) - pkgBugList = pkg.searchTasks() - - # Search bug list for other sync requests. - matchingBugs = [bug for bug in pkgBugList - if "Sync %s" % package in bug.title - or "Please sync %s" % package in bug.title] - - if len(matchingBugs) == 0: - return # No sync bugs found. - - print "The following bugs could be possible duplicate sync bug(s) on Launchpad:" - - for bug in matchingBugs: - print " *", bug.title - print " -", lp_libsupport.translate_api_web(bug.self_link) - - print "Please check the above URLs to verify this before filing a " \ - "possible duplicate report." - print "Press Ctrl-C to stop filing the bug report now, otherwise " \ - "please press enter." - raw_input_exit_on_ctrlc() - - # # entry point # diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index c8cf5ff..5d14ade 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -59,6 +59,27 @@ team.''' return need_sponsor +def checkExistingReports(srcpkg): + ''' + Check existing bug reports on Launchpad for a possible sync request. + + If found ask for confirmation on filing a request. + ''' + + # Fetch the package's bug list from Launchpad + pkg = Distribution('ubuntu').getSourcePackage(name = srcpkg.getPackageName()) + pkgBugList = pkg.getBugTasks() + + # Search bug list for other sync requests. + for bug in pkgBugList: + # check for Sync or sync and the package name + if 'ync %s' % package in bug.title: + print 'The following bug could be a possible duplicate sync bug on Launchpad:' + print ' * Bug #%i: %s (%s)' % \ + (bug.id, bug.title, translate_api_web(bug.self_link)) + print 'Please check the above URL to verify this before continuing.' + raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') + def postBug(srcpkg, subscribe, status, bugtitle, bugtext): ''' Use the LP API to file the sync request. diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 1e00081..3475ba2 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -27,7 +27,12 @@ import socket from .common import raw_input_exit_on_ctrlc from ..lp.udtexceptions import PackageNotFoundException -__all__ = ['getDebianSrcPkg', 'getUbuntuSrcPkg'] +__all__ = [ + 'getDebianSrcPkg', + 'getUbuntuSrcPkg', + 'getEmailAddress', + 'postBug', + ] class SourcePackagePublishingHistory(object): ''' @@ -114,6 +119,13 @@ def needSponsorship(name, component): else: print 'Invalid answer' +def checkExistingReports(srcpkg): + ''' + Point the user to the URL to manually check for duplicate bug reports. + ''' + print 'Please check on https://bugs.launchpad.net/ubuntu/+source/%s/+bugs for duplicate sync requests before continuing.' + raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') + def mailBug(srcpkg, subscribe, status, bugtitle, bugtext, keyid = None): ''' Submit the sync request per email. From d5a19ca5a7ac2539e2ba92a570584a489fda41cf Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Sat, 22 Aug 2009 18:07:26 +0200 Subject: [PATCH 15/18] ubuntutools.requestsync.lp: fix errors in imports --- ubuntutools/requestsync/lp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index 5d14ade..5a288e2 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -21,9 +21,9 @@ # of the GNU General Public License license. from .common import raw_input_exit_on_ctrlc -from ..lp.lpapiwrapper import Launchpad, Distribution, PersonTeam, DistributionSourcePackage +from ..lp.lpapicache import Launchpad, Distribution, PersonTeam, DistributionSourcePackage from ..lp.udtexceptions import * -from ..lp.lp_libsupport import translate_api_web +from ..lp.libsupport import translate_api_web def getDebianSrcPkg(name, release): debian = Distribution('debian') From 966ab3727ae9bbe821aa7f0ffa8802a33afba58d Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Sat, 22 Aug 2009 18:34:22 +0200 Subject: [PATCH 16/18] requestsync: reindent remaining code and small cleanup --- requestsync | 284 +++++++++++++++++++++++++--------------------------- 1 file changed, 137 insertions(+), 147 deletions(-) diff --git a/requestsync b/requestsync index 125e19f..94b4900 100755 --- a/requestsync +++ b/requestsync @@ -26,87 +26,87 @@ # # ################################################################## -import os -import subprocess import sys -from debian_bundle.changelog import Version from optparse import OptionParser +from debian_bundle.changelog import Version -# ubuntu-dev-tools modules. -import ubuntutools.lp.libsupport as lp_libsupport -import ubuntutools.lp.udtexceptions as udtexceptions -from ubuntutools.lp.lpapicache import Launchpad, LpApiWrapper, Distribution, PersonTeam +# ubuntu-dev-tools modules +from ubuntutools.lp import udtexceptions +from ubuntutools.requestsync.common import * # https_proxy fix import ubuntutools.common -from ubuntutools.requestsync.mail import * -from ubuntutools.requestsync.common import * -from ubuntutools.requestsync.lp import postBug - # # entry point # if __name__ == '__main__': - # Our usage options. - usage = "Usage: %prog [-d distro] [-k keyid] [-n] [--lp] [-s] [-e] " - usage += " [ [base version]]" - optParser = OptionParser(usage) + # Our usage options. + usage = 'Usage: %prog [-d distro] [-k keyid] [-n] [--lp] [-s] [-e] ' \ + ' [ [base version]]' + optParser = OptionParser(usage) - optParser.add_option("-d", type = "string", - dest = "dist", default = "unstable", - help = "Debian distribution to sync from.") - optParser.add_option("-k", type = "string", - dest = "keyid", default = None, - help = "GnuPG key ID to use for signing report.") - optParser.add_option("-n", action = "store_true", - dest = "newpkg", default = False, - help = "Whether package to sync is a new package in Ubuntu.") - optParser.add_option("--lp", action = "store_true", - dest = "lpbugs", default = False, - help = "Specify whether to use the launchpadlib module for filing " \ - "report.") - optParser.add_option("-s", action = "store_true", - dest = "sponsor", default = False, - help = "Force sponsorship requirement (shall be autodetected if not " \ - "specified).") - optParser.add_option("-e", action = "store_true", - dest = "ffe", default = False, - help = "Use this after FeatureFreeze for non-bug fix syncs, changes " \ - "default subscription to the appropriate release team.") + optParser.add_option('-d', type = 'string', + dest = 'dist', default = 'unstable', + help = 'Debian distribution to sync from.') + optParser.add_option('-k', type = 'string', + dest = 'keyid', default = None, + help = 'GnuPG key ID to use for signing report (only used when emailing the sync request).') + optParser.add_option('-n', action = 'store_true', + dest = 'newpkg', default = False, + help = 'Whether package to sync is a new package in Ubuntu.') + optParser.add_option('--lp', action = 'store_true', + dest = 'lpapi', default = False, + help = 'Specify whether to use the LP API for filing the sync request.') + optParser.add_option('-s', action = 'store_true', + dest = 'sponsor', default = False, + help = 'Force sponsorship') + optParser.add_option('-e', action = 'store_true', + dest = 'ffe', default = False, + help = 'Use this after FeatureFreeze for non-bug fix syncs, changes ' \ + 'default subscription to the appropriate release team.') - (options, args) = optParser.parse_args() + (options, args) = optParser.parse_args() - newsource = options.newpkg - sponsorship = options.sponsor - keyid = options.keyid - use_lp_bugs = options.lpbugs - need_interaction = False - distro = options.dist - ffe = options.ffe + if not len(args): + optParser.print_help() + sys.exit(1) - if not use_lp_bugs and not getEmailAddress(): - sys.exit(1) + # import the needed requestsync module + if options.lpapi: + from ubuntutools.requestsync.lp import * + from ubuntutools.lp.lpapicache import Distribution + else: + from ubuntutools.requestsync.mail import * + if not getEmailAddress(): + sys.exit(1) - if len(args) == 0: - optParser.print_help() - sys.exit(1) + newsource = options.newpkg + sponsorship = options.sponsor + keyid = options.keyid + lpapi = options.lpapi + need_interaction = False + distro = options.dist + ffe = options.ffe - if len(args) not in (2, 3): # no release specified, assume development release - release = Distribution('ubuntu').getDevelopmentSeries().name - print >> sys.stderr, ("Source package / target release missing - assuming %s " % - release) - else: - release = args[1] + if len(args) not in (2, 3): # no release specified, assume development release + if options.lpapi: + release = Distribution('ubuntu').getDevelopmentSeries().name + print >> sys.stderr, 'W: Target release missing - assuming %s' % release + else: + print >> sys.stderr, 'E: Source package or target release missing. Exiting.' + sys.exit(1) + else: + release = args[1] - srcpkg = args[0] - force_base_ver = None + srcpkg = args[0] + force_base_ver = None + + # Base version specified. + if len(args) == 3: force_base_ver = args[2] - # Base version specified. - if len(args) == 3: force_base_ver = args[2] + (cur_ver, component) = ('0', 'universe') # Let's assume universe - (cur_ver, component) = ('0', 'universe') # Let's assume universe - # Find Ubuntu release's package version. try: ubuntusrcpkg = getUbuntuSrcPkg(srcpkg, release) @@ -119,108 +119,98 @@ if __name__ == '__main__': raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') newsource = True # TODO: set it for now, but check code if it's needed - debsrcpkg = getDebianSrcPkg(srcpkg, distro) - debiancomponent = debsrcpkg.getComponent() - # Find Debian release's package version. - deb_version = debsrcpkg.getVersion() + debsrcpkg = getDebianSrcPkg(srcpkg, distro) + debiancomponent = debsrcpkg.getComponent() + # Find Debian release's package version. + deb_version = debsrcpkg.getVersion() - # Debian and Ubuntu versions are the same - stop. - if deb_version == cur_ver: - print 'The versions in Debian and Ubuntu are the same already (%s). Aborting.' % (deb_version,) - sys.exit(1) + # Debian and Ubuntu versions are the same - stop. + if deb_version == cur_ver: + print 'The versions in Debian and Ubuntu are the same already (%s). Aborting.' % (deb_version,) + sys.exit(1) - # -s flag not specified - check if we do need sponsorship. - if (not sponsorship): + # -s flag not specified - check if we do need sponsorship. + if (not sponsorship): if (not newsource): sponsorship = needsSponsorship(srcpkg, component) else: sponsorship = not PersonTeam.getMe().isLpTeamMember('motu') # assume going to universe - # Check for existing package reports. - if (not newsource) and use_lp_bugs: checkExistingReports(srcpkg) + # Check for existing package reports. + if (not newsource) and use_lp_bugs: checkExistingReports(srcpkg) - # Generate bug report. - subscribe = 'ubuntu-archive' - status = 'confirmed' - if sponsorship == True: - status = 'new' - if component in ['main', 'restricted']: - subscribe = 'ubuntu-main-sponsors' - else: - subscribe = 'ubuntu-universe-sponsors' - if ffe == True: - status = 'new' - if component in ['main', 'restricted']: - subscribe = 'ubuntu-release' - else: - subscribe = 'motu-release' + # Generate bug report. + subscribe = 'ubuntu-archive' + status = 'confirmed' + if sponsorship == True: + status = 'new' + if component in ['main', 'restricted']: + subscribe = 'ubuntu-main-sponsors' + else: + subscribe = 'ubuntu-universe-sponsors' + if ffe == True: + status = 'new' + if component in ['main', 'restricted']: + subscribe = 'ubuntu-release' + else: + subscribe = 'motu-release' + pkg_to_sync = '%s %s (%s) from Debian %s (%s)' % (srcpkg, deb_version, component, distro, debiancomponent) + title = "Sync %s" % pkg_to_sync + if ffe == True: + title = "FFe: " + title + report = "Please sync %s\n\n" % pkg_to_sync - pkg_to_sync = '%s %s (%s) from Debian %s (%s)' % (srcpkg, deb_version, component, distro, debiancomponent) - title = "Sync %s" % pkg_to_sync - if ffe == True: - title = "FFe: " + title - report = "Please sync %s\n\n" % pkg_to_sync - - base_ver = cur_ver - uidx = base_ver.find('ubuntu') - if uidx > 0: - base_ver = base_ver[:uidx] - need_interaction = True + base_ver = cur_ver + uidx = base_ver.find('ubuntu') + if uidx > 0: + base_ver = base_ver[:uidx] + need_interaction = True - print 'Changes have been made to the package in Ubuntu.' - print 'Please edit the report and give an explanation.' - print 'Press ENTER to start your editor. Press Control-C to abort now.' - print 'Not saving the report file will abort the request, too.' - raw_input_exit_on_ctrlc() - report += 'Explanation of the Ubuntu delta and why it can be dropped:\n' + \ - '>>> ENTER_EXPLANATION_HERE <<<\n\n' + print 'Changes have been made to the package in Ubuntu.' + print 'Please edit the report and give an explanation.' + print 'Press ENTER to start your editor. Press Control-C to abort now.' + print 'Not saving the report file will abort the request, too.' + raw_input_exit_on_ctrlc() + report += 'Explanation of the Ubuntu delta and why it can be dropped:\n' + \ + '>>> ENTER_EXPLANATION_HERE <<<\n\n' - if ffe == True: - need_interaction = True + if ffe == True: + need_interaction = True - print 'To approve FeatureFreeze exception, you need to state ' - print 'the reason why you feel it is necessary.' - print 'Press ENTER to start your editor. Press Control-C to abort now.' - print 'Not saving the report file will abort the request, too.' - raw_input_exit_on_ctrlc() - report += 'Explanation of FeatureFreeze exception:\n' + \ - '>>> ENTER_EXPLANATION_HERE <<<\n\n' + print 'To approve FeatureFreeze exception, you need to state ' + print 'the reason why you feel it is necessary.' + print 'Press ENTER to start your editor. Press Control-C to abort now.' + print 'Not saving the report file will abort the request, too.' + raw_input_exit_on_ctrlc() + report += 'Explanation of FeatureFreeze exception:\n' + \ + '>>> ENTER_EXPLANATION_HERE <<<\n\n' + # Check if they have a per-package upload permission. + if LpApiWrapper.isPerPackageUploader(srcpkg): + report += 'Note that I have per-package upload permissions for %s.\n\n' % srcpkg - # Check if they have a per-package upload permission. - if LpApiWrapper.isPerPackageUploader(srcpkg): - report += 'Note that I have per-package upload permissions for %s.\n\n' % srcpkg + uidx = base_ver.find('build') + if uidx > 0: + base_ver = base_ver[:uidx] - uidx = base_ver.find('build') - if uidx > 0: - base_ver = base_ver[:uidx] + if force_base_ver: + base_ver = force_base_ver - if force_base_ver: - base_ver = force_base_ver + if not newsource: report += 'Changelog since current %s version %s:\n\n' % (release, cur_ver) + changelog = getDebianChangelog(debsrcpkg, Version(base_ver)) + if not changelog: + sys.exit(1) + report += changelog + '\n' - if not newsource: report += 'Changelog since current %s version %s:\n\n' % (release, cur_ver) - changelog = getDebianChangelog(debsrcpkg, Version(base_ver)) - if not changelog: - sys.exit(1) - report += changelog + '\n' + (title, report) = edit_report(title, report, changes_required = need_interaction) - (title, report) = edit_report(title, report, changes_required = need_interaction) - - # Post sync request using Launchpad interface: - srcpkg = not newsource and srcpkg or None - if use_lp_bugs: - # Map status to the values expected by lp-bugs - mapping = {'new': 'New', 'confirmed': 'Confirmed'} - if postBug(srcpkg, subscribe, mapping[status], title, report): - sys.exit(0) - # Abort on error: - print 'Something went wrong. No sync request filed.' - sys.exit(1) - - # Mail sync request: - if mailBug(srcpkg, subscribe, status, title, report, keyid): - sys.exit(0) - - print 'Something went wrong. No sync request filed.' - sys.exit(1) + # Post sync request using Launchpad interface: + srcpkg = not newsource and srcpkg or None + if options.lpapi: + # Map status to the values expected by lp-bugs + mapping = {'new': 'New', 'confirmed': 'Confirmed'} + postBug(srcpkg, subscribe, mapping[status], title, report) + else: + # Mail sync request: + mailBug(srcpkg, subscribe, status, title, report, keyid) From f284ee7cd61ec526cde54a0a6fb41df60520f1a4 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Sun, 23 Aug 2009 13:08:22 +0200 Subject: [PATCH 17/18] requestsync: cleanup --- requestsync | 207 ++++++++++++++++---------------- ubuntutools/requestsync/lp.py | 2 +- ubuntutools/requestsync/mail.py | 16 +-- 3 files changed, 113 insertions(+), 112 deletions(-) diff --git a/requestsync b/requestsync index 94b4900..64a929e 100755 --- a/requestsync +++ b/requestsync @@ -57,9 +57,9 @@ if __name__ == '__main__': help = 'Whether package to sync is a new package in Ubuntu.') optParser.add_option('--lp', action = 'store_true', dest = 'lpapi', default = False, - help = 'Specify whether to use the LP API for filing the sync request.') + help = 'Specify whether to use the LP API for filing the sync request (recommended).') optParser.add_option('-s', action = 'store_true', - dest = 'sponsor', default = False, + dest = 'sponsorship', default = False, help = 'Force sponsorship') optParser.add_option('-e', action = 'store_true', dest = 'ffe', default = False, @@ -75,142 +75,143 @@ if __name__ == '__main__': # import the needed requestsync module if options.lpapi: from ubuntutools.requestsync.lp import * - from ubuntutools.lp.lpapicache import Distribution + from ubuntutools.lp.lpapicache import Distribution, PersonTeam else: from ubuntutools.requestsync.mail import * if not getEmailAddress(): sys.exit(1) newsource = options.newpkg - sponsorship = options.sponsor - keyid = options.keyid - lpapi = options.lpapi - need_interaction = False + sponsorship = options.sponsorship distro = options.dist ffe = options.ffe + lpapi = options.lpapi + need_interaction = False + force_base_version = None + srcpkg = args[0] - if len(args) not in (2, 3): # no release specified, assume development release - if options.lpapi: + if len(args) == 1: + if lpapi: release = Distribution('ubuntu').getDevelopmentSeries().name print >> sys.stderr, 'W: Target release missing - assuming %s' % release else: print >> sys.stderr, 'E: Source package or target release missing. Exiting.' sys.exit(1) - else: + elif len(args) == 2: release = args[1] + elif len(args) == 3: + release = args[1] + force_base_version = Version(args[2]) + else: + print >> sys.stderr, 'E: Too many arguments.' + optParser.print_help() + sys.exit(1) - srcpkg = args[0] - force_base_ver = None - - # Base version specified. - if len(args) == 3: force_base_ver = args[2] - - (cur_ver, component) = ('0', 'universe') # Let's assume universe - - # Find Ubuntu release's package version. + # Get the current Ubuntu source package try: - ubuntusrcpkg = getUbuntuSrcPkg(srcpkg, release) - cur_ver = ubuntusrcpkg.getVersion() - component = ubuntusrcpkg.getComponent() + ubuntu_srcpkg = getUbuntuSrcPkg(srcpkg, release) + ubuntu_version = Version(ubuntu_srcpkg.getVersion()) + ubuntu_component = ubuntu_srcpkg.getComponent() + newsource = False # override the -n flag except udtexceptions.PackageNotFoundException: + ubuntu_srcpkg = None + ubuntu_version = Version(0) + ubuntu_component = 'universe' # let's assume universe if not newsource: print "'%s' doesn't exist in 'Ubuntu %s'.\nDo you want to sync a new package?" % \ (srcpkg, release) raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') - newsource = True # TODO: set it for now, but check code if it's needed + newsource = True - debsrcpkg = getDebianSrcPkg(srcpkg, distro) - debiancomponent = debsrcpkg.getComponent() - # Find Debian release's package version. - deb_version = debsrcpkg.getVersion() + # Get the requested Debian source package + debian_srcpkg = getDebianSrcPkg(srcpkg, distro) + debian_version = Version(debian_srcpkg.getVersion()) + debian_component = debian_srcpkg.getComponent() - # Debian and Ubuntu versions are the same - stop. - if deb_version == cur_ver: - print 'The versions in Debian and Ubuntu are the same already (%s). Aborting.' % (deb_version,) + # Debian and Ubuntu versions are the same - stop + if ubuntu_version == debian_version: + print >> sys.stderr, \ + 'E: The versions in Debian and Ubuntu are the same already (%s). Aborting.' % ubuntu_version sys.exit(1) - # -s flag not specified - check if we do need sponsorship. - if (not sponsorship): - if (not newsource): - sponsorship = needsSponsorship(srcpkg, component) - else: - sponsorship = not PersonTeam.getMe().isLpTeamMember('motu') # assume going to universe + # -s flag not specified - check if we do need sponsorship + if not sponsorship: + sponsorship = needsSponsorship(srcpkg, ubuntu_component) - # Check for existing package reports. - if (not newsource) and use_lp_bugs: checkExistingReports(srcpkg) + # Check for existing package reports + if not newsource: + checkExistingReports(srcpkg) - # Generate bug report. - subscribe = 'ubuntu-archive' - status = 'confirmed' - if sponsorship == True: - status = 'new' - if component in ['main', 'restricted']: - subscribe = 'ubuntu-main-sponsors' + # Generate bug report + pkg_to_sync = '%s %s (%s) from Debian %s (%s)' % \ + (srcpkg, debian_version, ubuntu_component, distro, debian_component) + title = "Sync %s" % pkg_to_sync + if ffe: + title = "FFe: " + title + report = "Please sync %s\n\n" % pkg_to_sync + + if 'ubuntu' in str(ubuntu_version): + need_interaction = True + + print 'Changes have been made to the package in Ubuntu.\n' \ + 'Please edit the report and give an explanation.\n' \ + 'Not saving the report file will abort the request.' + report += 'Explanation of the Ubuntu delta and why it can be dropped:\n' \ + '>>> ENTER_EXPLANATION_HERE <<<\n\n' + + if ffe: + need_interaction = True + + print 'To approve FeatureFreeze exception, you need to state\n' \ + 'the reason why you feel it is necessary.\n' \ + 'Not saving the report file will abort the request.' + report += 'Explanation of FeatureFreeze exception:\n' \ + '>>> ENTER_EXPLANATION_HERE <<<\n\n' + + if need_interaction: + raw_input_exit_on_ctrlc('Press [Enter] to continue. Press [Ctrl-C] to abort now. ') + + # Check if they have a per-package upload permission. + if lpapi: + ubuntu_archive = Distribution('ubuntu').getArchive() + if PersonTeam.getMe().isPerPackageUploader(ubuntu_archive, srcpkg): + report += 'Note that I have per-package upload permissions for %s.\n\n' % srcpkg + + base_version = force_base_version or ubuntu_version + + if newsource: + report += 'All changelog entries:\n\n' else: - subscribe = 'ubuntu-universe-sponsors' - if ffe == True: + report += 'Changelog entries since current %s version %s:\n\n' % (release, ubuntu_version) + changelog = getDebianChangelog(debian_srcpkg, base_version) + if not changelog: + sys.exit(1) + report += changelog + + (title, report) = edit_report(title, report, changes_required = need_interaction) + + # bug status and bug subscriber + status = 'confirmed' + subscribe = 'ubuntu-archive' + if sponsorship: status = 'new' - if component in ['main', 'restricted']: + if ubuntu_component in ('main', 'restricted'): + subscribe = 'ubuntu-main-sponsors' + else: + subscribe = 'ubuntu-universe-sponsors' + if ffe: + status = 'new' + if ubuntu_component in ('main', 'restricted'): subscribe = 'ubuntu-release' else: subscribe = 'motu-release' - pkg_to_sync = '%s %s (%s) from Debian %s (%s)' % (srcpkg, deb_version, component, distro, debiancomponent) - title = "Sync %s" % pkg_to_sync - if ffe == True: - title = "FFe: " + title - report = "Please sync %s\n\n" % pkg_to_sync - - base_ver = cur_ver - uidx = base_ver.find('ubuntu') - if uidx > 0: - base_ver = base_ver[:uidx] - need_interaction = True - - print 'Changes have been made to the package in Ubuntu.' - print 'Please edit the report and give an explanation.' - print 'Press ENTER to start your editor. Press Control-C to abort now.' - print 'Not saving the report file will abort the request, too.' - raw_input_exit_on_ctrlc() - report += 'Explanation of the Ubuntu delta and why it can be dropped:\n' + \ - '>>> ENTER_EXPLANATION_HERE <<<\n\n' - - if ffe == True: - need_interaction = True - - print 'To approve FeatureFreeze exception, you need to state ' - print 'the reason why you feel it is necessary.' - print 'Press ENTER to start your editor. Press Control-C to abort now.' - print 'Not saving the report file will abort the request, too.' - raw_input_exit_on_ctrlc() - report += 'Explanation of FeatureFreeze exception:\n' + \ - '>>> ENTER_EXPLANATION_HERE <<<\n\n' - - # Check if they have a per-package upload permission. - if LpApiWrapper.isPerPackageUploader(srcpkg): - report += 'Note that I have per-package upload permissions for %s.\n\n' % srcpkg - - uidx = base_ver.find('build') - if uidx > 0: - base_ver = base_ver[:uidx] - - if force_base_ver: - base_ver = force_base_ver - - if not newsource: report += 'Changelog since current %s version %s:\n\n' % (release, cur_ver) - changelog = getDebianChangelog(debsrcpkg, Version(base_ver)) - if not changelog: - sys.exit(1) - report += changelog + '\n' - - (title, report) = edit_report(title, report, changes_required = need_interaction) - - # Post sync request using Launchpad interface: srcpkg = not newsource and srcpkg or None - if options.lpapi: - # Map status to the values expected by lp-bugs + if lpapi: + # Map status to the values expected by LP API mapping = {'new': 'New', 'confirmed': 'Confirmed'} + # Post sync request using LP API postBug(srcpkg, subscribe, mapping[status], title, report) else: - # Mail sync request: - mailBug(srcpkg, subscribe, status, title, report, keyid) + # Mail sync request + mailBug(srcpkg, subscribe, status, title, report, options.keyid) diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index 5a288e2..d002b5e 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -67,7 +67,7 @@ def checkExistingReports(srcpkg): ''' # Fetch the package's bug list from Launchpad - pkg = Distribution('ubuntu').getSourcePackage(name = srcpkg.getPackageName()) + pkg = Distribution('ubuntu').getSourcePackage(name = srcpkg) pkgBugList = pkg.getBugTasks() # Search bug list for other sync requests. diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 3475ba2..3b7b87a 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -31,7 +31,7 @@ __all__ = [ 'getDebianSrcPkg', 'getUbuntuSrcPkg', 'getEmailAddress', - 'postBug', + 'mailBug', ] class SourcePackagePublishingHistory(object): @@ -97,9 +97,9 @@ def getEmailAddress(): ''' myemailaddr = os.getenv('UBUMAIL') or os.getenv('DEBEMAIL') or os.getenv('EMAIL') if not myemailaddr: - print >> sys.stderr, 'The environment variable DEBEMAIL or ' \ - 'EMAIL needs to be set to let this script mail the ' \ - 'sync request.' + print >> sys.stderr, 'E: The environment variable UBUMAIL, ' \ + 'DEBEMAIL or EMAIL needs to be set to let this script ' \ + 'mail the sync request.' return myemailaddr def needSponsorship(name, component): @@ -139,7 +139,7 @@ def mailBug(srcpkg, subscribe, status, bugtitle, bugtext, keyid = None): # generate mailbody if srcpkg: - mailbody = ' affects ubuntu/%s\n' % srcpkg.getPackageName() + mailbody = ' affects ubuntu/%s\n' % srcpkg else: mailbody = ' affects ubuntu\n' mailbody += '''\ @@ -187,7 +187,7 @@ Content-Type: text/plain; charset=UTF-8 print 'Connecting to %s:%s ...' % (mailserver_host, mailserver_port) s = smtplib.SMTP(mailserver_host, mailserver_port) except socket.error, s: - print >> sys.stderr, "Could not connect to %s:%s: %s (%i)" % \ + print >> sys.stderr, 'E: Could not connect to %s:%s: %s (%i)' % \ (mailserver_host, mailserver_port, s[1], s[0]) return @@ -198,11 +198,11 @@ Content-Type: text/plain; charset=UTF-8 try: s.login(mailserver_user, mailserver_pass) except smtplib.SMTPAuthenticationError: - print 'Error authenticating to the server: invalid username and password.' + print >> sys.stderr, 'E: Error authenticating to the server: invalid username and password.' s.quit() return except: - print 'Unknown SMTP error.' + print >> sys.stderr, 'E: Unknown SMTP error.' s.quit() return From 82899a0f4548aa5bee595ccbee39920327a84b39 Mon Sep 17 00:00:00 2001 From: Michael Bienia Date: Tue, 25 Aug 2009 13:02:57 +0200 Subject: [PATCH 18/18] bug fixes --- requestsync | 12 ++++++++---- ubuntutools/requestsync/common.py | 7 ++++++- ubuntutools/requestsync/lp.py | 12 ++++++------ ubuntutools/requestsync/mail.py | 7 +++++-- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/requestsync b/requestsync index 64a929e..19f7285 100755 --- a/requestsync +++ b/requestsync @@ -124,9 +124,13 @@ if __name__ == '__main__': newsource = True # Get the requested Debian source package - debian_srcpkg = getDebianSrcPkg(srcpkg, distro) - debian_version = Version(debian_srcpkg.getVersion()) - debian_component = debian_srcpkg.getComponent() + try: + debian_srcpkg = getDebianSrcPkg(srcpkg, distro) + debian_version = Version(debian_srcpkg.getVersion()) + debian_component = debian_srcpkg.getComponent() + except udtexceptions.PackageNotFoundException, e: + print >> sys.stderr, "E: %s" % e + sys.exit(1) # Debian and Ubuntu versions are the same - stop if ubuntu_version == debian_version: @@ -136,7 +140,7 @@ if __name__ == '__main__': # -s flag not specified - check if we do need sponsorship if not sponsorship: - sponsorship = needsSponsorship(srcpkg, ubuntu_component) + sponsorship = needSponsorship(srcpkg, ubuntu_component) # Check for existing package reports if not newsource: diff --git a/ubuntutools/requestsync/common.py b/ubuntutools/requestsync/common.py index 47096cd..2cb66b9 100644 --- a/ubuntutools/requestsync/common.py +++ b/ubuntutools/requestsync/common.py @@ -34,7 +34,7 @@ def raw_input_exit_on_ctrlc(*args, **kwargs): try: return raw_input(*args, **kwargs) except KeyboardInterrupt: - print 'Abort requested. No sync request filed.' + print '\nAbort requested. No sync request filed.' sys.exit(1) def getDebianChangelog(srcpkg, version): @@ -48,6 +48,9 @@ def getDebianChangelog(srcpkg, version): subdir = 'lib%s' % pkgname[3] else: subdir = pkgname[0] + # Strip epoch from version + if ':' in pkgversion: + pkgversion = pkgversion[pkgversion.find(':')+1:] # Get the debian changelog file from packages.debian.org try: @@ -113,6 +116,8 @@ def edit_report(subject, body, changes_required = False): print 'The report has not been changed, but you have to explain why ' \ 'the Ubuntu changes can be dropped.' raw_input_exit_on_ctrlc('Press [Enter] to retry or [Control-C] to abort. ') + else: + changes_required = False report_file.seek(0) report = report_file.read() diff --git a/ubuntutools/requestsync/lp.py b/ubuntutools/requestsync/lp.py index d002b5e..7e8f3b3 100644 --- a/ubuntutools/requestsync/lp.py +++ b/ubuntutools/requestsync/lp.py @@ -55,7 +55,7 @@ Your sync request shall require an approval by a member of the appropriate sponsorship team, who shall be subscribed to this bug report. This must be done before it can be processed by a member of the Ubuntu Archive team.''' - raw_input_exit_on_ctrlc('If the above is correct please press [Enter]: ') + raw_input_exit_on_ctrlc('If the above is correct please press [Enter] ') return need_sponsor @@ -73,10 +73,10 @@ def checkExistingReports(srcpkg): # Search bug list for other sync requests. for bug in pkgBugList: # check for Sync or sync and the package name - if 'ync %s' % package in bug.title: + if not bug.is_complete and 'ync %s' % srcpkg in bug.title: print 'The following bug could be a possible duplicate sync bug on Launchpad:' - print ' * Bug #%i: %s (%s)' % \ - (bug.id, bug.title, translate_api_web(bug.self_link)) + print ' * %s (%s)' % \ + (bug.title, translate_api_web(bug.self_link)) print 'Please check the above URL to verify this before continuing.' raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') @@ -96,7 +96,7 @@ def postBug(srcpkg, subscribe, status, bugtitle, bugtext): bug_target = Distribution('ubuntu') # create bug - bug = Launchpad.bugs.createBug(title = bugtitle, description = bugtext, target = bug_target) + bug = Launchpad.bugs.createBug(title = bugtitle, description = bugtext, target = bug_target()) # newly created bugreports have only one task task = bug.bug_tasks[0] @@ -106,7 +106,7 @@ def postBug(srcpkg, subscribe, status, bugtitle, bugtext): task.status = status task.lp_save() - bug.subscribe(person = PersonTeam(subscribe)) + bug.subscribe(person = PersonTeam(subscribe)()) print 'Sync request filed as bug #%i: %s' % (bug.id, translate_api_web(bug.self_link)) diff --git a/ubuntutools/requestsync/mail.py b/ubuntutools/requestsync/mail.py index 3b7b87a..8e7d41a 100644 --- a/ubuntutools/requestsync/mail.py +++ b/ubuntutools/requestsync/mail.py @@ -31,6 +31,8 @@ __all__ = [ 'getDebianSrcPkg', 'getUbuntuSrcPkg', 'getEmailAddress', + 'needSponsorship', + 'checkExistingReports', 'mailBug', ] @@ -111,7 +113,7 @@ def needSponsorship(name, component): while True: print "Do you have upload permissions for the '%s' component " \ "or the package '%s'?" % (component, name) - val = raw_input_exit_on_ctrlc("If in doubt answer 'no'. [y/N]? ") + val = raw_input_exit_on_ctrlc("If in doubt answer 'n'. [y/N]? ") if val.lower() in ('y', 'yes'): return False elif val.lower() in ('n', 'no', ''): @@ -123,7 +125,8 @@ def checkExistingReports(srcpkg): ''' Point the user to the URL to manually check for duplicate bug reports. ''' - print 'Please check on https://bugs.launchpad.net/ubuntu/+source/%s/+bugs for duplicate sync requests before continuing.' + print 'Please check on https://bugs.launchpad.net/ubuntu/+source/%s/+bugs\n' \ + 'for duplicate sync requests before continuing.' % srcpkg raw_input_exit_on_ctrlc('Press [Enter] to continue or [Ctrl-C] to abort. ') def mailBug(srcpkg, subscribe, status, bugtitle, bugtext, keyid = None):