mirror of
				https://github.com/lubuntu-team/ppa-britney.git
				synced 2025-10-25 05:34:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			254 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #! /usr/bin/python
 | |
| 
 | |
| # Copyright (C) 2009, 2010, 2011, 2012 Canonical Ltd.
 | |
| 
 | |
| # 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 <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| """Apply suitable overrides to new kernel binaries, matching previous ones."""
 | |
| 
 | |
| from __future__ import print_function
 | |
| 
 | |
| import atexit
 | |
| from collections import defaultdict
 | |
| from contextlib import closing
 | |
| import gzip
 | |
| from optparse import OptionParser, Values
 | |
| import os
 | |
| import shutil
 | |
| import sys
 | |
| import tempfile
 | |
| try:
 | |
|     from urllib.request import urlopen
 | |
| except ImportError:
 | |
|     from urllib2 import urlopen
 | |
| 
 | |
| import apt_pkg
 | |
| from launchpadlib.launchpad import Launchpad
 | |
| from lazr.restfulclient.errors import ServerError
 | |
| from ubuntutools.question import YesNoQuestion
 | |
| 
 | |
| import lputils
 | |
| 
 | |
| 
 | |
| CONSUMER_KEY = "kernel-overrides"
 | |
| 
 | |
| 
 | |
| tempdir = None
 | |
| 
 | |
| 
 | |
| def ensure_tempdir():
 | |
|     global tempdir
 | |
|     if not tempdir:
 | |
|         tempdir = tempfile.mkdtemp(prefix='kernel-overrides')
 | |
|         atexit.register(shutil.rmtree, tempdir)
 | |
| 
 | |
| 
 | |
| class FakeBPPH:
 | |
|     def __init__(self, pkg, component, das):
 | |
|         self.binary_package_name = pkg
 | |
|         self.component_name = component
 | |
|         self.distro_arch_series = das
 | |
| 
 | |
| 
 | |
| def get_published_binaries(options, source):
 | |
|     """If getPublishedBinaries times out, fall back to doing it by hand."""
 | |
|     try:
 | |
|         for binary in source.getPublishedBinaries():
 | |
|             if not binary.is_debug:
 | |
|                 yield binary
 | |
|     except ServerError as e:
 | |
|         if e.response.status != 503:
 | |
|             raise
 | |
|         print("getPublishedBinaries timed out; fetching Packages instead ...")
 | |
|         ensure_tempdir()
 | |
|         for section_name in ("", "debian-installer"):
 | |
|             for component in ("main", "restricted", "universe", "multiverse"):
 | |
|                 for das in options.old.series.architectures:
 | |
|                     arch = das.architecture_tag
 | |
|                     if arch in ("amd64", "i386"):
 | |
|                         base = "http://archive.ubuntu.com/ubuntu"
 | |
|                     else:
 | |
|                         base = "http://ports.ubuntu.com/ubuntu-ports"
 | |
|                     url = ("%s/dists/%s/%s%s/binary-%s/Packages.gz" %
 | |
|                            (base, options.old.suite, component,
 | |
|                             "/%s" % section_name if section_name else "",
 | |
|                             arch))
 | |
|                     path = os.path.join(
 | |
|                         tempdir, "Ubuntu_%s_%s%s_Packages_%s" %
 | |
|                         (options.old.suite, component,
 | |
|                          "_%s" % section_name if section_name else "", arch))
 | |
|                     with closing(urlopen(url)) as url_file:
 | |
|                         with open("%s.gz" % path, "wb") as comp_file:
 | |
|                             comp_file.write(url_file.read())
 | |
|                     with closing(gzip.GzipFile("%s.gz" % path)) as gz_file:
 | |
|                         with open(path, "wb") as out_file:
 | |
|                             out_file.write(gz_file.read())
 | |
|                     with open(path) as packages_file:
 | |
|                         apt_packages = apt_pkg.TagFile(packages_file)
 | |
|                         for section in apt_packages:
 | |
|                             pkg = section["Package"]
 | |
|                             src = section.get("Source", pkg).split(" ", 1)[0]
 | |
|                             if src != options.source:
 | |
|                                 continue
 | |
|                             yield FakeBPPH(pkg, component, das)
 | |
| 
 | |
| 
 | |
| def find_current_binaries(options):
 | |
|     print("Checking existing binaries in %s ..." % options.old.suite,
 | |
|           file=sys.stderr)
 | |
|     sources = options.old.archive.getPublishedSources(
 | |
|         source_name=options.source, distro_series=options.old.series,
 | |
|         pocket=options.old.pocket, exact_match=True, status="Published")
 | |
|     for source in sources:
 | |
|         binaries = defaultdict(dict)
 | |
|         for binary in get_published_binaries(options, source):
 | |
|             print(".", end="")
 | |
|             sys.stdout.flush()
 | |
|             arch = binary.distro_arch_series.architecture_tag
 | |
|             name = binary.binary_package_name
 | |
|             component = binary.component_name
 | |
|             if name not in binaries[arch]:
 | |
|                 binaries[arch][name] = component
 | |
