Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions usr/bin/mintupdate-kernel-mark
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/python3

import os
import sys

if os.getuid() != 0:
print("This command needs to be run as root or with sudo.")
sys.exit(1)

if len(sys.argv) != 4:
print("Usage: mintupdate-kernel-mark <version> <kernel_type> <auto|manual>")
sys.exit(1)

version = sys.argv[1]
kernel_type = sys.argv[2]
action = sys.argv[3]

if action not in ("auto", "manual"):
print("Action must be 'auto' or 'manual'")
sys.exit(1)

import apt
import apt.progress.text

KERNEL_PKG_NAMES = [
"linux-headers-VERSION",
"linux-headers-VERSION-KERNELTYPE",
"linux-image-VERSION-KERNELTYPE",
"linux-image-unsigned-VERSION-KERNELTYPE",
"linux-modules-VERSION-KERNELTYPE",
"linux-modules-extra-VERSION-KERNELTYPE",
"linux-image-extra-VERSION-KERNELTYPE",
]

cache = apt.Cache()

for template in KERNEL_PKG_NAMES:
name = template.replace("VERSION", version).replace("-KERNELTYPE", kernel_type)
if name in cache:
pkg = cache[name]
if pkg.is_installed:
pkg.mark_auto(action == "auto")

cache.commit(apt.progress.text.AcquireProgress(),
apt.progress.base.InstallProgress())

sys.exit(0)
6 changes: 4 additions & 2 deletions usr/lib/linuxmint/mintUpdate/checkKernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
installed = 0
used = 0
installable = 0
is_auto = 0
pkg_version = ""
pkg_match = r.match(pkg_name)
if pkg_match:
Expand All @@ -39,6 +40,7 @@
if pkg.is_installed:
installed = 1
pkg_version = pkg.installed.version
is_auto = 1 if pkg.is_auto_installed else 0
else:
# only offer to install same-type kernels
if kernel_type != CONFIGURED_KERNEL_TYPE:
Expand Down Expand Up @@ -100,9 +102,9 @@
# unsupported
support_duration = 0

resultString = "KERNEL###%s###%s###%s###%s###%s###%s###%s###%s###%s###%s" % \
resultString = "KERNEL###%s###%s###%s###%s###%s###%s###%s###%s###%s###%s###%s" % \
(".".join(versions), version, pkg_version, installed, used, installable,
origin, archive, support_duration, kernel_type)
origin, archive, support_duration, kernel_type, is_auto)
print(resultString.encode("utf-8").decode('ascii', 'xmlcharrefreplace'))

except Exception as e:
Expand Down
108 changes: 98 additions & 10 deletions usr/lib/linuxmint/mintUpdate/kernelwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# System imports
import apt
import apt_pkg
import aptkit.simpleclient
import gettext
import locale
Expand Down Expand Up @@ -33,11 +34,12 @@ def list_header_func(row, before, user_data):
row.set_header(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL))

class Kernel():
def __init__(self, version, kernel_type, origin, installed):
def __init__(self, version, kernel_type, origin, installed, is_auto=False):
self.version = version
self.type = kernel_type
self.origin = origin
self.installed = installed
self.is_auto = is_auto

class MarkKernelRow(Gtk.ListBoxRow):
def __init__(self, kernel, kernel_list, version_id=None, supported=None):
Expand All @@ -61,10 +63,13 @@ def on_checked(self, widget):

class KernelRow(Gtk.ListBoxRow):
def __init__(self, version, pkg_version, kernel_type, text, installed, used, title,
installable, origin, support_status, kernel_window):
installable, origin, support_status, is_auto, apt_protected, kernel_window):
Gtk.ListBoxRow.__init__(self)

self.kernel_window = kernel_window
self.version = version
self.kernel_type = kernel_type
self.is_auto = is_auto

vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(vbox)
Expand All @@ -76,6 +81,13 @@ def __init__(self, version, pkg_version, kernel_type, text, installed, used, tit
vbox.pack_start(hbox, True, True, 0)
version_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
hbox.pack_start(version_box, False, False, 0)

pinned = installed and (not is_auto or apt_protected)
icon_name = "xsi-view-pin-symbolic" if pinned else "xsi-empty-icon-symbolic"
self.pin_image = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.MENU)
self.pin_image.set_margin_end(6)
version_box.pack_start(self.pin_image, False, False, 0)

