Last active
December 12, 2016 23:56
-
-
Save palfrey/fe442fb08c2f66db595f6574cd92215b to your computer and use it in GitHub Desktop.
Cross-grade helper script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2016 Tom Parker/Oliver Wyman, opensource@lshift.net | |
# License: AGPLv3 | |
import apt_pkg | |
import os | |
import subprocess | |
apt_pkg.init() | |
cache = apt_pkg.Cache() | |
sourcelist = apt_pkg.SourceList() | |
sourcelist.read_main_list() | |
dc = apt_pkg.DepCache(cache) | |
pr = apt_pkg.PackageRecords(cache) | |
if not cache.is_multi_arch: | |
raise Exception, "Need multi-arch apt_pkg" | |
null = open(os.devnull,"w") | |
def install_version(pkg, version): | |
print "%s: Installing %s:%s" % (pkg.name, version.ver_str, version.arch) | |
dc2 = apt_pkg.DepCache(cache) | |
dc2.init() | |
pm = apt_pkg.PackageManager(dc2) | |
acq = apt_pkg.Acquire() | |
dc2.set_candidate_ver(pkg, version) | |
dc2.mark_install(pkg, False) | |
pm.get_archives(acq, sourcelist, pr) | |
if acq.run() != 0: | |
raise Exception | |
for item in acq.items: | |
if item.error_text != "": | |
raise Exception, item | |
print "%s: Installing %s" % (pkg.name, item.destfile) | |
try: | |
subprocess.check_output(["dpkg", "-i", item.destfile], stderr=subprocess.STDOUT) | |
except subprocess.CalledProcessError: | |
pass # Assume it's due to other package issues that will get resolved later | |
def install_package(pkg, other_pkg): | |
version = other_pkg.current_ver | |
selected = [x for x in pkg.version_list if x.ver_str == version.ver_str] | |
if len(selected) == 1: | |
install_version(pkg, selected[0]) | |
return | |
selected = [x for x in pkg.version_list if apt_pkg.version_compare(version.ver_str, x.ver_str) < 0] | |
selected.sort(cmp=lambda x,y: apt_pkg.version_compare(x.ver_str,y.ver_str)) | |
if len(selected) == 0: | |
if len(pkg.version_list) == 0: | |
print "%s: Assuming local install as no candidate versions, skipping" % pkg.name | |
else: | |
raise Exception, pkg.version_list | |
else: | |
install_version(other_pkg, selected[0]) | |
install_version(pkg, selected[0]) | |
for pkg in cache.packages: | |
if pkg.architecture != "amd64": | |
continue | |
p = pkg.name | |
no_arch = cache[p] | |
if no_arch.version_list == []: | |
continue # skip things without versions | |
if no_arch.version_list[-1].arch == "all": | |
continue # skip Arch:all | |
try: | |
amd64 = cache[p, "amd64"] | |
except KeyError: | |
print "%s: Can't find package for amd64, assuming local install, and skipping" % p | |
continue | |
try: | |
i386 = cache[p, "i386"] | |
except KeyError: | |
# Architecture: all, so could skip | |
continue | |
if i386.current_ver == None: | |
if i386.inst_state == 0 and i386.current_state == 0: | |
# Assume not needed | |
continue | |
if i386.selected_state in [3,4]: # Deinstall or Purge | |
if amd64.current_ver == None: | |
print "%s: No amd64 version!" % p | |
else: | |
subprocess.check_call(["dpkg", "--purge", "%s:i386" % pkg.name]) | |
continue | |
print pkg | |
print "Selected: %d, inst: %d, current: %d"% (i386.selected_state, i386.inst_state, i386.current_state) | |
print "See https://github.com/mvo5/apt/blob/master/apt-pkg/pkgcache.h#L164 for information" | |
raise Exception | |
print "%s: i386" % p, i386.current_ver | |
if amd64.current_ver != None and amd64.current_ver.arch == "all": | |
print "%s: Architecture:all, so skip" % p | |
continue | |
print "%s: amd64" % p, amd64.current_ver | |
if amd64.current_ver == None and i386.current_ver != None: | |
install_package(amd64, i386) | |
elif dc.is_inst_broken(amd64): | |
if i386.current_ver == None: | |
print "%s: No i386, amd64 broken, assuming fixed later..." % p | |
elif amd64.current_ver.ver_str != i386.current_ver.ver_str: | |
print "%s: %s (amd64) != %s (i386)" % (p, amd64.current_ver.ver_str, i386.current_ver.ver_str) | |
comp = apt_pkg.version_compare(amd64.current_ver.ver_str, i386.current_ver.ver_str) | |
if comp > 0: | |
install_package(i386, amd64) | |
elif comp < 0: | |
install_package(amd64, i386) | |
else: | |
raise Exception | |
else: | |
print "%s: i386==amd64, and the latter is broken, assuming fixed later..." % p | |
else: | |
print "%s: All ok apparently!" % p | |
# multi-arch spec https://github.com/mvo5/apt/blob/master/apt-pkg/pkgcache.h#L623 | |
if amd64.current_ver.multi_arch == 4: | |
continue | |
print amd64.current_ver.multi_arch | |
raise Exception |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment