#! /usr/bin/python # Copyright (C) 2009, 2010, 2011, 2012 Canonical Ltd. # Authors: # Martin Pitt # Colin Watson # 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 3 of the License. # # 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. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Process binary NEW entries from Debian. Find and accept all binary NEW entries built by source packages synced directly from Debian. These do not typically need significant review. """ from __future__ import print_function import atexit from optparse import OptionParser import os import shutil import subprocess import sys import tempfile try: from urllib.parse import unquote, urlsplit from urllib.request import urlopen, urlretrieve except ImportError: from urllib import unquote, urlretrieve from urllib2 import urlopen from urlparse import urlsplit from launchpadlib.launchpad import Launchpad from ubuntutools.question import YesNoQuestion import lputils CONSUMER_KEY = "new-binary-debian-universe" temp_dir = None def ensure_temp_dir(): global temp_dir if temp_dir is None: temp_dir = tempfile.mkdtemp() atexit.register(shutil.rmtree, temp_dir) def find_matching_uploads(options, explicit_suite): kwargs = {} if explicit_suite: kwargs["pocket"] = options.pocket uploads = options.series.getPackageUploads( archive=options.archive, status="New", **kwargs) for upload in uploads: if upload.contains_build: if upload.changes_file_url is None: continue # display_name is inaccurate for the theoretical case of an # upload containing multiple builds, but in practice it's close # enough. source = upload.display_name.split(",")[0] if source == "linux": continue binaries = upload.getBinaryProperties() binaries = [b for b in binaries if "customformat" not in b] if [b for b in binaries if "ubuntu" in b["version"]]: continue changes_file = urlopen(upload.changes_file_url) try: changes = changes_file.read() finally: changes_file.close() if (" unstable; urgency=" not in changes and " experimental; urgency=" not in changes): continue if options.lintian: ensure_temp_dir() for url in upload.binaryFileUrls(): if (not url.endswith("_all.deb") and not url.endswith("_i386.deb")): continue filename = unquote(urlsplit(url)[2].split("/")[-1]) print("Fetching %s ..." % filename) path = os.path.join(temp_dir, filename) urlretrieve(url, path) lintian = subprocess.Popen( ["lintian", path], stdout=subprocess.PIPE, universal_newlines=True) out = lintian.communicate()[0] if lintian.returncode != 0: print("\n=== %s ===\n%s" % (filename, out), file=sys.stderr) yield upload, binaries def find_and_accept(options, explicit_suite): for upload, binaries in list( find_matching_uploads(options, explicit_suite)): if options.source and upload.package_name not in options.source: continue display = "%s/%s (%s)" % ( upload.display_name, upload.display_version, upload.display_arches) if options.dry_run: print("Would accept %s" % display) else: for binary in binaries: if "customformat" not in binary: print("%s | %s Component: %s Section: %s Priority: %s" % ( "N" if binary["is_new"] else "*", binary["name"], binary["component"], binary["section"], binary["priority"])) if not options.confirm_all: if YesNoQuestion().ask("Accept %s" % display, "no") == "no": continue print("Accepting %s" % display) upload.acceptFromQueue() def main(): parser = OptionParser(usage="usage: %prog [options]") parser.add_option( "-l", "--launchpad", dest="launchpad_instance", default="production") parser.add_option( "-d", "--distribution", metavar="DISTRO", default="ubuntu", help="look in distribution DISTRO") parser.add_option( "-s", "--suite", metavar="SUITE", help="look in suite SUITE") parser.add_option( "-n", "--dry-run", default=False, action="store_true", help="don't make any modifications") parser.add_option( "-y", "--confirm-all", default=False, action="store_true", help="do not ask for confirmation") parser.add_option( "--lintian", default=False, action="store_true", help="run packages through Lintian") parser.add_option( "--source", action="append", metavar="NAME", help="only consider source package NAME") options, _ = parser.parse_args() options.launchpad = Launchpad.login_with( CONSUMER_KEY, options.launchpad_instance, version="devel") explicit_suite = options.suite is not None lputils.setup_location(options) find_and_accept(options, explicit_suite) if __name__ == '__main__': main()