Mark installed kernel packages as automatically installed. - #1081
Open
AlexB7 wants to merge 1 commit into
Open
Conversation
mintupdate installs kernel packages (linux-image-*, linux-headers-*, linux-modules-*) directly by name whenever no meta package tracks the exact version, and always does so from the kernel selection window. Since these are requested by name rather than pulled in as a dependency, apt records them as manually installed, so "apt autoremove" (and mintupdate's own "remove obsolete kernels" automation, which just runs apt-get autoremove) can never reclaim them once superseded, and old kernels accumulate indefinitely. Tag these package names with aptkit's "#auto" suffix convention before handing them to aptkit, so they get flagged the same way a normal kernel upgrade via a meta package would. The new is_real_kernel_package() helper distinguishes version-specific kernel packages from meta packages (which must stay manual) by looking for an embedded VERSION-ABI kernel version rather than enumerating package flavors, so versioned flavors such as linux-modules-iwlwifi-* and linux-hwe-X.Y-headers-* are covered too. A companion fix in aptkit's SimpleAPTClient.install_packages() is needed for the update-list path, where local dependency resolution previously dropped the "#auto" marker; without it this change still works, but dependency packages discovered client-side get recorded as manual. Fixes linuxmint#938. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 13, 2026
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes: #938 and #1078
Summary
apt autoremove(and mintupdate's own "Remove obsolete kernels and dependencies" automation, which just shells out toapt-get autoremove --purge -y) was never cleaning up old kernels installed through mintupdate. The root cause: kernel packages installed via the GUI were being recorded by apt as manually installed instead of automatically installed, so they never became autoremove candidates in the first place and just accumulated indefinitely.Root cause
mintupdate installs the real, version-specific kernel packages (
linux-image-*,linux-headers-*,linux-modules-*,linux-modules-extra-*) directly by package name in two places:aptUpdater.py'sfind_changes()fallback path (no meta package tracks the exact point-release version), which ends up inmintUpdate.py'sinstall().kernelwindow.py'sinstall_kernels(), used by the kernel selection window, always installs the literal versioned packages.Because these are requested by name rather than pulled in transitively as a dependency of a meta package (like a normal
apt upgradewould do), apt/aptkit records them as manually installed. Manually installed packages are permanently exempt fromapt autoremove, so every kernel mintupdate ever installs this way sticks around forever.I confirmed this empirically on a test system:
apt-mark showmanuallisted every installed kernel package (image/headers/modules/ modules-extra, across every installed kernel version) as manual, andapt-mark showautoreturned none.aptkit already has a mechanism for this — package names can carry an
#autosuffix (seeaptworker._mark_packages_for_installation()) telling the worker to record the package as automatically installed (pkg.mark_install(False, False, from_user=False)) instead of manually. mintupdate never used it.Fix
Classes.py: addis_real_kernel_package(), a small regex helper that identifies actual version-specific kernel packages (linux-image-6.17.0-41-generic,linux-headers-7.0.0-28,linux-modules-iwlwifi-6.8.0-41-generic, ...) as opposed to meta packages (linux-generic,linux-generic-hwe-24.04,linux-virtual, ...), which should stay manual, same as they would after a normal install. Rather than enumerating package flavors, it keys off the embedded VERSION-ABI kernel version (\d+\.\d+\.\d+-\d+), which versioned kernel packages always contain and meta package names never do (an HWE series suffix like-hwe-24.04has no third version component or ABI number). This also covers versioned flavors mintupdate doesn't install itself but may upgrade in place on a same-ABI respin (linux-modules-iwlwifi/ipu6/usbio-*,linux-hwe-X.Y-headers-*), which would otherwise get flipped from automatic to manual by an explicit-by-name upgrade.mintUpdate.pyinstall(): tag real kernel package names with#autobefore adding them to the list handed to aptkit.kernelwindow.pyinstall_kernels(): tag allto_installkernel package names with#auto(everything built there is already a real, versioned package, so no filtering needed).History: when this broke
Kernel autoremoval used to work for most users, and the regression point is identifiable:
The "#auto" marker this PR uses has been supported by the aptkit worker the whole time - it was inherited from aptdaemon when aptkit was forked (April 2022) - it just was never used by any client.
Design note: kernel window installs are also tagged
Tagging the kernel selection window's installs
#autois a deliberate choice worth calling out: it means a kernel version the user explicitly picked there becomes autoremove-eligible once superseded. Apt's built-in protection always keeps the running kernel and the newest installed ones, and the "Remove obsolete kernels and dependencies" automation is opt-in and advertises exactly this behavior — but a user who installs an older kernel as a deliberate boot fallback, isn't running it, and has that automation enabled could see it cleaned up. If maintainers prefer to treat kernel-window installs as an explicit manual choice, dropping thekernelwindow.pyhunk keeps the main-update-list fix (the #938 scenario) intact.Companion fix
This alone isn't sufficient —
aptkit.simpleclient.SimpleAPTClient .install_packages()locally resolves dependencies and flattens any newly-discovered packages into the request list without preserving the#autotag, which silently drops the auto/manual distinction even for well-behaved meta-package-driven kernel installs. A companion fix is needed in aptkit itself: https://github.com/linuxmint/aptkit (PR linuxmint/aptkit#19).There is no hard version lockstep, so the two can land independently: with an unpatched aptkit, the kernel window path (
commit_changes) does no local resolution and works fully, and on the update-list path the tagged name still reaches the aptkit worker (which already understands#auto); only the local dependency-flattening step misses it, printing a harmless "Package ... not found in the cache!" line. Once the aptkit fix is released, mintupdate's aptkit dependency in debian/control should be bumped accordingly.Testing
Manually tested on a Mint 24.04-based system:
apt-mark showautothat all installed image/headers/modules/modules-extra packages for those kernels are now flagged automatic (previously they showed up underapt-mark showmanualinstead).apt-get autoremove --dry-runthat the superseded kernel packages are now correctly identified as removal candidates once a newer kernel supersedes them, and that the currently running kernel is left alone.apt autoremovefor real and confirmed the superseded kernel packages were removed while the running kernel remained intact and bootable.No existing tests cover the modified install-list-building code paths (
tests/test_kernel_window.pydoesn't touchinstall_kernels()'sto_installconstruction).Claude Fable 5 was used to fix these issues.