Merge lp://staging/~glatzor/update-manager/ubuntu-glatzor into lp://staging/update-manager
- ubuntu-glatzor
- Merge into main
Proposed by
Sebastian Heinlein
Status: | Merged |
---|---|
Merged at revision: | 1828 |
Proposed branch: | lp://staging/~glatzor/update-manager/ubuntu-glatzor |
Merge into: | lp://staging/update-manager |
Diff against target: |
366 lines (+128/-144) 4 files modified
UpdateManager/UpdateManager.py (+34/-13) UpdateManager/backend/InstallBackend.py (+12/-1) UpdateManager/backend/InstallBackendAptdaemon.py (+42/-76) UpdateManager/backend/InstallBackendSynaptic.py (+40/-54) |
To merge this branch: | bzr merge lp://staging/~glatzor/update-manager/ubuntu-glatzor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Core Development Team | Pending | ||
Review via email: mp+16123@code.staging.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Sebastian Heinlein (glatzor) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'UpdateManager/UpdateManager.py' |
2 | --- UpdateManager/UpdateManager.py 2009-11-23 11:09:20 +0000 |
3 | +++ UpdateManager/UpdateManager.py 2009-12-14 12:35:26 +0000 |
4 | @@ -121,6 +121,12 @@ |
5 | except: |
6 | logging.exception("setlocale failed") |
7 | |
8 | + # Used for inhibiting power management |
9 | + self.sleep_cookie = None |
10 | + self.sleep_dev = None |
11 | + |
12 | + self.reboot_required = False |
13 | + |
14 | self.image_logo.set_from_icon_name("update-manager", gtk.ICON_SIZE_DIALOG) |
15 | self.window_main.set_sensitive(False) |
16 | self.window_main.grab_focus() |
17 | @@ -213,7 +219,7 @@ |
18 | self.window_main.show() |
19 | # get the install backend |
20 | self.install_backend = backend.backend_factory(self.window_main) |
21 | - |
22 | + self.install_backend.connect("action-done", self._on_backend_done) |
23 | # it can only the iconified *after* it is shown (even if the docs |
24 | # claim otherwise) |
25 | if options.no_focus_on_map: |
26 | @@ -615,29 +621,44 @@ |
27 | os.environ["APT_LISTCHANGES_FRONTEND"]="none" |
28 | |
29 | # Do not suspend during the update process |
30 | - (dev, cookie) = inhibit_sleep() |
31 | + (self.sleep_dev, self.sleep_cookie) = inhibit_sleep() |
32 | |
33 | # set window to insensitive |
34 | self.window_main.set_sensitive(False) |
35 | self.window_main.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) |
36 | - |
37 | +# |
38 | # do it |
39 | if action == UPDATE: |
40 | self.install_backend.update() |
41 | elif action == INSTALL: |
42 | - has_reboot = os.path.exists(REBOOT_REQUIRED_FILE) |
43 | - # do it |
44 | - self.install_backend.commit(self.cache) |
45 | - # check if there is a new reboot required notification |
46 | - if not has_reboot and os.path.exists(REBOOT_REQUIRED_FILE): |
47 | - self.show_reboot_required_dialog() |
48 | - s = _("Reading package information") |
49 | - self.label_cache_progress_title.set_label("<b><big>%s</big></b>" % s) |
50 | + # If the progress dialog should be closed automatically afterwards |
51 | + gconfclient = gconf.client_get_default() |
52 | + close_on_done = gconfclient.get_bool("/apps/update-manager/" |
53 | + "autoclose_install_window") |
54 | + # Get the packages which should be installed and update |
55 | + pkgs_install = [] |
56 | + pkgs_upgrade = [] |
57 | + for pkg in self.cache: |
58 | + if pkg.markedInstall: |
59 | + pkgs_install.append(pkg.name) |
60 | + elif pkg.markedUpgrade: |
61 | + pkgs_upgrade.append(pkg.name) |
62 | + self.reboot_required = os.path.exists(REBOOT_REQUIRED_FILE) |
63 | + self.install_backend.commit(pkgs_install, pkgs_upgrade, close_on_done) |
64 | + |
65 | + def _on_backend_done(self, backend, action): |
66 | + # check if there is a new reboot required notification |
67 | + if action == INSTALL and not self.reboot_required and \ |
68 | + os.path.exists(REBOOT_REQUIRED_FILE): |
69 | + self.show_reboot_required_dialog() |
70 | + msg = _("Reading package information") |
71 | + self.label_cache_progress_title.set_label("<b><big>%s</big></b>" % msg) |
72 | self.fillstore() |
73 | |
74 | # Allow suspend after synaptic is finished |
75 | - if cookie != False: |
76 | - allow_sleep(dev, cookie) |
77 | + if self.sleep_cookie: |
78 | + allow_sleep(self.sleep_dev, self.sleep_cookie) |
79 | + self.sleep_cookie = self.sleep_dev = None |
80 | self.window_main.set_sensitive(True) |
81 | self.window_main.window.set_cursor(None) |
82 | |
83 | |
84 | === modified file 'UpdateManager/backend/InstallBackend.py' |
85 | --- UpdateManager/backend/InstallBackend.py 2009-07-24 14:17:02 +0000 |
86 | +++ UpdateManager/backend/InstallBackend.py 2009-12-14 12:35:26 +0000 |
87 | @@ -1,18 +1,29 @@ |
88 | # (c) 2005-2009 Canonical, GPL |
89 | # |
90 | |
91 | -class InstallBackend(object): |
92 | +import gobject |
93 | + |
94 | +class InstallBackend(gobject.GObject): |
95 | """The abstract backend that can install/remove packages""" |
96 | + |
97 | + __gsignals__ = {"action-done": (gobject.SIGNAL_RUN_FIRST, |
98 | + gobject.TYPE_NONE, (gobject.TYPE_INT,))} |
99 | + |
100 | + (INSTALL, UPDATE) = range(2) |
101 | + |
102 | def __init__(self, window_main): |
103 | """init backend |
104 | takes a gtk main window as parameter |
105 | """ |
106 | + gobject.GObject.__init__(self) |
107 | self.window_main = window_main |
108 | |
109 | def commit(self, cache): |
110 | """Commit the cache changes """ |
111 | + raise NotImplemented |
112 | |
113 | def update(self): |
114 | """Run a update to refresh the package list""" |
115 | + raise NotImplemented |
116 | |
117 | |
118 | |
119 | === modified file 'UpdateManager/backend/InstallBackendAptdaemon.py' |
120 | --- UpdateManager/backend/InstallBackendAptdaemon.py 2009-10-08 07:51:51 +0000 |
121 | +++ UpdateManager/backend/InstallBackendAptdaemon.py 2009-12-14 12:35:26 +0000 |
122 | @@ -1,87 +1,53 @@ |
123 | # (c) 2005-2009 Canonical, GPL |
124 | # |
125 | |
126 | -import apt_pkg |
127 | -import gobject |
128 | -import gtk |
129 | - |
130 | -import dbus |
131 | -from aptdaemon import client |
132 | -from aptdaemon.enums import * |
133 | -from aptdaemon.gtkwidgets import (AptErrorDialog, |
134 | - AptProgressDialog, |
135 | - AptMessageDialog) |
136 | +from aptdaemon import client, enums |
137 | +from aptdaemon.gtkwidgets import AptProgressDialog |
138 | |
139 | from InstallBackend import InstallBackend |
140 | |
141 | +POLKIT_ERROR_NOT_AUTHORIZED = "org.freedesktop.PolicyKit.Error.NotAuthorized" |
142 | |
143 | class InstallBackendAptdaemon(InstallBackend): |
144 | - """The abstract backend that can install/remove packages""" |
145 | - |
146 | - def _get_icon(self): |
147 | - theme = gtk.icon_theme_get_default () |
148 | - icon = theme.load_icon("update-manager", 16, 0) |
149 | - return icon |
150 | - |
151 | - def commit(self, cache): |
152 | + |
153 | + """Makes use of aptdaemon to refresh the cache and to install updates.""" |
154 | + |
155 | + def update(self): |
156 | + """Run a update to refresh the package list""" |
157 | + ac = client.AptClient() |
158 | + ac.update_cache(reply_handler=self._run_transaction, |
159 | + error_handler=self._on_error) |
160 | + |
161 | + def commit(self, pkgs_install, pkgs_upgrade, close_on_done): |
162 | """Commit a list of package adds and removes""" |
163 | - try: |
164 | - apt_pkg.PkgSystemUnLock() |
165 | - except SystemError: |
166 | - pass |
167 | - self.ac = client.AptClient() |
168 | - add = [] |
169 | - upgrade = [] |
170 | - for pkg in cache: |
171 | - if pkg.markedInstall: |
172 | - add.append(pkg.name) |
173 | - elif pkg.markedUpgrade: |
174 | - upgrade.append(pkg.name) |
175 | + ac = client.AptClient() |
176 | # parameter order: install, reinstall, remove, purge, upgrade |
177 | - t = self.ac.commit_packages(add, [], [], [], upgrade, |
178 | - exit_handler=self._on_exit) |
179 | - dia = AptProgressDialog(t, parent=self.window_main) |
180 | - dia.set_icon(self._get_icon()) |
181 | - try: |
182 | - dia.run() |
183 | - except dbus.exceptions.DBusException, e: |
184 | - if e._dbus_error_name == "org.freedesktop.PolicyKit.Error.NotAuthorized": |
185 | - pass |
186 | - else: |
187 | - raise |
188 | - dia.hide() |
189 | - self._show_messages(t) |
190 | - |
191 | - def update(self): |
192 | - """Run a update to refresh the package list""" |
193 | - try: |
194 | - apt_pkg.PkgSystemUnLock() |
195 | - except SystemError: |
196 | + _reply_handler = lambda trans: self._run_transaction(trans, |
197 | + close_on_done) |
198 | + ac.commit_packages(pkgs_install, [], [], [], pkgs_upgrade, |
199 | + reply_handler=_reply_handler, |
200 | + error_handler=self._on_error) |
201 | + |
202 | + def _run_transaction(self, trans, close=True): |
203 | + dia = AptProgressDialog(trans, parent=self.window_main) |
204 | + dia.set_icon_name("update-manager") |
205 | + dia.connect("finished", self._on_finished) |
206 | + dia.run(show_error=True, close_on_finished=close, |
207 | + reply_handler=lambda: True, |
208 | + error_handler=self._on_error) |
209 | + |
210 | + def _on_finished(self, dialog): |
211 | + dialog.destroy() |
212 | + if dialog._transaction.role == enums.ROLE_UPDATE_CACHE: |
213 | + action = self.UPDATE |
214 | + else: |
215 | + action = self.INSTALL |
216 | + self.emit("action-done", action) |
217 | + |
218 | + def _on_error(self, error): |
219 | + if error.get_dbus_name() == POLKIT_ERROR_NOT_AUTHORIZED: |
220 | + # Should already be handled by the polkit agent |
221 | pass |
222 | - self.ac = client.AptClient() |
223 | - t = self.ac.update_cache(exit_handler=self._on_exit) |
224 | - dia = AptProgressDialog(t, parent=self.window_main, terminal=False) |
225 | - dia.set_icon(self._get_icon()) |
226 | - try: |
227 | - dia.run() |
228 | - except dbus.exceptions.DBusException, e: |
229 | - if e._dbus_error_name == "org.freedesktop.PolicyKit.Error.NotAuthorized": |
230 | - pass |
231 | - else: |
232 | - raise |
233 | - dia.hide() |
234 | - self._show_messages(t) |
235 | - |
236 | - def _on_exit(self, trans, exit): |
237 | - if exit == EXIT_FAILED: |
238 | - d = AptErrorDialog(trans.get_error(), parent=self.window_main) |
239 | - d.run() |
240 | - d.hide() |
241 | - |
242 | - def _show_messages(self, trans): |
243 | - while gtk.events_pending(): |
244 | - gtk.main_iteration() |
245 | - for msg in trans._messages: |
246 | - d = AptMessageDialog(msg.enum, msg.details, parent=self.window_main) |
247 | - d.run() |
248 | - d.hide() |
249 | + else: |
250 | + #FIXME: Show an error dialog |
251 | + raise error |
252 | |
253 | === modified file 'UpdateManager/backend/InstallBackendSynaptic.py' |
254 | --- UpdateManager/backend/InstallBackendSynaptic.py 2009-07-24 14:17:02 +0000 |
255 | +++ UpdateManager/backend/InstallBackendSynaptic.py 2009-12-14 12:35:26 +0000 |
256 | @@ -12,15 +12,14 @@ |
257 | import gconf |
258 | from gettext import gettext as _ |
259 | |
260 | +import gobject |
261 | + |
262 | from InstallBackend import InstallBackend |
263 | |
264 | class InstallBackendSynaptic(InstallBackend): |
265 | """ Install backend based on synaptic """ |
266 | - |
267 | - # synaptic actions |
268 | - (INSTALL, UPDATE) = range(2) |
269 | |
270 | - def _run_synaptic(self, id, lock, cache=None, action=INSTALL): |
271 | + def _run_synaptic(self, action, opt, tempf): |
272 | try: |
273 | apt_pkg.PkgSystemUnLock() |
274 | except SystemError: |
275 | @@ -28,54 +27,41 @@ |
276 | cmd = ["/usr/bin/gksu", |
277 | "--desktop", "/usr/share/applications/update-manager.desktop", |
278 | "--", "/usr/sbin/synaptic", "--hide-main-window", |
279 | - "--non-interactive", "--parent-window-id", "%s" % (id) ] |
280 | - if action == self.INSTALL: |
281 | - # close when update was successful (its ok to use a Synaptic:: |
282 | - # option here, it will not get auto-saved, because synaptic does |
283 | - # not save options in non-interactive mode) |
284 | - gconfclient = gconf.client_get_default() |
285 | - if gconfclient.get_bool("/apps/update-manager/autoclose_install_window"): |
286 | - cmd.append("-o") |
287 | - cmd.append("Synaptic::closeZvt=true") |
288 | - # custom progress strings |
289 | - cmd.append("--progress-str") |
290 | - cmd.append("%s" % _("Please wait, this can take some time.")) |
291 | - cmd.append("--finish-str") |
292 | - cmd.append("%s" % _("Update is complete")) |
293 | - f = tempfile.NamedTemporaryFile() |
294 | - for pkg in cache: |
295 | - if pkg.markedInstall or pkg.markedUpgrade: |
296 | - f.write("%s\tinstall\n" % pkg.name) |
297 | - cmd.append("--set-selections-file") |
298 | - cmd.append("%s" % f.name) |
299 | - f.flush() |
300 | - self.return_code = subprocess.call(cmd) |
301 | - f.close() |
302 | - elif action == self.UPDATE: |
303 | - cmd.append("--update-at-startup") |
304 | - self.return_code = subprocess.call(cmd) |
305 | - else: |
306 | - print "run_synaptic() called with unknown action" |
307 | - return False |
308 | - lock.release() |
309 | - |
310 | - def _perform_action(self, action, cache=None): |
311 | - lock = thread.allocate_lock() |
312 | - lock.acquire() |
313 | - t = thread.start_new_thread(self._run_synaptic, |
314 | - (self.window_main.window.xid, |
315 | - lock, cache, action)) |
316 | - while lock.locked(): |
317 | - while gtk.events_pending(): |
318 | - gtk.main_iteration() |
319 | - time.sleep(0.05) |
320 | - return self.return_code |
321 | - |
322 | + "--non-interactive", "--parent-window-id", |
323 | + "%s" % self.window_main.window.xid ] |
324 | + cmd.extend(opt) |
325 | + flags = gobject.SPAWN_DO_NOT_REAP_CHILD |
326 | + (pid, stdin, stdout, stderr) = gobject.spawn_async(cmd, flags=flags) |
327 | + gobject.child_watch_add(pid, self._on_synaptic_exit, (action, tempf)) |
328 | + |
329 | + def _on_synaptic_exit(self, pid, condition, data): |
330 | + action, tempf = data |
331 | + if tempf: |
332 | + tempf.close() |
333 | + self.emit("action-done", action) |
334 | + |
335 | def update(self): |
336 | - return self._perform_action(self.UPDATE) |
337 | - |
338 | - def commit(self, cache): |
339 | - return self._perform_action(self.INSTALL, cache) |
340 | - |
341 | - |
342 | - |
343 | + opt = ["--update-at-startup"] |
344 | + tempf = None |
345 | + self._run_synaptic(self.UPDATE, opt, tempf) |
346 | + |
347 | + def commit(self, pkgs_install, pkgs_upgrade, close_on_done): |
348 | + # close when update was successful (its ok to use a Synaptic:: |
349 | + # option here, it will not get auto-saved, because synaptic does |
350 | + # not save options in non-interactive mode) |
351 | + opt = [] |
352 | + if close_on_done: |
353 | + opt.append("-o") |
354 | + opt.append("Synaptic::closeZvt=true") |
355 | + # custom progress strings |
356 | + opt.append("--progress-str") |
357 | + opt.append("%s" % _("Please wait, this can take some time.")) |
358 | + opt.append("--finish-str") |
359 | + opt.append("%s" % _("Update is complete")) |
360 | + tempf = tempfile.NamedTemporaryFile() |
361 | + for pkg_name in pkgs_install + pkgs_upgrade: |
362 | + tempf.write("%s\tinstall\n" % pkg_name) |
363 | + opt.append("--set-selections-file") |
364 | + opt.append("%s" % tempf.name) |
365 | + tempf.flush() |
366 | + self._run_synaptic(self.INSTALL, opt, tempf) |
Ported to latest aptdaemon API and simplified the InstallBackends