Merge lp://staging/~glatzor/update-manager/ubuntu-glatzor into lp://staging/update-manager

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
Reviewer Review Type Date Requested Status
Ubuntu Core Development Team Pending
Review via email: mp+16123@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
Sebastian Heinlein (glatzor) wrote :

Ported to latest aptdaemon API and simplified the InstallBackends

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)

Subscribers

People subscribed via source and target branches

to status/vote changes: