# -*- coding: utf-8 -*- # # lp.py - methods used by requestsync while interacting # directly with Launchpad # # 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; 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-2 file for the full text # of the GNU General Public License license. import logging import re from debian.deb822 import Changes from distro_info import DebianDistroInfo, DistroDataOutdated from httplib2 import Http, HttpLib2Error from ubuntutools.lp import udtexceptions from ubuntutools.lp.lpapicache import ( Distribution, DistributionSourcePackage, Launchpad, PersonTeam, ) from ubuntutools.question import confirmation_prompt Logger = logging.getLogger(__name__) def get_debian_srcpkg(name, release): debian = Distribution("debian") debian_archive = debian.getArchive() try: release = DebianDistroInfo().codename(release, None, release) except DistroDataOutdated as e: Logger.warning(e) return debian_archive.getSourcePackage(name, release) def get_ubuntu_srcpkg(name, release, pocket="Release"): ubuntu = Distribution("ubuntu") ubuntu_archive = ubuntu.getArchive() try: return ubuntu_archive.getSourcePackage(name, release, pocket) except udtexceptions.PackageNotFoundException: if pocket != "Release": parent_pocket = "Release" if pocket == "Updates": parent_pocket = "Proposed" return get_ubuntu_srcpkg(name, release, parent_pocket) raise def need_sponsorship(name, component, release): """ Check if the user has upload permissions for either the package itself or the component """ archive = Distribution("ubuntu").getArchive() distroseries = Distribution("ubuntu").getSeries(release) need_sponsor = not PersonTeam.me.canUploadPackage(archive, distroseries, 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.""" ) confirmation_prompt() return need_sponsor def check_existing_reports(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) pkg_bug_list = pkg.searchTasks( status=["Incomplete", "New", "Confirmed", "Triaged", "In Progress", "Fix Committed"], omit_duplicates=True, ) # Search bug list for other sync requests. for bug in pkg_bug_list: # check for Sync or sync and the package name 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:\n" " * %s (%s)\n" "Please check the above URL to verify this before " "continuing." % (bug.title, bug.web_link) ) confirmation_prompt() def get_ubuntu_delta_changelog(srcpkg): """ Download the Ubuntu changelog and extract the entries since the last sync from Debian. """ archive = Distribution("ubuntu").getArchive() spph = archive.getPublishedSources( source_name=srcpkg.getPackageName(), exact_match=True, pocket="Release" ) debian_info = DebianDistroInfo() topline = re.compile( r"^(\w%(name_chars)s*) \(([^\(\) \t]+)\)" r"((\s+%(name_chars)s+)+)\;" % {"name_chars": "[-+0-9a-z.]"}, re.IGNORECASE, ) delta = [] for record in spph: changes_url = record.changesFileUrl() if changes_url is None: # Native sync break try: response = Http().request(changes_url)[0] except HttpLib2Error as e: Logger.error(str(e)) break if response.status != 200: Logger.error("%s: %s %s", changes_url, response.status, response.reason) break changes = Changes(Http().request(changes_url)[1]) for line in changes["Changes"].splitlines(): line = line[1:] match = topline.match(line) if match: distribution = match.group(3).split()[0].split("-")[0] if debian_info.valid(distribution): break if line.startswith(" "): delta.append(line) else: continue break return "\n".join(delta) def post_bug(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)) confirmation_prompt() if srcpkg: # pylint: disable=protected-access 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.me.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, bug.web_link))