#!/usr/bin/python # -*- coding: utf-8 -*- # # (C) 2007 Canonical Ltd., Steve Kowalik # Authors: # Martin Pitt # Steve Kowalik # Michael Bienia # Daniel Hahler # Iain Lane # Jonathan Davies # Markus Korn (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 os import subprocess import sys from debian_bundle.changelog import Version from optparse import OptionParser # 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 # https_proxy fix 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. 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 # if __name__ == '__main__': # Our usage options. usage = "Usage: %prog [-d distro] [-k keyid] [-n] [--lp] [-s] [-e] " usage += " [ [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.") (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 use_lp_bugs and not getEmailAddress(): sys.exit(1) if len(args) == 0: optParser.print_help() sys.exit(1) 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] 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. 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() # 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) # -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) # 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 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 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)