mirror of
https://git.launchpad.net/ubuntu-dev-tools
synced 2025-03-12 15:41:09 +00:00
instead of debian.debian_support.Version, use ubuntutools version, which extends it and adds the strip_epoch() function which is needed to convert full version string to version used in filenames
362 lines
14 KiB
Python
Executable File
362 lines
14 KiB
Python
Executable File
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# (C) 2007 Canonical Ltd., Steve Kowalik
|
|
# Authors:
|
|
# Martin Pitt <martin.pitt@ubuntu.com>
|
|
# Steve Kowalik <stevenk@ubuntu.com>
|
|
# Michael Bienia <geser@ubuntu.com>
|
|
# Daniel Hahler <ubuntu@thequod.de>
|
|
# Iain Lane <laney@ubuntu.com>
|
|
# Jonathan Davies <jpds@ubuntu.com>
|
|
# Markus Korn <thekorn@gmx.de> (python-launchpadlib support)
|
|
#
|
|
# ##################################################################
|
|
#
|
|
# 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; 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.
|
|
#
|
|
# See file /usr/share/common-licenses/GPL-2 for more details.
|
|
#
|
|
# ##################################################################
|
|
|
|
import optparse
|
|
import os
|
|
import sys
|
|
|
|
from distro_info import UbuntuDistroInfo
|
|
|
|
from ubuntutools.config import UDTConfig, ubu_email
|
|
from ubuntutools.lp import udtexceptions
|
|
from ubuntutools.misc import require_utf8
|
|
from ubuntutools.question import confirmation_prompt, EditBugReport
|
|
from ubuntutools.version import Version
|
|
|
|
#
|
|
# entry point
|
|
#
|
|
|
|
|
|
def main():
|
|
# Our usage options.
|
|
usage = ('Usage: %prog [options] '
|
|
'<source package> [<target release> [base version]]')
|
|
parser = optparse.OptionParser(usage)
|
|
|
|
parser.add_option('-d', type='string',
|
|
dest='dist', default='unstable',
|
|
help='Debian distribution to sync from.')
|
|
parser.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).')
|
|
parser.add_option('-n', action='store_true',
|
|
dest='newpkg', default=False,
|
|
help='Whether package to sync is a new package in '
|
|
'Ubuntu.')
|
|
parser.add_option('--email', action='store_true', default=False,
|
|
help='Use a PGP-signed email for filing the sync '
|
|
'request, rather than the LP API.')
|
|
parser.add_option('--lp', dest='deprecated_lp_flag',
|
|
action='store_true', default=False,
|
|
help=optparse.SUPPRESS_HELP)
|
|
parser.add_option('-l', '--lpinstance', metavar='INSTANCE',
|
|
dest='lpinstance', default=None,
|
|
help='Launchpad instance to connect to '
|
|
'(default: production).')
|
|
parser.add_option('-s', action='store_true',
|
|
dest='sponsorship', default=False,
|
|
help='Force sponsorship')
|
|
parser.add_option('-C', action='store_true',
|
|
dest='missing_changelog_ok', default=False,
|
|
help='Allow changelog to be manually filled in '
|
|
'when missing')
|
|
parser.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.')
|
|
parser.add_option('--no-conf', action='store_true',
|
|
dest='no_conf', default=False,
|
|
help="Don't read config files or environment variables")
|
|
|
|
(options, args) = parser.parse_args()
|
|
|
|
if not len(args):
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
require_utf8()
|
|
|
|
config = UDTConfig(options.no_conf)
|
|
|
|
if options.deprecated_lp_flag:
|
|
print "The --lp flag is now default, ignored."
|
|
if options.email:
|
|
options.lpapi = False
|
|
else:
|
|
options.lpapi = config.get_value('USE_LPAPI', default=True,
|
|
boolean=True)
|
|
if options.lpinstance is None:
|
|
options.lpinstance = config.get_value('LPINSTANCE')
|
|
|
|
if options.keyid is None:
|
|
options.keyid = config.get_value('KEYID')
|
|
|
|
if not options.lpapi:
|
|
if options.lpinstance == 'production':
|
|
bug_mail_domain = 'bugs.launchpad.net'
|
|
elif options.lpinstance == 'staging':
|
|
bug_mail_domain = 'bugs.staging.launchpad.net'
|
|
else:
|
|
print >> sys.stderr, ('Error: Unknown launchpad instance: %s'
|
|
% options.lpinstance)
|
|
sys.exit(1)
|
|
|
|
mailserver_host = config.get_value('SMTP_SERVER',
|
|
default=None,
|
|
compat_keys=['UBUSMTP', 'DEBSMTP'])
|
|
if not options.lpapi and not mailserver_host:
|
|
try:
|
|
import DNS
|
|
DNS.DiscoverNameServers()
|
|
mxlist = DNS.mxlookup(bug_mail_domain)
|
|
firstmx = mxlist[0]
|
|
mailserver_host = firstmx[1]
|
|
except ImportError:
|
|
print >> sys.stderr, ('Please install python-dns to support '
|
|
'Launchpad mail server lookup.')
|
|
sys.exit(1)
|
|
|
|
mailserver_port = config.get_value('SMTP_PORT', default=25,
|
|
compat_keys=['UBUSMTP_PORT',
|
|
'DEBSMTP_PORT'])
|
|
mailserver_user = config.get_value('SMTP_USER',
|
|
compat_keys=['UBUSMTP_USER',
|
|
'DEBSMTP_USER'])
|
|
mailserver_pass = config.get_value('SMTP_PASS',
|
|
compat_keys=['UBUSMTP_PASS',
|
|
'DEBSMTP_PASS'])
|
|
|
|
# import the needed requestsync module
|
|
if options.lpapi:
|
|
from ubuntutools.requestsync.lp import (check_existing_reports,
|
|
get_debian_srcpkg,
|
|
get_ubuntu_srcpkg,
|
|
get_ubuntu_delta_changelog,
|
|
need_sponsorship, post_bug)
|
|
from ubuntutools.lp.lpapicache import Distribution, Launchpad
|
|
# See if we have LP credentials and exit if we don't -
|
|
# cannot continue in this case
|
|
|
|
try:
|
|
# devel for changelogUrl()
|
|
Launchpad.login(service=options.lpinstance, api_version='devel')
|
|
except IOError:
|
|
sys.exit(1)
|
|
else:
|
|
from ubuntutools.requestsync.mail import (check_existing_reports,
|
|
get_debian_srcpkg,
|
|
get_ubuntu_srcpkg,
|
|
get_ubuntu_delta_changelog,
|
|
mail_bug, need_sponsorship)
|
|
if not any(x in os.environ for x in ('UBUMAIL', 'DEBEMAIL', 'EMAIL')):
|
|
print >> sys.stderr, (
|
|
'E: The environment variable UBUMAIL, DEBEMAIL or EMAIL needs '
|
|
'to be set to let this script mail the sync request.')
|
|
sys.exit(1)
|
|
|
|
newsource = options.newpkg
|
|
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) == 1:
|
|
if lpapi:
|
|
release = Distribution('ubuntu').getDevelopmentSeries().name
|
|
else:
|
|
ubu_info = UbuntuDistroInfo()
|
|
release = ubu_info.devel()
|
|
print >> sys.stderr, 'W: Target release missing - assuming %s' % release
|
|
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.'
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
# Get the current Ubuntu source package
|
|
try:
|
|
ubuntu_srcpkg = get_ubuntu_srcpkg(srcpkg, release, 'Proposed')
|
|
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('~')
|
|
ubuntu_component = None # Set after getting the Debian info
|
|
if not newsource:
|
|
print("'%s' doesn't exist in 'Ubuntu %s'.\nDo you want to sync a new package?" %
|
|
(srcpkg, release))
|
|
confirmation_prompt()
|
|
newsource = True
|
|
except udtexceptions.SeriesNotFoundException, error:
|
|
print >> sys.stderr, "E: %s" % error
|
|
sys.exit(1)
|
|
|
|
# Get the requested Debian source package
|
|
try:
|
|
debian_srcpkg = get_debian_srcpkg(srcpkg, distro)
|
|
debian_version = Version(debian_srcpkg.getVersion())
|
|
debian_component = debian_srcpkg.getComponent()
|
|
except udtexceptions.PackageNotFoundException, error:
|
|
print >> sys.stderr, "E: %s" % error
|
|
sys.exit(1)
|
|
except udtexceptions.SeriesNotFoundException, error:
|
|
print >> sys.stderr, "E: %s" % error
|
|
sys.exit(1)
|
|
|
|
if ubuntu_component is None:
|
|
if debian_component == 'main':
|
|
ubuntu_component = 'universe'
|
|
else:
|
|
ubuntu_component = 'multiverse'
|
|
|
|
# Stop if Ubuntu has already the version from Debian or a newer version
|
|
if (ubuntu_version >= debian_version) and options.lpapi:
|
|
# try rmadison
|
|
import ubuntutools.requestsync.mail
|
|
try:
|
|
debian_srcpkg = ubuntutools.requestsync.mail.get_debian_srcpkg(srcpkg, distro)
|
|
debian_version = Version(debian_srcpkg.getVersion())
|
|
debian_component = debian_srcpkg.getComponent()
|
|
except udtexceptions.PackageNotFoundException, error:
|
|
print >> sys.stderr, "E: %s" % error
|
|
sys.exit(1)
|
|
|
|
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)
|
|
if ubuntu_version > debian_version:
|
|
print >> sys.stderr, ('E: The version in Ubuntu (%s) is newer than '
|
|
'the version in Debian (%s). Aborting.'
|
|
% (ubuntu_version, debian_version))
|
|
sys.exit(1)
|
|
|
|
# -s flag not specified - check if we do need sponsorship
|
|
if not sponsorship:
|
|
sponsorship = need_sponsorship(srcpkg, ubuntu_component, release)
|
|
|
|
if not sponsorship and not ffe:
|
|
print >> sys.stderr, ('Consider using syncpackage(1) for syncs that '
|
|
'do not require feature freeze exceptions.')
|
|
|
|
# Check for existing package reports
|
|
if not newsource:
|
|
check_existing_reports(srcpkg)
|
|
|
|
# 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 += (u'Explanation of the Ubuntu delta and why it can be '
|
|
u'dropped:\n%s\n>>> ENTER_EXPLANATION_HERE <<<\n\n'
|
|
% get_ubuntu_delta_changelog(ubuntu_srcpkg))
|
|
|
|
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:
|
|
confirmation_prompt()
|
|
|
|
base_version = force_base_version or ubuntu_version
|
|
|
|
if newsource:
|
|
report += 'All changelog entries:\n\n'
|
|
else:
|
|
report += ('Changelog entries since current %s version %s:\n\n'
|
|
% (release, ubuntu_version))
|
|
changelog = debian_srcpkg.getChangelog(since_version=base_version)
|
|
if not changelog:
|
|
if not options.missing_changelog_ok:
|
|
print >> sys.stderr, ("E: Did not retrieve any changelog entries. "
|
|
"Do you need to specify '-C'? "
|
|
"Was the package recently uploaded? (check "
|
|
"http://packages.debian.org/changelogs/)")
|
|
sys.exit(1)
|
|
else:
|
|
need_interaction = True
|
|
changelog = "XXX FIXME: add changelog here XXX"
|
|
report += changelog
|
|
|
|
editor = EditBugReport(title, report)
|
|
editor.edit(optional=not need_interaction)
|
|
title, report = editor.get_report()
|
|
|
|
if 'XXX FIXME' in report:
|
|
print >> sys.stderr, ("E: changelog boilerplate found in report, "
|
|
"please manually add changelog when using '-C'")
|
|
sys.exit(1)
|
|
|
|
# bug status and bug subscriber
|
|
status = 'confirmed'
|
|
subscribe = 'ubuntu-archive'
|
|
if sponsorship:
|
|
status = 'new'
|
|
subscribe = 'ubuntu-sponsors'
|
|
if ffe:
|
|
status = 'new'
|
|
subscribe = 'ubuntu-release'
|
|
|
|
srcpkg = not newsource and srcpkg or None
|
|
if lpapi:
|
|
# Map status to the values expected by LP API
|
|
mapping = {'new': 'New', 'confirmed': 'Confirmed'}
|
|
# Post sync request using LP API
|
|
post_bug(srcpkg, subscribe, mapping[status], title, report)
|
|
else:
|
|
email_from = ubu_email(export=False)[1]
|
|
# Mail sync request
|
|
mail_bug(srcpkg, subscribe, status, title, report, bug_mail_domain,
|
|
options.keyid, email_from, mailserver_host, mailserver_port,
|
|
mailserver_user, mailserver_pass)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
main()
|
|
except KeyboardInterrupt:
|
|
print "\nUser abort."
|
|
sys.exit(2)
|