2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
1 |
# UpdateManager.py
|
2511.1.8
by Michael Terry
more pep8 fixes |
2 |
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
|
2511.1.14
by Michael Terry
auto-pep8'd some warnings |
3 |
#
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
4 |
# Copyright (c) 2012 Canonical
|
2511.1.14
by Michael Terry
auto-pep8'd some warnings |
5 |
#
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
6 |
# Author: Michael Terry <michael.terry@canonical.com>
|
2511.1.14
by Michael Terry
auto-pep8'd some warnings |
7 |
#
|
8 |
# This program is free software; you can redistribute it and/or
|
|
9 |
# modify it under the terms of the GNU General Public License as
|
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
10 |
# published by the Free Software Foundation; either version 2 of the
|
11 |
# License, or (at your option) any later version.
|
|
2511.1.14
by Michael Terry
auto-pep8'd some warnings |
12 |
#
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
13 |
# This program is distributed in the hope that it will be useful,
|
14 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16 |
# GNU General Public License for more details.
|
|
2511.1.14
by Michael Terry
auto-pep8'd some warnings |
17 |
#
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
18 |
# You should have received a copy of the GNU General Public License
|
19 |
# along with this program; if not, write to the Free Software
|
|
20 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
21 |
# USA
|
|
22 |
||
23 |
from __future__ import absolute_import, print_function |
|
24 |
||
25 |
from gi.repository import Gtk |
|
2622.1.11
by Dylan McCall
Removed unnecessary resizing of main window during _start_pane. |
26 |
from gi.repository import Gdk, GdkX11 |
2428.4.5
by Michael Terry
move meta release checking into main UpdateManager class; use dialog panes for those interactions rather than popup dialogs |
27 |
from gi.repository import Gio |
28 |
from gi.repository import GLib |
|
2820
by Mathieu Trudel-Lapierre
Block style context changed signal while enforcing the main window's |
29 |
from gi.repository import GObject |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
30 |
|
2633
by Martin Pitt
Drop unused imports and assignments to fix pyflakes errors. |
31 |
GdkX11 # pyflakes |
32 |
||
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
33 |
import warnings |
2511.1.8
by Michael Terry
more pep8 fixes |
34 |
warnings.filterwarnings("ignore", "Accessed deprecated property", |
35 |
DeprecationWarning) |
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
36 |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
37 |
import distro_info |
2893.2.1
by Iain Lane
List OEM metapackages |
38 |
import fnmatch |
2947.1.5
by Robert Ancell
Get package list from ua security-status |
39 |
import json |
2428.4.4
by Michael Terry
move cache from UpdatesAvailable to UpdateManager; use generic ErrorDialog class in a few places |
40 |
import os |
2622.1.1
by Dylan McCall
Defensive coding around package objects in UpdateList and UpdatesAvailable. |
41 |
import subprocess |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
42 |
import sys |
2622.1.1
by Dylan McCall
Defensive coding around package objects in UpdateList and UpdatesAvailable. |
43 |
import time |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
44 |
from gettext import gettext as _ |
45 |
||
46 |
import dbus |
|
47 |
import dbus.service |
|
48 |
from dbus.mainloop.glib import DBusGMainLoop |
|
49 |
DBusGMainLoop(set_as_default=True) |
|
50 |
||
51 |
from .UnitySupport import UnitySupport |
|
2428.4.5
by Michael Terry
move meta release checking into main UpdateManager class; use dialog panes for those interactions rather than popup dialogs |
52 |
from .Dialogs import (DistUpgradeDialog, |
53 |
ErrorDialog, |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
54 |
HWEUpgradeDialog, |
2428.4.5
by Michael Terry
move meta release checking into main UpdateManager class; use dialog panes for those interactions rather than popup dialogs |
55 |
NeedRestartDialog, |
56 |
NoUpdatesDialog, |
|
2864.1.1
by Brian Murray
UpdateManager/UpdateManager.py: Do not offer to upgrade systems running on |
57 |
NoUpgradeForYouDialog, |
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
58 |
PartialUpgradeDialog, |
2534.1.1
by Michael Terry
add you-stopped-update dialog |
59 |
StoppedUpdatesDialog, |
2565.1.1
by Michael Terry
Allow user to continue if an update error occurs |
60 |
UnsupportedDialog, |
61 |
UpdateErrorDialog) |
|
2428.4.5
by Michael Terry
move meta release checking into main UpdateManager class; use dialog panes for those interactions rather than popup dialogs |
62 |
from .MetaReleaseGObject import MetaRelease |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
63 |
from .UpdatesAvailable import UpdatesAvailable |
64 |
from .Core.AlertWatcher import AlertWatcher |
|
2428.4.4
by Michael Terry
move cache from UpdatesAvailable to UpdateManager; use generic ErrorDialog class in a few places |
65 |
from .Core.MyCache import MyCache |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
66 |
from .Core.roam import NetworkManagerHelper |
2428.4.4
by Michael Terry
move cache from UpdatesAvailable to UpdateManager; use generic ErrorDialog class in a few places |
67 |
from .Core.UpdateList import UpdateList |
2864.1.1
by Brian Murray
UpdateManager/UpdateManager.py: Do not offer to upgrade systems running on |
68 |
from .Core.utils import get_arch, get_dist |
2622.1.12
by Dylan McCall
Put back the "backend" module. It wasn't necessary to move it in this branch. |
69 |
from .backend import (InstallBackend, |
70 |
get_backend) |
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
71 |
|
2428.4.1
by Michael Terry
add basic support for no-updates-needed and restart-needed dialogs |
72 |
# file that signals if we need to reboot
|
73 |
REBOOT_REQUIRED_FILE = "/var/run/reboot-required" |
|
74 |
||
2511.1.8
by Michael Terry
more pep8 fixes |
75 |
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
76 |
class UpdateManager(Gtk.Window): |
2622.1.7
by Dylan McCall
Every GUI component is now a Dialog subclass, inserted as a widget into the main window, by the main window. |
77 |
""" This class is the main window and work flow controller. The main
|
78 |
window will show panes, and it will morph between them. """
|
|
2511.1.8
by Michael Terry
more pep8 fixes |
79 |
|
80 |
def __init__(self, datadir, options): |
|
81 |
Gtk.Window.__init__(self) |
|
82 |
||
83 |
# Public members
|
|
84 |
self.datadir = datadir |
|
85 |
self.options = options |
|
86 |
self.unity = UnitySupport() |
|
87 |
self.controller = None |
|
88 |
self.cache = None |
|
2947.1.5
by Robert Ancell
Get package list from ua security-status |
89 |
self.ua_security_packages = [] |
2511.1.8
by Michael Terry
more pep8 fixes |
90 |
self.update_list = None |
91 |
self.meta_release = None |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
92 |
self.hwe_replacement_packages = None |
2893.2.1
by Iain Lane
List OEM metapackages |
93 |
self.oem_metapackages = set() |
2875.1.1
by Marcus Tomlinson
Fix TypeError crash in update() |
94 |
self.duplicate_packages = [] |
2864.1.1
by Brian Murray
UpdateManager/UpdateManager.py: Do not offer to upgrade systems running on |
95 |
self.arch = get_arch() |
2511.1.8
by Michael Terry
more pep8 fixes |
96 |
|
97 |
# Basic GTK+ parameters
|
|
98 |
self.set_title(_("Software Updater")) |
|
99 |
self.set_icon_name("system-software-update") |
|
100 |
self.set_position(Gtk.WindowPosition.CENTER) |
|
2568.1.1
by Michael Terry
Keep dialog width at 33em |
101 |
|
102 |
# Keep window at a constant size
|
|
103 |
ctx = self.get_style_context() |
|
2820
by Mathieu Trudel-Lapierre
Block style context changed signal while enforcing the main window's |
104 |
self.style_changed = ctx.connect("changed", |
105 |
lambda ctx: |
|
106 |
self.resize_to_standard_width()) |
|
2511.1.8
by Michael Terry
more pep8 fixes |
107 |
|
108 |
# Signals
|
|
2622.1.8
by Dylan McCall
Fixed broken close buttons and certain dialogs failing to initialize. |
109 |
self.connect("delete-event", self._on_close) |
2511.1.8
by Michael Terry
more pep8 fixes |
110 |
|
111 |
self._setup_dbus() |
|
112 |
||
113 |
# deal with no-focus-on-map
|
|
114 |
if self.options and self.options.no_focus_on_map: |
|
115 |
self.set_focus_on_map(False) |
|
116 |
self.iconify() |
|
117 |
self.stick() |
|
118 |
self.set_urgency_hint(True) |
|
119 |
self.unity.set_urgency(True) |
|
120 |
self.initial_focus_id = self.connect( |
|
121 |
"focus-in-event", self.on_initial_focus_in) |
|
122 |
||
123 |
# Look for a new release in a thread
|
|
124 |
self.meta_release = MetaRelease( |
|
125 |
self.options and self.options.devel_release, |
|
2933
by Brian Murray
If --debug is used on the command line pass it along to the metarelease |
126 |
self.options and self.options.use_proposed, |
127 |
self.options and self.options.debug) |
|
2511.1.8
by Michael Terry
more pep8 fixes |
128 |
|
2622.1.7
by Dylan McCall
Every GUI component is now a Dialog subclass, inserted as a widget into the main window, by the main window. |
129 |
def begin_user_resizable(self, stored_width=0, stored_height=0): |
130 |
self.set_resizable(True) |
|
131 |
if stored_width > 0 and stored_height > 0: |
|
132 |
# There is a race here. If we immediately resize, it often doesn't
|
|
133 |
# take. Using idle_add helps, but we *still* occasionally don't
|
|
134 |
# restore the size correctly. Help needed to track this down!
|
|
135 |
GLib.idle_add(lambda: self.resize(stored_width, stored_height)) |
|
136 |
||
137 |
def end_user_resizable(self): |
|
138 |
self.set_resizable(False) |
|
139 |
||
2568.1.1
by Michael Terry
Keep dialog width at 33em |
140 |
def resize_to_standard_width(self): |
141 |
if self.get_resizable(): |
|
142 |
return # only size to a specific em if we are a static size |
|
143 |
num_em = 33 # per SoftwareUpdates spec |
|
144 |
dpi = self.get_screen().get_resolution() |
|
145 |
if dpi <= 0: |
|
146 |
dpi = 96 |
|
147 |
ctx = self.get_style_context() |
|
2823
by Mathieu Trudel-Lapierre
Fix my spelling mistake in the previous upload. Oops. |
148 |
GObject.signal_handler_block(ctx, self.style_changed) |
2568.1.1
by Michael Terry
Keep dialog width at 33em |
149 |
size = ctx.get_property("font-size", Gtk.StateFlags.NORMAL) |
150 |
width = dpi / 72 * size * num_em |
|
151 |
self.set_size_request(width, -1) |
|
2823
by Mathieu Trudel-Lapierre
Fix my spelling mistake in the previous upload. Oops. |
152 |
GObject.signal_handler_unblock(ctx, self.style_changed) |
2568.1.1
by Michael Terry
Keep dialog width at 33em |
153 |
|
2511.1.8
by Michael Terry
more pep8 fixes |
154 |
def on_initial_focus_in(self, widget, event): |
155 |
"""callback run on initial focus-in (if started unmapped)"""
|
|
156 |
self.unstick() |
|
157 |
self.set_urgency_hint(False) |
|
158 |
self.unity.set_urgency(False) |
|
159 |
self.disconnect(self.initial_focus_id) |
|
160 |
return False |
|
161 |
||
2622.1.7
by Dylan McCall
Every GUI component is now a Dialog subclass, inserted as a widget into the main window, by the main window. |
162 |
def _start_pane(self, pane): |
163 |
if self.controller is not None: |
|
164 |
self.controller.stop() |
|
165 |
if isinstance(self.controller, Gtk.Widget): |
|
166 |
self.controller.destroy() |
|
167 |
||
168 |
self.controller = pane |
|
169 |
self._look_ready() |
|
2622.1.11
by Dylan McCall
Removed unnecessary resizing of main window during _start_pane. |
170 |
self.end_user_resizable() |
2511.1.8
by Michael Terry
more pep8 fixes |
171 |
|
172 |
if pane is None: |
|
173 |
return
|
|
174 |
||
2622.1.7
by Dylan McCall
Every GUI component is now a Dialog subclass, inserted as a widget into the main window, by the main window. |
175 |
if isinstance(pane, Gtk.Widget): |
176 |
self.add(pane) |
|
2622.1.11
by Dylan McCall
Removed unnecessary resizing of main window during _start_pane. |
177 |
pane.start() |
2622.1.10
by Dylan McCall
Removing ill-advised WrapLabel widget. Restored original behaviour for text wrapping in heading and description labels. |
178 |
self.show_all() |
179 |
else: |
|
2622.1.11
by Dylan McCall
Removed unnecessary resizing of main window during _start_pane. |
180 |
pane.start() |
2622.1.10
by Dylan McCall
Removing ill-advised WrapLabel widget. Restored original behaviour for text wrapping in heading and description labels. |
181 |
self.hide() |
2511.1.8
by Michael Terry
more pep8 fixes |
182 |
|
2622.1.8
by Dylan McCall
Fixed broken close buttons and certain dialogs failing to initialize. |
183 |
def _on_close(self, widget, data=None): |
2691
by Michael Vogt
UpdateManager/UpdateManager.py: _on_close() should return the value to make |
184 |
return self.close() |
2622.1.8
by Dylan McCall
Fixed broken close buttons and certain dialogs failing to initialize. |
185 |
|
186 |
def close(self): |
|
2511.1.8
by Michael Terry
more pep8 fixes |
187 |
if not self.get_sensitive(): |
188 |
return True |
|
189 |
||
2658.1.1
by Sebastien Bacher
check if there is a controller before using it |
190 |
if self.controller: |
191 |
controller_close = self.controller.close() |
|
192 |
if controller_close: |
|
193 |
return controller_close |
|
2511.1.8
by Michael Terry
more pep8 fixes |
194 |
self.exit() |
195 |
||
196 |
def exit(self): |
|
197 |
""" exit the application, save the state """
|
|
2622.1.7
by Dylan McCall
Every GUI component is now a Dialog subclass, inserted as a widget into the main window, by the main window. |
198 |
self._start_pane(None) |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
199 |
sys.exit(0) |
2511.1.8
by Michael Terry
more pep8 fixes |
200 |
|
2622.1.1
by Dylan McCall
Defensive coding around package objects in UpdateList and UpdatesAvailable. |
201 |
def show_settings(self): |
202 |
cmd = ["/usr/bin/software-properties-gtk", |
|
2786
by Brian Murray
UpdateManager.py: Workaround a crash when calling software-properties-gtk |
203 |
"--open-tab", "2"] |
204 |
||
205 |
if "WAYLAND_DISPLAY" not in os.environ: |
|
206 |
cmd += ["--toplevel", "%s" % self.get_window().get_xid()] |
|
207 |
||
2622.1.2
by Dylan McCall
UpdatesAvailable is now a Dialog subclass. |
208 |
self._look_busy() |
2622.1.1
by Dylan McCall
Defensive coding around package objects in UpdateList and UpdatesAvailable. |
209 |
try: |
210 |
p = subprocess.Popen(cmd) |
|
211 |
except OSError: |
|
212 |
pass
|
|
213 |
else: |
|
214 |
while p.poll() is None: |
|
215 |
while Gtk.events_pending(): |
|
216 |
Gtk.main_iteration() |
|
217 |
time.sleep(0.05) |
|
218 |
finally: |
|
219 |
self.start_available() |
|
220 |
||
2511.1.8
by Michael Terry
more pep8 fixes |
221 |
def start_update(self): |
222 |
if self.options.no_update: |
|
223 |
self.start_available() |
|
224 |
return
|
|
225 |
||
2622.1.7
by Dylan McCall
Every GUI component is now a Dialog subclass, inserted as a widget into the main window, by the main window. |
226 |
update_backend = get_backend(self, InstallBackend.ACTION_UPDATE) |
227 |
self._start_pane(update_backend) |
|
228 |
||
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
229 |
def start_install(self, hwe_upgrade=False): |
2893.2.1
by Iain Lane
List OEM metapackages |
230 |
install_backend = get_backend(self, InstallBackend.ACTION_PRE_INSTALL) |
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
231 |
if hwe_upgrade: |
232 |
for pkgname in self.hwe_replacement_packages: |
|
2734
by Brian Murray
UpdateManager/UpdateManager.py: when marking HWE packages for install pass |
233 |
try: |
234 |
self.cache[pkgname].mark_install() |
|
235 |
except SystemError: |
|
236 |
pass
|
|
2622.1.7
by Dylan McCall
Every GUI component is now a Dialog subclass, inserted as a widget into the main window, by the main window. |
237 |
self._start_pane(install_backend) |
2511.1.8
by Michael Terry
more pep8 fixes |
238 |
|
2568
by Michael Terry
whoops, fix typo in error-during-update branch that caused us to show a warning more often than needed |
239 |
def start_available(self, cancelled_update=False, error_occurred=False): |
2511.1.8
by Michael Terry
more pep8 fixes |
240 |
self._look_busy() |
241 |
self.refresh_cache() |
|
242 |
||
2887.1.1
by Brian Murray
UpdateManager/UpdateManager.py: when refreshing the cache and encountering |
243 |
if self.cache is None: |
244 |
return
|
|
245 |
||
2865
by Marcus Tomlinson
UpdateManager/backend/__init__.py: once apt upgrade completes, use the deb2snap.json file from ubuntu-release-upgrader to perform snap updates. |
246 |
pane = self._make_available_pane(self.cache.install_count |
247 |
+ self.cache.del_count, |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
248 |
os.path.exists(REBOOT_REQUIRED_FILE), |
2565.1.1
by Michael Terry
Allow user to continue if an update error occurs |
249 |
cancelled_update, error_occurred) |
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
250 |
self._start_pane(pane) |
251 |
||
2893.2.1
by Iain Lane
List OEM metapackages |
252 |
def _check_oem_metapackages(self): |
253 |
di = distro_info.UbuntuDistroInfo() |
|
254 |
codename = get_dist() |
|
255 |
lts = di.is_lts(codename) |
|
256 |
if not lts: |
|
257 |
return None |
|
258 |
OEM_PATH = os.path.join(GLib.get_user_runtime_dir(), |
|
259 |
"ubuntu-drivers-oem.package-list") |
|
260 |
if not os.path.exists(OEM_PATH): |
|
261 |
return None |
|
262 |
||
263 |
# Packages that aren't installed but apply to this system
|
|
264 |
with open(OEM_PATH, 'r') as f: |
|
265 |
self.oem_metapackages |= set(f.read().splitlines()) |
|
266 |
||
267 |
# Packages that are already installed
|
|
268 |
for pkg in self.cache: |
|
269 |
if fnmatch.fnmatch(pkg.name, 'oem-*-meta') \ |
|
270 |
and pkg.installed: |
|
271 |
self.oem_metapackages.add(pkg) |
|
272 |
||
2947.1.5
by Robert Ancell
Get package list from ua security-status |
273 |
def _get_ua_security_status(self): |
274 |
self.ua_security_packages = [] |
|
275 |
try: |
|
2957
by Sebastien Bacher
Update of the parsing for pro client changes |
276 |
p = subprocess.Popen(['pro', 'security-status', '--format=json'], |
2953
by Steve Langasek
Fix autopkgtest regressions. |
277 |
stdout=subprocess.PIPE) |
2947.1.5
by Robert Ancell
Get package list from ua security-status |
278 |
except OSError: |
279 |
pass
|
|
280 |
else: |
|
281 |
while p.poll() is None: |
|
282 |
while Gtk.events_pending(): |
|
283 |
Gtk.main_iteration() |
|
284 |
time.sleep(0.05) |
|
2947.1.13
by Robert Ancell
Use json.load instead of json.loads |
285 |
s = json.load(p.stdout) |
2947.1.6
by Robert Ancell
Only show packages pending attach |
286 |
for package in s.get('packages', []): |
287 |
status = package.get('status', '') |
|
288 |
if status == 'pending_attach': |
|
2957
by Sebastien Bacher
Update of the parsing for pro client changes |
289 |
name = package.get('package', '') |
2947.1.6
by Robert Ancell
Only show packages pending attach |
290 |
version = package.get('version', '') |
2953
by Steve Langasek
Fix autopkgtest regressions. |
291 |
size = package.get('download_size', 0) |
2947.1.7
by Robert Ancell
Add size to UA packages |
292 |
self.ua_security_packages.append((name, version, size)) |
2947.1.5
by Robert Ancell
Get package list from ua security-status |
293 |
|
2565.1.1
by Michael Terry
Allow user to continue if an update error occurs |
294 |
def _make_available_pane(self, install_count, need_reboot=False, |
295 |
cancelled_update=False, error_occurred=False): |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
296 |
self._check_hwe_support_status() |
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
297 |
if install_count == 0: |
2522.1.1
by Michael Terry
Update package cache and unity badge before showing restart-needed dialog |
298 |
# Need Restart > New Release > No Updates
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
299 |
if need_reboot: |
300 |
return NeedRestartDialog(self) |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
301 |
dist_upgrade = self._check_meta_release() |
302 |
if dist_upgrade: |
|
303 |
return dist_upgrade |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
304 |
elif cancelled_update: |
305 |
return StoppedUpdatesDialog(self) |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
306 |
elif self.hwe_replacement_packages: |
307 |
return HWEUpgradeDialog(self) |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
308 |
else: |
2565.1.1
by Michael Terry
Allow user to continue if an update error occurs |
309 |
return NoUpdatesDialog(self, error_occurred=error_occurred) |
2511.1.8
by Michael Terry
more pep8 fixes |
310 |
else: |
2534.1.1
by Michael Terry
add you-stopped-update dialog |
311 |
header = None |
312 |
desc = None |
|
2565.1.1
by Michael Terry
Allow user to continue if an update error occurs |
313 |
if error_occurred: |
314 |
desc = _("Some software couldn’t be checked for updates.") |
|
315 |
elif cancelled_update: |
|
2534.1.1
by Michael Terry
add you-stopped-update dialog |
316 |
header = _("You stopped the check for updates.") |
317 |
desc = _("Updated software is available from " |
|
318 |
"a previous check.") |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
319 |
# Display HWE updates first as an old HWE stack is vulnerable
|
320 |
elif self.hwe_replacement_packages: |
|
321 |
return HWEUpgradeDialog(self) |
|
2664
by Marc Deslauriers
* Allow user to close the restart required dialog (LP: #1033226) |
322 |
return UpdatesAvailable(self, header, desc, need_reboot) |
2511.1.8
by Michael Terry
more pep8 fixes |
323 |
|
2835.1.1
by Balint Reczey
Print transaction error and let the user try again applying updates |
324 |
def start_error(self, update_and_retry, header, desc): |
325 |
if update_and_retry: |
|
2565.1.1
by Michael Terry
Allow user to continue if an update error occurs |
326 |
self._start_pane(UpdateErrorDialog(self, header, desc)) |
327 |
else: |
|
328 |
self._start_pane(ErrorDialog(self, header, desc)) |
|
2511.1.8
by Michael Terry
more pep8 fixes |
329 |
|
330 |
def _look_busy(self): |
|
331 |
self.set_sensitive(False) |
|
332 |
if self.get_window() is not None: |
|
333 |
self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) |
|
334 |
||
2622.1.2
by Dylan McCall
UpdatesAvailable is now a Dialog subclass. |
335 |
def _look_ready(self): |
336 |
self.set_sensitive(True) |
|
337 |
if self.get_window() is not None: |
|
338 |
self.get_window().set_cursor(None) |
|
339 |
self.get_window().set_functions(Gdk.WMFunction.ALL) |
|
340 |
||
2511.1.8
by Michael Terry
more pep8 fixes |
341 |
def _check_meta_release(self): |
342 |
if self.meta_release is None: |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
343 |
return None |
2511.1.8
by Michael Terry
more pep8 fixes |
344 |
|
345 |
if self.meta_release.downloading: |
|
346 |
# Block until we get an answer
|
|
347 |
GLib.idle_add(self._meta_release_wait_idle) |
|
348 |
Gtk.main() |
|
349 |
||
350 |
# Check if there is anything to upgrade to or a known-broken upgrade
|
|
351 |
next = self.meta_release.upgradable_to |
|
352 |
if not next or next.upgrade_broken: |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
353 |
return None |
2511.1.8
by Michael Terry
more pep8 fixes |
354 |
|
355 |
# Check for end-of-life
|
|
356 |
if self.meta_release.no_longer_supported: |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
357 |
return UnsupportedDialog(self, self.meta_release) |
2511.1.8
by Michael Terry
more pep8 fixes |
358 |
|
359 |
# Check for new fresh release
|
|
2662
by Martin Pitt
Stop using deprecated GObject constructors with positional arguments |
360 |
settings = Gio.Settings.new("com.ubuntu.update-manager") |
2841.1.1
by Balint Reczey
Ignore PEP 8 W503 instead of E502 and drop many added backslashes |
361 |
if (self.meta_release.new_dist |
362 |
and (self.options.check_dist_upgrades |
|
2840.1.1
by Balint Reczey
Fix PEP 8 warnings |
363 |
or settings.get_boolean("check-dist-upgrades"))): |
2864.1.1
by Brian Murray
UpdateManager/UpdateManager.py: Do not offer to upgrade systems running on |
364 |
if self.arch == 'i386': |
365 |
return NoUpgradeForYouDialog(self, self.meta_release, |
|
366 |
self.arch) |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
367 |
return DistUpgradeDialog(self, self.meta_release) |
2511.1.8
by Michael Terry
more pep8 fixes |
368 |
|
2534.1.5
by Michael Terry
adjust code to make the UpdateManager class slightly easier to unit test; add tests for stop-update code |
369 |
return None |
2511.1.8
by Michael Terry
more pep8 fixes |
370 |
|
371 |
def _meta_release_wait_idle(self): |
|
372 |
# 'downloading' is changed in a thread, but the signal
|
|
373 |
# 'done_downloading' is done in our thread's event loop. So we know
|
|
374 |
# that it won't fire while we're in this function.
|
|
375 |
if not self.meta_release.downloading: |
|
376 |
Gtk.main_quit() |
|
377 |
else: |
|
378 |
self.meta_release.connect("done_downloading", Gtk.main_quit) |
|
379 |
return False |
|
380 |
||
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
381 |
def _check_hwe_support_status(self): |
382 |
di = distro_info.UbuntuDistroInfo() |
|
383 |
codename = get_dist() |
|
384 |
lts = di.is_lts(codename) |
|
385 |
if not lts: |
|
386 |
return None |
|
387 |
HWE = "/usr/bin/hwe-support-status" |
|
388 |
if not os.path.exists(HWE): |
|
389 |
return None |
|
390 |
cmd = [HWE, "--show-replacements"] |
|
391 |
self._parse_hwe_support_status(cmd) |
|
392 |
||
393 |
def _parse_hwe_support_status(self, cmd): |
|
394 |
try: |
|
395 |
subprocess.check_output(cmd) |
|
396 |
# for debugging
|
|
397 |
# print("nothing unsupported running")
|
|
398 |
except subprocess.CalledProcessError as e: |
|
399 |
if e.returncode == 10: |
|
400 |
packages = e.output.strip().split() |
|
401 |
self.hwe_replacement_packages = [] |
|
402 |
for pkgname in packages: |
|
403 |
pkgname = pkgname.decode('utf-8') |
|
2775
by Brian Murray
Fix a bunch of pep8 related errors. |
404 |
if pkgname in self.cache and \ |
405 |
not self.cache[pkgname].is_installed: |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
406 |
self.hwe_replacement_packages.append(pkgname) |
407 |
# for debugging
|
|
408 |
# print(self.hwe_replacement_packages)
|
|
409 |
||
2511.1.8
by Michael Terry
more pep8 fixes |
410 |
# fixme: we should probably abstract away all the stuff from libapt
|
411 |
def refresh_cache(self): |
|
412 |
try: |
|
413 |
if self.cache is None: |
|
414 |
self.cache = MyCache(None) |
|
415 |
else: |
|
416 |
self.cache.open(None) |
|
417 |
self.cache._initDepCache() |
|
418 |
except AssertionError: |
|
419 |
# if the cache could not be opened for some reason,
|
|
420 |
# let the release upgrader handle it, it deals
|
|
421 |
# a lot better with this
|
|
422 |
self._start_pane(PartialUpgradeDialog(self)) |
|
423 |
# we assert a clean cache
|
|
424 |
header = _("Software index is broken") |
|
425 |
desc = _("It is impossible to install or remove any software. " |
|
426 |
"Please use the package manager \"Synaptic\" or run " |
|
427 |
"\"sudo apt-get install -f\" in a terminal to fix " |
|
428 |
"this issue at first.") |
|
2887.1.1
by Brian Murray
UpdateManager/UpdateManager.py: when refreshing the cache and encountering |
429 |
self.start_error(False, header, desc) |
430 |
return
|
|
2511.1.8
by Michael Terry
more pep8 fixes |
431 |
except SystemError as e: |
432 |
header = _("Could not initialize the package information") |
|
433 |
desc = _("An unresolvable problem occurred while " |
|
434 |
"initializing the package information.\n\n" |
|
435 |
"Please report this bug against the 'update-manager' "
|
|
2537
by Michael Terry
fix a couple of pep8 errors |
436 |
"package and include the following error "
|
437 |
"message:\n") + str(e) |
|
2887.1.1
by Brian Murray
UpdateManager/UpdateManager.py: when refreshing the cache and encountering |
438 |
self.start_error(False, header, desc) |
439 |
return
|
|
2511.1.8
by Michael Terry
more pep8 fixes |
440 |
|
441 |
# Let the Gtk event loop breath if it hasn't had a chance.
|
|
2613.1.1
by Michael Terry
Allow Gtk loop to iterate when we're calculating all the dependencies for updates |
442 |
def iterate(): |
443 |
while Gtk.events_pending(): |
|
444 |
Gtk.main_iteration() |
|
445 |
iterate() |
|
2511.1.8
by Michael Terry
more pep8 fixes |
446 |
|
2893.2.1
by Iain Lane
List OEM metapackages |
447 |
self._check_oem_metapackages() |
448 |
||
2947.1.5
by Robert Ancell
Get package list from ua security-status |
449 |
self._get_ua_security_status() |
450 |
||
2893.2.1
by Iain Lane
List OEM metapackages |
451 |
for pkgname in self.oem_metapackages: |
452 |
try: |
|
453 |
if not self.cache[pkgname].is_installed: |
|
454 |
self.cache[pkgname].mark_install() |
|
455 |
except SystemError: |
|
456 |
pass
|
|
457 |
||
2511.1.8
by Michael Terry
more pep8 fixes |
458 |
self.update_list = UpdateList(self) |
459 |
try: |
|
2865
by Marcus Tomlinson
UpdateManager/backend/__init__.py: once apt upgrade completes, use the deb2snap.json file from ubuntu-release-upgrader to perform snap updates. |
460 |
self.update_list.update(self.cache, eventloop_callback=iterate, |
2953
by Steve Langasek
Fix autopkgtest regressions. |
461 |
duplicate_packages=self.duplicate_packages, |
462 |
ua_security_packages=self. |
|
463 |
ua_security_packages) |
|
2511.1.8
by Michael Terry
more pep8 fixes |
464 |
except SystemError as e: |
465 |
header = _("Could not calculate the upgrade") |
|
466 |
desc = _("An unresolvable problem occurred while " |
|
467 |
"calculating the upgrade.\n\n" |
|
468 |
"Please report this bug against the 'update-manager' "
|
|
2537
by Michael Terry
fix a couple of pep8 errors |
469 |
"package and include the following error "
|
470 |
"message:\n") + str(e) |
|
2587
by Michael Terry
Fix some calls to start_error to add an extra required argument; these calls must have been missed before |
471 |
self.start_error(True, header, desc) |
2511.1.8
by Michael Terry
more pep8 fixes |
472 |
|
473 |
if self.update_list.distUpgradeWouldDelete > 0: |
|
474 |
self._start_pane(PartialUpgradeDialog(self)) |
|
475 |
||
476 |
def _setup_dbus(self): |
|
2727.1.1
by Brian Murray
Include HWE support tools and information. (LP: #1498059) |
477 |
""" this sets up a dbus listener if none is installed already """
|
2511.1.8
by Michael Terry
more pep8 fixes |
478 |
# check if there is another g-a-i already and if not setup one
|
479 |
# listening on dbus
|
|
480 |
try: |
|
481 |
bus = dbus.SessionBus() |
|
2853
by Brian Murray
debian/tests/control: really use pyflakes3 instead of pyflakes, |
482 |
except Exception: |
2511.1.8
by Michael Terry
more pep8 fixes |
483 |
print("warning: could not initiate dbus") |
484 |
return
|
|
485 |
try: |
|
2511.1.14
by Michael Terry
auto-pep8'd some warnings |
486 |
proxy_obj = bus.get_object('org.freedesktop.UpdateManager', |
2511.1.8
by Michael Terry
more pep8 fixes |
487 |
'/org/freedesktop/UpdateManagerObject') |
488 |
iface = dbus.Interface(proxy_obj, |
|
489 |
'org.freedesktop.UpdateManagerIFace') |
|
490 |
iface.bringToFront() |
|
491 |
#print("send bringToFront")
|
|
492 |
sys.exit(0) |
|
493 |
except dbus.DBusException: |
|
494 |
#print("no listening object (%s) " % e)
|
|
495 |
bus_name = dbus.service.BusName('org.freedesktop.UpdateManager', |
|
496 |
bus) |
|
497 |
self.dbusController = UpdateManagerDbusController(self, bus_name) |
|
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
498 |
|
499 |
||
500 |
class UpdateManagerDbusController(dbus.service.Object): |
|
501 |
""" this is a helper to provide the UpdateManagerIFace """
|
|
502 |
def __init__(self, parent, bus_name, |
|
503 |
object_path='/org/freedesktop/UpdateManagerObject'): |
|
504 |
dbus.service.Object.__init__(self, bus_name, object_path) |
|
505 |
self.parent = parent |
|
2511.1.8
by Michael Terry
more pep8 fixes |
506 |
self.alert_watcher = AlertWatcher() |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
507 |
self.alert_watcher.connect("network-alert", self._on_network_alert) |
508 |
self.connected = False |
|
509 |
||
510 |
@dbus.service.method('org.freedesktop.UpdateManagerIFace') |
|
511 |
def bringToFront(self): |
|
512 |
self.parent.present() |
|
513 |
return True |
|
514 |
||
515 |
@dbus.service.method('org.freedesktop.UpdateManagerIFace') |
|
516 |
def upgrade(self): |
|
517 |
try: |
|
518 |
self.parent.start_install() |
|
519 |
return True |
|
2853
by Brian Murray
debian/tests/control: really use pyflakes3 instead of pyflakes, |
520 |
except Exception: |
2428.3.1
by Michael Terry
bring some of AptDialog from aptdaemon into our code to have more control over its presentation (i.e. stuff the widgets inside of our own main window; split UpdateManager into a central point of control and put old widgets into UpdatesAvailable class |
521 |
return False |
522 |
||
523 |
def _on_network_alert(self, watcher, state): |
|
524 |
if state in NetworkManagerHelper.NM_STATE_CONNECTED_LIST: |
|
525 |
self.connected = True |
|
526 |
else: |
|
527 |
self.connected = False |