version_label = Gtk.Label()
version_label.set_markup("%s" % text)
version_box.pack_start(version_label, False, False, 0)
Expand Down Expand Up @@ -129,8 +141,25 @@ def __init__(self, version, pkg_version, kernel_type, text, installed, used, tit
box.pack_start(link, False, False, 2)

button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

if installed:
self.do_not_remove_check = Gtk.CheckButton(label=_("Do not automatically remove"))
self.do_not_remove_check.set_active(not is_auto)
if apt_protected:
self.do_not_remove_check.set_active(True)
self.do_not_remove_check.set_sensitive(False)
self.do_not_remove_check.set_tooltip_text(
_("This kernel is protected by APT and will not be automatically removed.")
)
else:
self.do_not_remove_check.set_tooltip_text(
_("When checked, this kernel will not be removed by automatic cleanup.")
)
self.do_not_remove_check.connect("toggled", self.on_do_not_remove_toggled)
button_box.pack_start(self.do_not_remove_check, False, False, 0)

button = Gtk.Button()
kernel = Kernel(version, kernel_type, origin, installed)
kernel = Kernel(version, kernel_type, origin, installed, is_auto)
button.connect("clicked", self.install_kernel, kernel)
queuebutton = Gtk.Button()
queuebutton.connect("clicked", self.queue_kernel, kernel)
Expand Down Expand Up @@ -159,6 +188,36 @@ def show_hide_children(self, widget):
else:
self.revealer.set_reveal_child(True)

def on_do_not_remove_toggled(self, widget):
action = "manual" if widget.get_active() else "auto"
self.do_not_remove_check.set_sensitive(False)
self._run_mark_async(action)

@_async
def _run_mark_async(self, action):
try:
result = subprocess.run(
["pkexec", "/usr/bin/mintupdate-kernel-mark",
self.version, self.kernel_type, action],
capture_output=True, text=True
)
success = (result.returncode == 0)
except Exception:
success = False
self._mark_done(action, success)

@_idle
def _mark_done(self, action, success):
self.do_not_remove_check.set_sensitive(True)
if success:
self.is_auto = (action == "auto")
icon_name = "xsi-empty-icon-symbolic" if self.is_auto else "xsi-view-pin-symbolic"
self.pin_image.set_from_icon_name(icon_name, Gtk.IconSize.MENU)
else:
self.do_not_remove_check.handler_block_by_func(self.on_do_not_remove_toggled)
self.do_not_remove_check.set_active(not self.is_auto)
self.do_not_remove_check.handler_unblock_by_func(self.on_do_not_remove_toggled)

def install_kernel(self, widget, kernel):
if kernel.installed:
message = _("Are you sure you want to remove the %s kernel?") % kernel.version
Expand Down Expand Up @@ -281,10 +340,11 @@ def refresh_kernels_list_done(self, kernels):
ACTIVE_KERNEL_VERSION = "0"
for kernel in kernels:
values = kernel.split('###')
if len(values) == 11:
(version_id, version, pkg_version, installed, used, installable, origin, archive, support_duration, kernel_type) = values[1:]
if len(values) == 12:
(version_id, version, pkg_version, installed, used, installable, origin, archive, support_duration, kernel_type, is_auto) = values[1:]
installed = (installed == "1")
used = (used == "1")
is_auto = (is_auto == "1")
title = ""
if used:
title = _("Active")
Expand All @@ -310,7 +370,7 @@ def refresh_kernels_list_done(self, kernels):
hwe_support_duration[release].append([page_label, support_duration])

kernel_list_prelim.append([version_id, version, pkg_version, kernel_type, page_label, label, installed, used, title,
installable, origin, release, support_duration])
installable, origin, release, support_duration, is_auto])
if page_label not in pages_needed:
pages_needed.append(page_label)
pages_needed_sort.append([version_id, page_label])
Expand Down Expand Up @@ -360,9 +420,36 @@ def refresh_kernels_list_done(self, kernels):
kernel_list = []
supported_kernels = {}

# Determine which installed kernels are APT-protected.
# APT::Protect-Kernels (default true) enables kernel protection.
# APT::NeverAutoRemove::KernelCount (default 2) sets how many
# of the most recent installed kernels are protected. The running
# kernel is always protected regardless of count.
protect_kernels = apt_pkg.config.find_b("APT::Protect-Kernels", True)
kernel_count = apt_pkg.config.find_i("APT::NeverAutoRemove::KernelCount", 2)