|         if binaries:
 | |
|             print()
 | |
|             return binaries
 | |
|     print()
 | |
|     return []
 | |
| 
 | |
| 
 | |
| def find_matching_uploads(options, newabi):
 | |
|     print("Checking %s uploads to %s ..." %
 | |
|           (options.queue.lower(), options.suite), file=sys.stderr)
 | |
|     uploads = options.series.getPackageUploads(
 | |
|         name=options.source, exact_match=True, archive=options.archive,
 | |
|         pocket=options.pocket, status=options.queue)
 | |
|     for upload in uploads:
 | |
|         if upload.contains_build:
 | |
|             # 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 == options.source:
 | |
|                 binaries = upload.getBinaryProperties()
 | |
|                 binaries = [b for b in binaries if "customformat" not in b]
 | |
|                 if [b for b in binaries if newabi in b["version"]]:
 | |
|                     yield upload, binaries
 | |
| 
 | |
| 
 | |
| def equal_except_abi(old, new, abi):
 | |
|     """Are OLD and NEW the same package name aside from ABI?"""
 | |
|     # Make sure new always contains the ABI.
 | |
|     if abi in old:
 | |
|         old, new = new, old
 | |
|     if abi not in new:
 | |
|         return False
 | |
| 
 | |
|     left, _, right = new.partition(abi)
 | |
|     if not old.startswith(left) or not old.endswith(right):
 | |
|         return False
 | |
|     old_abi = old[len(left):]
 | |
|     if right:
 | |
|         old_abi = old_abi[:-len(right)]
 | |
|     return old_abi[0].isdigit() and old_abi[-1].isdigit()
 | |
| 
 | |
| 
 | |
| def apply_kernel_overrides(options, newabi):
 | |
|     current_binaries = find_current_binaries(options)
 | |
|     all_changes = []
 | |
| 
 | |
|     for upload, binaries in find_matching_uploads(options, newabi):
 | |
|         print("%s/%s (%s):" %
 | |
|               (upload.package_name, upload.package_version,
 | |
|                upload.display_arches.split(",")[0]))
 | |
|         changes = []
 | |
|         for binary in binaries:
 | |
|             if binary["architecture"] not in current_binaries:
 | |
|                 continue
 | |
|             current_binaries_arch = current_binaries[binary["architecture"]]
 | |
|             for name, component in current_binaries_arch.items():
 | |
|                 if (binary["component"] != component and
 | |
|                         equal_except_abi(name, binary["name"], newabi)):
 | |
|                     print("\t%s: %s -> %s" %
 | |
|                           (binary["name"], binary["component"], component))
 | |
|                     changes.append(
 | |
|                         {"name": binary["name"], "component": component})
 | |
|         if changes:
 | |
|             all_changes.append((upload, changes))
 | |
| 
 | |
|     if all_changes:
 | |
|         if options.dry_run:
 | |
|             print("Dry run; no changes made.")
 | |
|         else:
 | |
|             if not options.confirm_all:
 | |
|                 if YesNoQuestion().ask("Override", "no") == "no":
 | |
|                     return
 | |
|             for upload, changes in all_changes:
 | |
|                 upload.overrideBinaries(changes=changes)
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     parser = OptionParser(usage="usage: %prog [options] NEW-ABI")
 | |
|     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 (default: <current series>-proposed)")
 | |
|     parser.add_option(
 | |
|         "--old-suite", metavar="SUITE",
 | |
|         help="look for previous binaries in suite SUITE "
 | |
|              "(default: value of --suite without -proposed)")
 | |
|     parser.add_option(
 | |
|         "-s", "--source", metavar="SOURCE", default="linux",
 | |
|         help="operate on source package SOURCE")
 | |
|     parser.add_option(
 | |
|         "-Q", "--queue", metavar="QUEUE", default="new",
 | |
|         help="consider packages in QUEUE")
 | |
|     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")
 | |
|     options, args = parser.parse_args()
 | |
|     if len(args) != 1:
 | |
|         parser.error("must supply NEW-ABI")
 | |
|     newabi = args[0]
 | |
| 
 | |
|     options.launchpad = Launchpad.login_with(
 | |
|         CONSUMER_KEY, options.launchpad_instance, version="devel")
 | |
| 
 | |
|     if options.suite is None:
 | |
|         distribution = options.launchpad.distributions[options.distribution]
 | |
|         options.suite = "%s-proposed" % distribution.current_series.name
 | |
|     if options.old_suite is None:
 | |
|         options.old_suite = options.suite
 | |
|         if options.old_suite.endswith("-proposed"):
 | |
|             options.old_suite = options.old_suite[:-9]
 | |
|     options.queue = options.queue.title()
 | |
|     options.version = None
 | |
|     lputils.setup_location(options)
 | |
|     options.old = Values()
 | |
|     options.old.launchpad = options.launchpad
 | |
|     options.old.distribution = options.distribution
 | |
|     options.old.suite = options.old_suite
 | |
|     lputils.setup_location(options.old)
 | |
| 
 | |
|     apply_kernel_overrides(options, newabi)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     main()
 |