Skip to content

Instantly share code, notes, and snippets.

@palfrey
Last active December 12, 2016 23:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save palfrey/fe442fb08c2f66db595f6574cd92215b to your computer and use it in GitHub Desktop.
Save palfrey/fe442fb08c2f66db595f6574cd92215b to your computer and use it in GitHub Desktop.
Cross-grade helper script
# 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