mirror of
https://git.launchpad.net/ubuntu-dev-tools
synced 2025-03-12 15:41:09 +00:00
412 lines
13 KiB
Python
Executable File
412 lines
13 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# -*- 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 argparse
|
|
import os
|
|
import sys
|
|
|
|
from distro_info import UbuntuDistroInfo
|
|
|
|
from ubuntutools import getLogger
|
|
from ubuntutools.config import UDTConfig, ubu_email
|
|
from ubuntutools.lp import udtexceptions
|
|
from ubuntutools.misc import require_utf8
|
|
from ubuntutools.question import EditBugReport, confirmation_prompt
|
|
from ubuntutools.version import Version
|
|
|
|
Logger = getLogger()
|
|
|
|
#
|
|
# entry point
|
|
#
|
|
|
|
|
|
def main():
|
|
# Our usage options.
|
|
usage = "%(prog)s [options] <source package> [<target release> [base version]]"
|
|
parser = argparse.ArgumentParser(usage=usage)
|
|
|
|
parser.add_argument(
|
|
"-d", dest="dist", default="unstable", help="Debian distribution to sync from."
|
|
)
|
|
parser.add_argument(
|
|
"-k",
|
|
dest="keyid",
|
|
default=None,
|
|
help="GnuPG key ID to use for signing report "
|
|
"(only used when emailing the sync request).",
|
|
)
|
|
parser.add_argument(
|
|
"-n",
|
|
action="store_true",
|
|
dest="newpkg",
|
|
default=False,
|
|
help="Whether package to sync is a new package in Ubuntu.",
|
|
)
|
|
parser.add_argument(
|
|
"--email",
|
|
action="store_true",
|
|
default=False,
|
|
help="Use a PGP-signed email for filing the sync request, rather than the LP API.",
|
|
)
|
|
parser.add_argument(
|
|
"--lp",
|
|
dest="deprecated_lp_flag",
|
|
action="store_true",
|
|
default=False,
|
|
help=argparse.SUPPRESS,
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--lpinstance",
|
|
metavar="INSTANCE",
|
|
dest="lpinstance",
|
|
default=None,
|
|
help="Launchpad instance to connect to (default: production).",
|
|
)
|
|
parser.add_argument(
|
|
"-s", action="store_true", dest="sponsorship", default=False, help="Force sponsorship"
|
|
)
|
|
parser.add_argument(
|
|
"-C",
|
|
action="store_true",
|
|
dest="missing_changelog_ok",
|
|
default=False,
|
|
help="Allow changelog to be manually filled in when missing",
|
|
)
|
|
parser.add_argument(
|
|
"-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_argument(
|
|
"--no-conf",
|
|
action="store_true",
|
|
dest="no_conf",
|
|
default=False,
|
|
help="Don't read config files or environment variables",
|
|
)
|
|
parser.add_argument("source_package", help=argparse.SUPPRESS)
|
|
parser.add_argument("release", nargs="?", help=argparse.SUPPRESS)
|
|
parser.add_argument("base_version", nargs="?", type=Version, help=argparse.SUPPRESS)
|
|
args = parser.parse_args()
|
|
|
|
require_utf8()
|
|
|
|
config = UDTConfig(args.no_conf)
|
|
|
|
if args.deprecated_lp_flag:
|
|
Logger.info("The --lp flag is now default, ignored.")
|
|
if args.email:
|
|
args.lpapi = False
|
|
else:
|
|
args.lpapi = config.get_value("USE_LPAPI", default=True, boolean=True)
|
|
if args.lpinstance is None:
|
|
args.lpinstance = config.get_value("LPINSTANCE")
|
|
|
|
if args.keyid is None:
|
|
args.keyid = config.get_value("KEYID")
|
|
|
|
if not args.lpapi:
|
|
if args.lpinstance == "production":
|
|
bug_mail_domain = "bugs.launchpad.net"
|
|
elif args.lpinstance == "staging":
|
|
bug_mail_domain = "bugs.staging.launchpad.net"
|
|
else:
|
|
Logger.error("Error: Unknown launchpad instance: %s", args.lpinstance)
|
|
sys.exit(1)
|
|
|
|
mailserver_host = config.get_value(
|
|
"SMTP_SERVER", default=None, compat_keys=["UBUSMTP", "DEBSMTP"]
|
|
)
|
|
if not args.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:
|
|
Logger.error("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 args.lpapi:
|
|
from ubuntutools.lp.lpapicache import Distribution, Launchpad
|
|
from ubuntutools.requestsync.lp import (
|
|
check_existing_reports,
|
|
get_debian_srcpkg,
|
|
get_ubuntu_delta_changelog,
|
|
get_ubuntu_srcpkg,
|
|
need_sponsorship,
|
|
post_bug,
|
|
)
|
|
|
|
# See if we have LP credentials and exit if we don't -
|
|
# cannot continue in this case
|
|
|
|
try:
|
|
# devel for changelogUrl()
|
|
Launchpad.login(service=args.lpinstance, api_version="devel")
|
|
except IOError:
|
|
sys.exit(1)
|
|
else:
|
|
from ubuntutools.requestsync.mail import (
|
|
check_existing_reports,
|
|
get_debian_srcpkg,
|
|
get_ubuntu_delta_changelog,
|
|
get_ubuntu_srcpkg,
|
|
mail_bug,
|
|
need_sponsorship,
|
|
)
|
|
|
|
if not any(x in os.environ for x in ("UBUMAIL", "DEBEMAIL", "EMAIL")):
|
|
Logger.error(
|
|
"The environment variable UBUMAIL, DEBEMAIL or EMAIL needs "
|
|
"to be set to let this script mail the sync request."
|
|
)
|
|
sys.exit(1)
|
|
|
|
newsource = args.newpkg
|
|
sponsorship = args.sponsorship
|
|
distro = args.dist
|
|
ffe = args.ffe
|
|
lpapi = args.lpapi
|
|
need_interaction = False
|
|
srcpkg = args.source_package
|
|
|
|
if not args.release:
|
|
if lpapi:
|
|
args.release = Distribution("ubuntu").getDevelopmentSeries().name
|
|
else:
|
|
ubu_info = UbuntuDistroInfo()
|
|
args.release = ubu_info.devel()
|
|
Logger.warning("Target release missing - assuming %s", args.release)
|
|
|
|
# Get the current Ubuntu source package
|
|
try:
|
|
ubuntu_srcpkg = get_ubuntu_srcpkg(srcpkg, args.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:
|
|
Logger.info("'%s' doesn't exist in 'Ubuntu %s'.", srcpkg, args.release)
|
|
Logger.info("Do you want to sync a new package?")
|
|
confirmation_prompt()
|
|
newsource = True
|
|
except udtexceptions.SeriesNotFoundException as error:
|
|
Logger.error(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 as error:
|
|
Logger.error(error)
|
|
sys.exit(1)
|
|
except udtexceptions.SeriesNotFoundException as error:
|
|
Logger.error(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 args.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 as error:
|
|
Logger.error(error)
|
|
sys.exit(1)
|
|
|
|
if ubuntu_version == debian_version:
|
|
Logger.error(
|
|
"The versions in Debian and Ubuntu are the same already (%s). Aborting.",
|
|
ubuntu_version,
|
|
)
|
|
sys.exit(1)
|
|
if ubuntu_version > debian_version:
|
|
Logger.error(
|
|
"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, args.release)
|
|
|
|
if not sponsorship and not ffe:
|
|
Logger.error(
|
|
"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
|
|
|
|
Logger.info("Changes have been made to the package in Ubuntu.")
|
|
Logger.info("Please edit the report and give an explanation.")
|
|
Logger.info("Not saving the report file will abort the request.")
|
|
report += (
|
|
"Explanation of the Ubuntu delta and why it can be "
|
|
"dropped:\n%s\n>>> ENTER_EXPLANATION_HERE <<<\n\n"
|
|
% get_ubuntu_delta_changelog(ubuntu_srcpkg)
|
|
)
|
|
|
|
if ffe:
|
|
need_interaction = True
|
|
|
|
Logger.info("To approve FeatureFreeze exception, you need to state")
|
|
Logger.info("the reason why you feel it is necessary.")
|
|
Logger.info("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 = args.base_version or ubuntu_version
|
|
|
|
if newsource:
|
|
report += "All changelog entries:\n\n"
|
|
else:
|
|
report += "Changelog entries since current %s version %s:\n\n" % (
|
|
args.release,
|
|
ubuntu_version,
|
|
)
|
|
changelog = debian_srcpkg.getChangelog(since_version=base_version)
|
|
if not changelog:
|
|
if not args.missing_changelog_ok:
|
|
Logger.error(
|
|
"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:
|
|
Logger.error(
|
|
"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,
|
|
args.keyid,
|
|
email_from,
|
|
mailserver_host,
|
|
mailserver_port,
|
|
mailserver_user,
|
|
mailserver_pass,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except KeyboardInterrupt:
|
|
Logger.error("User abort.")
|
|
sys.exit(2)
|