installed_version_ids = []
running_version_id = None
for kernel in kernel_list_prelim:
vid, _v, _pv, _kt, _pl, _l, inst, used = kernel[:8]
if inst:
installed_version_ids.append(vid)
if used:
running_version_id = vid
installed_version_ids.sort(reverse=True)

apt_protected_ids = set()
if running_version_id:
apt_protected_ids.add(running_version_id)
if protect_kernels:
for vid in installed_version_ids:
if len(apt_protected_ids) >= kernel_count:
break
apt_protected_ids.add(vid)

self.installed_kernels = []
for kernel in kernel_list_prelim:
(version_id, version, pkg_version, kernel_type, page_label, label, installed, used, title, installable, origin, release, support_duration) = kernel
(version_id, version, pkg_version, kernel_type, page_label, label, installed, used, title, installable, origin, release, support_duration, is_auto) = kernel
support_status = ""
newest_supported_in_series = False
if support_duration and origin == "1":
Expand Down Expand Up @@ -393,8 +480,9 @@ def refresh_kernels_list_done(self, kernels):
self.marked_kernels, version_id,
newest_supported_in_series))

apt_protected = (version_id in apt_protected_ids) if installed else False
kernel_list.append([version_id, version, pkg_version, kernel_type, page_label, label,
installed, used, title, installable, origin, support_status])
installed, used, title, installable, origin, support_status, is_auto, apt_protected])
del(kernel_list_prelim)

# add kernels to UI
Expand All @@ -411,13 +499,13 @@ def refresh_kernels_list_done(self, kernels):
self.ui_kernel_stack.add_titled(scw, page, page)

for kernel in kernel_list:
(version_id, version, pkg_version, kernel_type, page_label, label, installed, used, title, installable, origin, support_status) = kernel
(version_id, version, pkg_version, kernel_type, page_label, label, installed, used, title, installable, origin, support_status, is_auto, apt_protected) = kernel
if used:
currently_using = _("You are currently using the following kernel:")
self.ui_current_label.set_markup("<b>%s %s%s%s</b>" % (currently_using, label, kernel_type, ' (%s)' % support_status if support_status else ''))
if page_label == page:
row = KernelRow(version, pkg_version, kernel_type, label, installed, used, title,
installable, origin, support_status, self)
installable, origin, support_status, is_auto, apt_protected, self)
list_box.add(row)

list_box.connect("row_activated", self.on_row_activated)
Expand Down
12 changes: 12 additions & 0 deletions usr/share/polkit-1/actions/com.linuxmint.updates.policy
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<message xml:lang="fa">مدیر به‌روزرسانی</message>
<message xml:lang="fi">Päivitysten hallinta</message>
<message xml:lang="fil">Tagapamahala ng Update</message>
<message xml:lang="fo">Dagføringa fyrisiting</message>

Check failure on line 38 in usr/share/polkit-1/actions/com.linuxmint.updates.policy

View workflow job for this annotation

GitHub Actions / build / build (mint22, linuxmintd/mint22.3-amd64, Mint 22, true) / Mint 22

fo ==> of, for, to, do, go
<message xml:lang="fr">Gestionnaire de mise à jour</message>
<message xml:lang="fr_CA">Gestionnaire de mise à jour</message>
<message xml:lang="ga">Bainisteoir Nuashonraithe</message>
Expand Down Expand Up @@ -88,7 +88,7 @@
<message xml:lang="sr@latin">Menadžer ažuriranja</message>
<message xml:lang="sv">Uppdateringshanterare</message>
<message xml:lang="ta">மேம்பாட்டு நிர்வகிப்பான்</message>
<message xml:lang="te">నవీకరణ నిర్వాహకం</message>

Check failure on line 91 in usr/share/polkit-1/actions/com.linuxmint.updates.policy

View workflow job for this annotation

GitHub Actions / build / build (mint22, linuxmintd/mint22.3-amd64, Mint 22, true) / Mint 22

te ==> the, be, we, to
<message xml:lang="tg">Мудири навсозиҳо</message>
<message xml:lang="th">โปรแกรมจัดการการปรับปรุง</message>
<message xml:lang="tl">Tagapamahala ng Update</message>
Expand All @@ -109,4 +109,16 @@
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/mintupdate-automation</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">false</annotate>
</action>

<action id="com.linuxmint.updates.kernel-mark">
<icon_name>mintupdate</icon_name>
<message>Update Manager</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/mintupdate-kernel-mark</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">false</annotate>
</action>
</policyconfig>
Loading