Skip to content

Instantly share code, notes, and snippets.

@schorschii
Last active September 16, 2025 15:28
Show Gist options
  • Select an option

  • Save schorschii/7c0c72e72bb36dde966ba9f58b4a8da9 to your computer and use it in GitHub Desktop.

Select an option

Save schorschii/7c0c72e72bb36dde966ba9f58b4a8da9 to your computer and use it in GitHub Desktop.
This is the apt downgrade logic of the mintupgrade GUI tool - useful if you want to upgrade many computers via CLI. After changing apt's sources.list and executing `apt dist-upgrade`, you need to downgrade some packages, e.g. base-files to show the correct Mint version in system info dialog (/etc/lsb-release).
#!/usr/bin/python3
import apt
import apt_pkg
import aptsources.sourceslist
import subprocess
# Returns a tuple containing two lists
# The first list is a list of orphaned packages (packages which have no origin)
# The second list is a list of packages which version is not the official version (this does not
# include packages which simply aren't up to date)
def get_foreign_packages(find_orphans=True, find_downgradable_packages=True):
orphan_packages = []
orphan_t64_names = []
downgradable_packages = []
cache = apt.Cache()
for key in cache.keys():
if key == "mintupgrade":
# Ignore mintupgrade, so we can test foreign versions of it.
continue
pkg = cache[key]
if (pkg.is_installed):
installed_version = pkg.installed.version
# Find packages which aren't downloadable
if (pkg.candidate == None) or (not pkg.candidate.downloadable):
if find_orphans:
downloadable = False
for version in pkg.versions:
if version.downloadable:
downloadable = True
if not downloadable:
t64_name = f"{pkg.name}t64"
if t64_name in cache:
orphan_t64_names.append(t64_name)
else:
orphan_packages.append([pkg, installed_version])
if (pkg.candidate != None):
if find_downgradable_packages:
best_version = None
archive = None
for version in pkg.versions:
if not version.downloadable:
continue
for origin in version.origins:
if origin.origin != None and origin.origin.lower() in ("ubuntu", "canonical", "debian", "linuxmint"):
if best_version is None:
best_version = version
archive = origin.archive
else:
if version.policy_priority > best_version.policy_priority:
best_version = version
archive = origin.archive
elif version.policy_priority == best_version.policy_priority:
# same priorities, compare version
return_code = subprocess.call(["dpkg", "--compare-versions", version.version, "gt", best_version.version])
if return_code == 0:
best_version = version
archive = origin.archive
if best_version != None and installed_version != best_version and pkg.candidate.version != best_version.version:
downgradable_packages.append([pkg, installed_version, best_version, archive])
return (orphan_packages, orphan_t64_names, downgradable_packages)
orphans, orphan_t64_names, foreigns = get_foreign_packages(find_orphans=False, find_downgradable_packages=True)
# print downgradable packages
for foreign in foreigns:
print( foreign[0].name+'\t'+foreign[1]+'\t'+foreign[2].version )
print()
# print apt command line for direct execution
print( 'apt install', end=' ' )
for foreign in foreigns:
print( foreign[0].name+'='+foreign[2].version, end=' ' )
print()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment