Merge lp:~robert-ancell/update-manager/ua-bionic-merge into lp:~ubuntu-core-dev/update-manager/bionic

Proposed by Robert Ancell
Status: Merged
Merged at revision: 2841
Proposed branch: lp:~robert-ancell/update-manager/ua-bionic-merge
Merge into: lp:~ubuntu-core-dev/update-manager/bionic
Diff against target: 353 lines (+112/-22)
5 files modified
UpdateManager/Core/UpdateList.py (+53/-13)
UpdateManager/Dialogs.py (+4/-4)
UpdateManager/UpdateManager.py (+28/-1)
UpdateManager/UpdatesAvailable.py (+21/-4)
debian/changelog (+6/-0)
To merge this branch: bzr merge lp:~robert-ancell/update-manager/ua-bionic-merge
Reviewer Review Type Date Requested Status
Ubuntu Core Development Team Pending
Review via email: mp+435932@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

Merged because this has been uploaded as a SRU.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UpdateManager/Core/UpdateList.py'
2--- UpdateManager/Core/UpdateList.py 2018-10-03 17:45:08 +0000
3+++ UpdateManager/Core/UpdateList.py 2023-01-18 03:42:01 +0000
4@@ -43,11 +43,12 @@
5
6
7 class UpdateItem():
8- def __init__(self, pkg, name, icon, to_remove):
9+ def __init__(self, pkg, name, icon, to_remove, sensitive=True):
10 self.icon = icon
11 self.name = name
12 self.pkg = pkg
13 self.to_remove = to_remove
14+ self.sensitive = sensitive
15
16 def is_selected(self):
17 if not self.to_remove:
18@@ -59,13 +60,13 @@
19 class UpdateGroup(UpdateItem):
20 _depcache = {}
21
22- def __init__(self, pkg, name, icon, to_remove):
23- UpdateItem.__init__(self, pkg, name, icon, to_remove)
24+ def __init__(self, pkg, name, icon, to_remove, sensitive=True):
25+ UpdateItem.__init__(self, pkg, name, icon, to_remove, sensitive)
26 self._items = set()
27 self._deps = set()
28 self.core_item = None
29 if pkg is not None:
30- self.core_item = UpdateItem(pkg, name, icon, to_remove)
31+ self.core_item = UpdateItem(pkg, name, icon, to_remove, sensitive)
32 self._items.add(self.core_item)
33
34 @property
35@@ -74,10 +75,11 @@
36 all_items.extend(self._items)
37 return sorted(all_items, key=lambda a: a.name.lower())
38
39- def add(self, pkg, cache=None, eventloop_callback=None, to_remove=False):
40+ def add(self, pkg, cache=None, eventloop_callback=None, to_remove=False,
41+ sensitive=True):
42 name = utils.get_package_label(pkg)
43 icon = Gio.ThemedIcon.new("package")
44- self._items.add(UpdateItem(pkg, name, icon, to_remove))
45+ self._items.add(UpdateItem(pkg, name, icon, to_remove, sensitive))
46 # If the pkg is in self._deps, stop here. We have already calculated
47 # the recursive dependencies for this package, no need to do it again.
48 if cache and pkg.name in cache and pkg.name not in self._deps:
49@@ -153,27 +155,29 @@
50
51
52 class UpdateApplicationGroup(UpdateGroup):
53- def __init__(self, pkg, application, to_remove):
54+ def __init__(self, pkg, application, to_remove, sensitive=True):
55 name = application.get_display_name()
56 icon = application.get_icon()
57 super(UpdateApplicationGroup, self).__init__(pkg, name, icon,
58- to_remove)
59+ to_remove, sensitive)
60
61
62 class UpdatePackageGroup(UpdateGroup):
63- def __init__(self, pkg, to_remove):
64+ def __init__(self, pkg, to_remove, sensitive=True):
65 name = utils.get_package_label(pkg)
66 icon = Gio.ThemedIcon.new("package")
67- super(UpdatePackageGroup, self).__init__(pkg, name, icon, to_remove)
68+ super(UpdatePackageGroup, self).__init__(pkg, name, icon, to_remove,
69+ sensitive)
70
71
72 class UpdateSystemGroup(UpdateGroup):
73- def __init__(self, cache, to_remove):
74+ def __init__(self, cache, to_remove, sensitive=True):
75 # Translators: the %s is a distro name, like 'Ubuntu' and 'base' as in
76 # the core components and packages.
77 name = _("%s base") % utils.get_ubuntu_flavor_name(cache=cache)
78 icon = Gio.ThemedIcon.new("distributor-logo")
79- super(UpdateSystemGroup, self).__init__(None, name, icon, to_remove)
80+ super(UpdateSystemGroup, self).__init__(None, name, icon, to_remove,
81+ sensitive)
82
83
84 class UpdateOrigin():
85@@ -213,6 +217,7 @@
86 self.update_groups = []
87 self.security_groups = []
88 self.kernel_autoremove_groups = []
89+ self.ubuntu_pro_groups = []
90 self.num_updates = 0
91 self.random = random.Random()
92 self.ignored_phased_updates = []
93@@ -472,7 +477,7 @@
94
95 return app_groups + pkg_groups
96
97- def update(self, cache, eventloop_callback=None):
98+ def update(self, cache, eventloop_callback=None, ua_security_packages=[]):
99 self.held_back = []
100
101 # do the upgrade
102@@ -482,6 +487,34 @@
103 upgrade_pkgs = []
104 kernel_autoremove_pkgs = []
105
106+ class FakeUbuntuProPackageCandidate:
107+ def __init__(self, source_name, version, size):
108+ self.source_name = source_name
109+ self.summary = source_name
110+ self.description = source_name
111+ self.version = version
112+ self.size = size
113+ self.downloadable = False
114+ self.record = {}
115+
116+ class FakeUbuntuProPackage:
117+ def __init__(self, package_name, version, size):
118+ self.name = package_name
119+ self.candidate = FakeUbuntuProPackageCandidate(package_name,
120+ version, size)
121+ self.marked_install = False
122+ self.marked_upgrade = False
123+
124+ def mark_install(self):
125+ pass
126+
127+ def mark_delete(self):
128+ pass
129+ fake_ua_packages = []
130+ for (package_name, version, size) in ua_security_packages:
131+ fake_ua_packages.append(FakeUbuntuProPackage(package_name,
132+ version, size))
133+
134 # Find all upgradable packages
135 for pkg in cache:
136 if pkg.is_upgradable or pkg.marked_install:
137@@ -535,3 +568,10 @@
138 eventloop_callback)
139 self.kernel_autoremove_groups = self._make_groups(
140 cache, kernel_autoremove_pkgs, eventloop_callback, True)
141+ if len(fake_ua_packages) > 0:
142+ ubuntu_pro_group = UpdateGroup(None,
143+ "Ubuntu Pro (enable in Settings…)",
144+ None, False, False)
145+ for package in fake_ua_packages:
146+ ubuntu_pro_group.add(package)
147+ self.ubuntu_pro_groups = [ubuntu_pro_group]
148
149=== modified file 'UpdateManager/Dialogs.py'
150--- UpdateManager/Dialogs.py 2022-09-13 23:50:38 +0000
151+++ UpdateManager/Dialogs.py 2023-01-18 03:42:01 +0000
152@@ -161,10 +161,10 @@
153 if self._is_livepatch_supported() and \
154 self.settings_button and \
155 self.settings.get_int('launch-count') >= 4:
156- self.set_desc(_("<b>Tip:</b> You can use Livepatch to "
157- "keep your computer more secure between "
158- "restarts."))
159- self.settings_button.set_label(_("Settings & Livepatch…"))
160+ self.set_desc(_("<b>Tip:</b> You can use Livepatch with "
161+ "Ubuntu Pro to keep your computer more "
162+ "secure between restarts."))
163+ self.settings_button.set_label(_("Settings & Pro…"))
164 return
165
166 needs_reschedule = False
167
168=== modified file 'UpdateManager/UpdateManager.py'
169--- UpdateManager/UpdateManager.py 2022-09-13 23:50:56 +0000
170+++ UpdateManager/UpdateManager.py 2023-01-18 03:42:01 +0000
171@@ -36,6 +36,7 @@
172
173 import apt_pkg
174 import distro_info
175+import json
176 import os
177 import subprocess
178 import sys
179@@ -85,6 +86,7 @@
180 self.unity = UnitySupport()
181 self.controller = None
182 self.cache = None
183+ self.ua_security_packages = []
184 self.update_list = None
185 self.meta_release = None
186 self.hwe_replacement_packages = None
187@@ -247,6 +249,27 @@
188 cancelled_update, error_occurred)
189 self._start_pane(pane)
190
191+ def _get_ua_security_status(self):
192+ self.ua_security_packages = []
193+ try:
194+ p = subprocess.Popen(['ua', 'security-status', '--format=json'],
195+ stdout=subprocess.PIPE)
196+ except OSError:
197+ pass
198+ else:
199+ while p.poll() is None:
200+ while Gtk.events_pending():
201+ Gtk.main_iteration()
202+ time.sleep(0.05)
203+ s = json.load(p.stdout)
204+ for package in s.get('packages', []):
205+ status = package.get('status', '')
206+ if status == 'pending_attach':
207+ name = package.get('name', '')
208+ version = package.get('version', '')
209+ size = package.get('download_size', 0)
210+ self.ua_security_packages.append((name, version, size))
211+
212 def _make_available_pane(self, install_count, need_reboot=False,
213 cancelled_update=False, error_occurred=False):
214 self._check_hwe_support_status()
215@@ -406,9 +429,13 @@
216 Gtk.main_iteration()
217 iterate()
218
219+ self._get_ua_security_status()
220+
221 self.update_list = UpdateList(self)
222 try:
223- self.update_list.update(self.cache, eventloop_callback=iterate)
224+ self.update_list.update(self.cache, eventloop_callback=iterate,
225+ ua_security_packages=self.
226+ ua_security_packages)
227 except SystemError as e:
228 header = _("Could not calculate the upgrade")
229 desc = _("An unresolvable problem occurred while "
230
231=== modified file 'UpdateManager/UpdatesAvailable.py'
232--- UpdateManager/UpdatesAvailable.py 2018-03-18 21:43:58 +0000
233+++ UpdateManager/UpdatesAvailable.py 2023-01-18 03:42:01 +0000
234@@ -74,7 +74,8 @@
235 # - screen reader does not say "Downloaded" for downloaded updates
236
237 # list constants
238-(LIST_NAME, LIST_UPDATE_DATA, LIST_SIZE, LIST_TOGGLE_ACTIVE) = range(4)
239+(LIST_NAME, LIST_UPDATE_DATA, LIST_SIZE, LIST_TOGGLE_ACTIVE,
240+ LIST_SENSITIVE) = range(5)
241
242 # NetworkManager enums
243 from .Core.roam import NetworkManagerHelper
244@@ -261,7 +262,7 @@
245 changes_buffer.create_tag("versiontag", weight=Pango.Weight.BOLD)
246
247 # the treeview (move into it's own code!)
248- self.store = Gtk.TreeStore(str, GObject.TYPE_PYOBJECT, str, bool)
249+ self.store = Gtk.TreeStore(str, GObject.TYPE_PYOBJECT, str, bool, bool)
250 self.treeview_update.set_model(None)
251
252 self.image_restart.set_from_gicon(self.get_restart_icon(),
253@@ -293,6 +294,8 @@
254 pkg_column.pack_start(pkg_toggle_renderer, False)
255 pkg_column.add_attribute(pkg_toggle_renderer,
256 'active', LIST_TOGGLE_ACTIVE)
257+ pkg_column.add_attribute(pkg_toggle_renderer,
258+ 'sensitive', LIST_SENSITIVE)
259 pkg_column.set_cell_data_func(pkg_toggle_renderer,
260 self.pkg_toggle_renderer_data_func)
261
262@@ -319,6 +322,8 @@
263 size_column = Gtk.TreeViewColumn(_("Download"), size_renderer,
264 text=LIST_SIZE)
265 size_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
266+ size_column.add_attribute(size_renderer,
267+ 'sensitive', LIST_SENSITIVE)
268 self.treeview_update.append_column(size_column)
269
270 self.treeview_update.set_headers_visible(True)
271@@ -404,8 +409,11 @@
272 def restart_icon_renderer_data_func(self, cell_layout, renderer, model,
273 iter, user_data):
274 data = model.get_value(iter, LIST_UPDATE_DATA)
275+ sensitive = model.get_value(iter, LIST_SENSITIVE)
276 path = model.get_path(iter)
277
278+ renderer.set_sensitive(sensitive)
279+
280 requires_restart = False
281 if data.item and data.item.pkg:
282 requires_restart = self.pkg_requires_restart(data.item.pkg)
283@@ -433,6 +441,7 @@
284 if data.item:
285 activatable = data.item.pkg.name not in self.list.held_back
286 inconsistent = False
287+ renderer.set_sensitive(data.item.sensitive)
288 elif data.group:
289 activatable = True
290 inconsistent = data.group.selection_is_inconsistent()
291@@ -485,8 +494,11 @@
292 def pkg_label_renderer_data_func(self, cell_layout, renderer, model,
293 iter, user_data):
294 data = model.get_value(iter, LIST_UPDATE_DATA)
295+ sensitive = model.get_value(iter, LIST_SENSITIVE)
296 name = GLib.markup_escape_text(model.get_value(iter, LIST_NAME))
297
298+ renderer.set_sensitive(sensitive)
299+
300 if data.group:
301 markup = name
302 elif data.item:
303@@ -997,6 +1009,7 @@
304 name,
305 UpdateData(groups, None, None),
306 humanize_size(total_size),
307+ True,
308 True
309 ]
310 return self.store.append(None, header_row)
311@@ -1020,7 +1033,8 @@
312 group.name,
313 UpdateData(None, group, group_is_item),
314 humanize_size(group.get_total_size()),
315- True
316+ True,
317+ group.sensitive
318 ]
319 group_iter = self.store.append(None, group_row)
320
321@@ -1031,7 +1045,8 @@
322 item.name,
323 UpdateData(None, None, item),
324 humanize_size(getattr(item.pkg.candidate, "size", 0)),
325- True
326+ True,
327+ group.sensitive
328 ]
329 self.store.append(group_iter, item_row)
330
331@@ -1063,6 +1078,8 @@
332 _("Unused kernel updates to be removed"),
333 self.list.kernel_autoremove_groups)
334 self._add_groups(self.list.kernel_autoremove_groups)
335+ if self.list.ubuntu_pro_groups:
336+ self._add_groups(self.list.ubuntu_pro_groups)
337
338 self.treeview_update.set_model(self.store)
339 self.pkg_cell_area.indent_toplevel = (
340
341=== modified file 'debian/changelog'
342--- debian/changelog 2022-09-13 23:51:20 +0000
343+++ debian/changelog 2023-01-18 03:42:01 +0000
344@@ -1,3 +1,9 @@
345+update-manager (1:18.04.11.15) bionic; urgency=medium
346+
347+ * Show pending Ubuntu pro packages (LP: #1990450)
348+
349+ -- Robert Ancell <robert.ancell@canonical.com> Wed, 18 Jan 2023 15:09:17 +1300
350+
351 update-manager (1:18.04.11.14) bionic; urgency=medium
352
353 * tests/test_meta_release_core.py: switch a test from using lucid to bionic

Subscribers

People subscribed via source and target branches