mirror of
https://git.launchpad.net/ubuntu-dev-tools
synced 2025-12-06 15:43:27 +00:00
pylint complains: ``` requestsync:156:34: E0606: Possibly using variable 'bug_mail_domain' before assignment (possibly-used-before-assignment) requestsync:217:27: E0606: Possibly using variable 'Distribution' before assignment (possibly-used-before-assignment) requestsync:380:8: E0606: Possibly using variable 'post_bug' before assignment (possibly-used-before-assignment) ``` These errors are false positives. So silence them. The perfect solution would be to restructure the code.
409 lines
13 KiB
Python
Executable File
409 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 # pylint: disable=import-outside-toplevel
|
|
|
|
DNS.DiscoverNameServers()
|
|
# imported earlier, pylint: disable-next=possibly-used-before-assignment
|
|
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
|
|
# pylint: disable=import-outside-toplevel
|
|
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:
|
|
# imported earlier, pylint: disable-next=possibly-used-before-assignment
|
|
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 # pylint: disable=import-outside-toplevel
|
|
|
|
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 = (
|
|
f"{srcpkg} {debian_version} ({ubuntu_component})"
|
|
f" from Debian {distro} ({debian_component})"
|
|
)
|
|
title = f"Sync {pkg_to_sync}"
|
|
if ffe:
|
|
title = "FFe: " + title
|
|
report = f"Please sync {pkg_to_sync}\n\n"
|
|
|
|
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 += (
|
|
f"Explanation of the Ubuntu delta and why it can be dropped:\n"
|
|
f"{get_ubuntu_delta_changelog(ubuntu_srcpkg)}\n>>> ENTER_EXPLANATION_HERE <<<\n\n"
|
|
)
|
|
|
|
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 += f"Changelog entries since current {args.release} version {ubuntu_version}:\n\n"
|
|
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 = None if newsource else srcpkg
|
|
if lpapi:
|
|
# Map status to the values expected by LP API
|
|
mapping = {"new": "New", "confirmed": "Confirmed"}
|
|
# Post sync request using LP API
|
|
# imported earlier, pylint: disable-next=possibly-used-before-assignment
|
|
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)
|