File: 0004-Implement-PackageKit-support.patch

package info (click to toggle)
software-properties 0.96.20.2-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 4,376 kB
  • sloc: python: 5,116; makefile: 19; sh: 18
file content (385 lines) | stat: -rw-r--r-- 16,203 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
From: Matthias Klumpp <mak@debian.org>
Date: Sun, 13 Mar 2016 15:24:56 +0100
Subject: Implement PackageKit support

This replaces the obsolete Aptdaemon bits and unifies the way cache
updates are handled using PackageKit.
---
 softwareproperties/gtk/DialogCacheOutdated.py   | 101 ++++++++++++++++--------
 softwareproperties/gtk/SoftwarePropertiesGtk.py |  97 ++++++++++++++---------
 softwareproperties/kde/SoftwarePropertiesKDE.py |  50 +++++++++++-
 3 files changed, 175 insertions(+), 73 deletions(-)

diff --git a/softwareproperties/gtk/DialogCacheOutdated.py b/softwareproperties/gtk/DialogCacheOutdated.py
index 31e1dd7..a1d7c05 100644
--- a/softwareproperties/gtk/DialogCacheOutdated.py
+++ b/softwareproperties/gtk/DialogCacheOutdated.py
@@ -21,17 +21,51 @@
 #  USA
 
 import os
-from gi.repository import GObject, Gtk
-
-import aptdaemon.client
-import aptdaemon.enums
-from aptdaemon.gtk3widgets import AptErrorDialog, AptProgressDialog
+import gi
+gi.require_version('PackageKitGlib', '1.0')
+gi.require_version('Gdk', '3.0')
+gi.require_version('Gtk', '3.0')
+from gi.repository import GObject, Gdk, Gtk
+from gi.repository import PackageKitGlib as packagekit
+from gettext import gettext as _
 
 from softwareproperties.gtk.utils import (
     setup_ui,
 )
 
 
+class ProgressDialog(Gtk.Window):
+    """A small helper window to display progress"""
+
+    def __init__(self, parent):
+        Gtk.Window.__init__(self, title=_("Cache Refresh"))
+        self.set_transient_for(parent)
+        self.set_position(Gtk.WindowPosition.CENTER)
+        self.set_border_width(16)
+        self.set_modal(True)
+        self.set_deletable(False)
+
+        self.set_default_size(300, 75)
+        geometry = Gdk.Geometry()
+        geometry.min_width = 210
+        geometry.min_height = 60
+        geometry.max_width = 800
+        geometry.max_height = 260
+        self.set_geometry_hints(None, geometry, Gdk.WindowHints.MIN_SIZE)
+        self.set_geometry_hints(None, geometry, Gdk.WindowHints.MAX_SIZE)
+
+        self.box = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL)
+        self.add(self.box)
+
+        self.label = Gtk.Label(xalign=0)
+        self.label.set_markup("<b><big>{}</big></b>".format(_("Refreshing software cache")))
+        self.box.pack_start(self.label, False, False, 0)
+
+        # create a progress bar
+        self.progressbar = Gtk.ProgressBar()
+        self.box.pack_start(self.progressbar, True, True, 0)
+
+
 class DialogCacheOutdated:
     def __init__(self, parent, datadir):
         """setup up the gtk dialog"""
@@ -41,44 +75,45 @@ class DialogCacheOutdated:
         self.dialog = self.dialog_cache_outofdate
         self.dialog.set_transient_for(parent)
 
-    def _run_transaction(self, transaction):
-        transaction.connect('finished', self._on_transaction_done)
-        dia = AptProgressDialog(transaction) #parent=self.parent.get_window())
-        dia.run(close_on_finished=True, show_error=True,
-                reply_handler=lambda: True,
-                error_handler=self._on_error)
-
-    def _on_transaction_done(self, transaction, exit_state):
-        self.loop.quit()
+    def on_pktask_progress(self, progress, ptype, udata=(None,)):
+        if ptype == packagekit.ProgressType.PERCENTAGE:
+            perc = progress.get_property('percentage')
+            self._pdia.progressbar.set_fraction(perc / 100.0)
 
-    def _on_error(self, error):
+    def on_pktask_finish(self, source, result, udata=(None,)):
+        results = None
         try:
-            raise error
-        except aptdaemon.errors.NotAuthorizedError:
-            # Silently ignore auth failures
-            return
-        except aptdaemon.errors.TransactionFailed as _error:
-            error = _error
-        except Exception as _error:
-            error = aptdaemon.errors.TransactionFailed(aptdaemon.enums.ERROR_UNKNOWN,
-                                                       str(_error))
-        dia = AptErrorDialog(error)
-        dia.run()
-        dia.hide()
+            results = self._pktask.generic_finish(result)
+        except Exception as e:
+            dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.ERROR,
+                Gtk.ButtonsType.CANCEL, _("Error while refreshing cache"))
+            dialog.format_secondary_text(str(e))
+            dialog.run()
+        self._loop.quit ()
 
     def run(self):
         """run the dialog, and if reload was pressed run cache update"""
         res = self.dialog.run()
         self.dialog.hide()
         if res == Gtk.ResponseType.APPLY:
-            self.loop = GObject.MainLoop()
-
-            ac = aptdaemon.client.AptClient()
-            ac.update_cache(reply_handler=self._run_transaction,
-                            error_handler=self._on_error)
+            self._pktask = packagekit.Task()
+            self._pdia = ProgressDialog(self.parent)
+            self._loop = GObject.MainLoop()
+            self._pdia.show_all()
 
             self.parent.set_sensitive(False)
-            self.loop.run()
+            try:
+                self._pktask.refresh_cache_async (False, # force
+                                                  None,  # GCancellable
+                                                  self.on_pktask_progress,
+                                                  (None,), # user data
+                                                  self.on_pktask_finish,
+                                                  (None,));
+            except Exception as e:
+                print("Error while requesting cache refresh: {}".format(e))
+
+            self._loop.run()
+            self._pdia.hide()
             self.parent.set_sensitive(True)
 
         return res
diff --git a/softwareproperties/gtk/SoftwarePropertiesGtk.py b/softwareproperties/gtk/SoftwarePropertiesGtk.py
index cf375c1..92037a9 100644
--- a/softwareproperties/gtk/SoftwarePropertiesGtk.py
+++ b/softwareproperties/gtk/SoftwarePropertiesGtk.py
@@ -27,16 +27,21 @@ from __future__ import absolute_import, print_function
 import apt
 import apt_pkg
 import dbus
+import dbus.glib
+import dbus.mainloop.glib
 from gettext import gettext as _
 import gettext
 import os
 import subprocess
-from aptdaemon import client
-from aptdaemon.errors import NotAuthorizedError, TransactionFailed
 import logging
 import threading
 import sys
 
+import gi
+gi.require_version('PackageKitGlib', '1.0')
+gi.require_version('Gdk', '3.0')
+gi.require_version('Gtk', '3.0')
+from gi.repository import PackageKitGlib as packagekit
 from gi.repository import GObject, Gdk, Gtk, Gio, GLib
 
 from .SimpleGtkbuilderApp import SimpleGtkbuilderApp
@@ -51,6 +56,8 @@ import softwareproperties.distro
 from softwareproperties.SoftwareProperties import SoftwareProperties
 import softwareproperties.SoftwareProperties
 
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
 try:
     from UbuntuDrivers import detect
 except ImportError as e:
@@ -165,7 +172,7 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
         self.handlers = {}
 
         self.apt_cache = {}
-        self.apt_client = client.AptClient()
+        self.pk_task = packagekit.Task()
 
         # Put some life into the user interface:
         self.init_auto_update()
@@ -1033,7 +1040,7 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
             if e._dbus_error_name == 'com.ubuntu.SoftwareProperties.PermissionDeniedByPolicy':
                 logging.error("Authentication canceled, changes have not been saved")
 
-    def on_driver_changes_progress(self, transaction, progress):
+    def on_driver_changes_progress(self, progress, ptype, data=None):
         #print(progress)
         self.button_driver_revert.set_visible(False)
         self.button_driver_apply.set_visible(False)
@@ -1043,30 +1050,30 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
         self.progress_bar.set_visible(True)
 
         self.label_driver_action.set_label(_("Applying changes..."))
-        self.progress_bar.set_fraction(progress / 100.0)
-
-    def on_driver_changes_finish(self, transaction, exit_state):
-        self.progress_bar.set_visible(False)
-        self.clear_changes()
-        self.apt_cache = apt.Cache()
-        self.set_driver_action_status()
-        self.update_label_and_icons_from_status()
-        self.button_driver_revert.set_visible(True)
-        self.button_driver_apply.set_visible(True)
-        self.button_driver_cancel.set_visible(False)
-        self.scrolled_window_drivers.set_sensitive(True)
-
-    def on_driver_changes_error(self, transaction, error_code, error_details):
-        self.on_driver_changes_revert()
-        self.set_driver_action_status()
-        self.update_label_and_icons_from_status()
-        self.button_driver_revert.set_visible(True)
-        self.button_driver_apply.set_visible(True)
-        self.button_driver_cancel.set_visible(False)
-        self.scrolled_window_drivers.set_sensitive(True)
+        if ptype == packagekit.ProgressType.PERCENTAGE:
+            prog_value = progress.get_property('percentage')
+            self.progress_bar.set_fraction(prog_value / 100.0)
 
-    def on_driver_changes_cancellable_changed(self, transaction, cancellable):
-        self.button_driver_cancel.set_sensitive(cancellable)
+    def on_driver_changes_finish(self, source, result, installs_pending):
+        results = None
+        try:
+            results = self.pk_task.generic_finish(result)
+        except Exception as e:
+            self.on_driver_changes_revert()
+            dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.ERROR,
+                Gtk.ButtonsType.CANCEL, _("Error while applying changes"))
+            dialog.format_secondary_text(str(e))
+            dialog.run()
+        if not installs_pending:
+            self.progress_bar.set_visible(False)
+            self.clear_changes()
+            self.apt_cache = apt.Cache()
+            self.set_driver_action_status()
+            self.update_label_and_icons_from_status()
+            self.button_driver_revert.set_visible(True)
+            self.button_driver_apply.set_visible(True)
+            self.button_driver_cancel.set_visible(False)
+            self.scrolled_window_drivers.set_sensitive(True)
 
     def on_driver_changes_apply(self, button):
 
@@ -1079,18 +1086,36 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
             else:
                 installs.append(pkg.shortname)
 
+        self.cancellable = Gio.Cancellable()
         try:
-            self.transaction = self.apt_client.commit_packages(install=installs, remove=removals,
-                                                               reinstall=[], purge=[], upgrade=[], downgrade=[])
-            self.transaction.connect("progress-changed", self.on_driver_changes_progress)
-            self.transaction.connect("cancellable-changed", self.on_driver_changes_cancellable_changed)
-            self.transaction.connect("finished", self.on_driver_changes_finish)
-            self.transaction.connect("error", self.on_driver_changes_error)
-            self.transaction.run()
+            if removals:
+                installs_pending = False
+                if installs:
+                    installs_pending = True
+                self.pk_task.reset()
+                self.pk_task.remove_packages_async(removals,
+                            False,  # allow deps
+                            True,  # autoremove
+                            self.cancellable,  # cancellable
+                            self.on_driver_changes_progress,
+                            None,  # progress data
+                            self.on_driver_changes_finish,  # callback ready
+                            installs_pending  # callback data
+                 )
+            if installs:
+                self.pk_task.reset()
+                task.install_packages_async(installs,
+                        self.cancellable,  # cancellable
+                        self.on_driver_changes_progress,
+                        None,  # progress data
+                        self.on_driver_changes_finish,  # GAsyncReadyCallback
+                        False  # ready data
+                 )
+
             self.button_driver_revert.set_sensitive(False)
             self.button_driver_apply.set_sensitive(False)
             self.scrolled_window_drivers.set_sensitive(False)
-        except (NotAuthorizedError, TransactionFailed) as e:
+        except Exception as e:
             print("Warning: install transaction not completed successfully: {}".format(e))
 
     def on_driver_changes_revert(self, button_revert=None):
@@ -1110,7 +1135,7 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
         self.button_driver_apply.set_sensitive(False)
 
     def on_driver_changes_cancel(self, button_cancel):
-        self.transaction.cancel()
+        self.cancellable.cancel()
         self.clear_changes()
 
     def on_driver_restart_clicked(self, button_restart):
diff --git a/softwareproperties/kde/SoftwarePropertiesKDE.py b/softwareproperties/kde/SoftwarePropertiesKDE.py
index d9ddee2..f31474c 100644
--- a/softwareproperties/kde/SoftwarePropertiesKDE.py
+++ b/softwareproperties/kde/SoftwarePropertiesKDE.py
@@ -30,7 +30,10 @@ import apt_pkg
 import tempfile
 from gettext import gettext as _
 import os
-import subprocess
+
+import gi
+gi.require_version('PackageKitGlib', '1.0')
+from gi.repository import PackageKitGlib as packagekit
 
 from PyQt5 import uic
 from PyQt5.QtCore import *
@@ -694,6 +697,20 @@ class SoftwarePropertiesKDE(SoftwareProperties):
     self.apt_key.update()
     self.show_keys()
 
+  def on_pktask_progress(self, progress, ptype, udata=(None,)):
+    if ptype == packagekit.ProgressType.PERCENTAGE:
+      perc = progress.get_property('percentage')
+      self._pdialog.setValue(perc)
+
+  def on_pktask_finish(self, source, result, udata=(None,)):
+    results = None
+    try:
+        results = self._pktask.generic_finish(result)
+    except Exception as e:
+      QMessageBox.warning(self.userinterface, _("Could not refresh cache"), str(e))
+    self._pdialog.hide()
+    kapp.quit()
+
   def on_close_button(self):
     """Show a dialog that a reload of the channel information is required
        only if there is no parent defined"""
@@ -708,9 +725,34 @@ class SoftwarePropertiesKDE(SoftwareProperties):
         messageBox.setText(text)
         messageBox.exec_()
         if (messageBox.clickedButton() == reloadButton):
-                cmd = ["/usr/bin/qapt-batch", "--update"]
-                subprocess.call(cmd)
-    kapp.quit()
+                self._pdialog = QProgressDialog("<big>{}</big>".format(_("Refreshing software cache")),
+                                                "Cancel", 0, 100, self.userinterface)
+                self._pdialog.setWindowTitle(_("Cache Refresh"))
+                self._pdialog.setCancelButton(None)
+                self._pdialog.setAutoClose(False)
+                self._pdialog.setMinimumWidth(210)
+                self._pdialog.setMinimumHeight(60)
+
+                self._pktask = packagekit.Task()
+                self._pdialog.show()
+                self.userinterface.hide()
+                try:
+                    self._pktask.refresh_cache_async (False, # force
+                                                  None,  # GCancellable
+                                                  self.on_pktask_progress,
+                                                  (None,), # user data
+                                                  self.on_pktask_finish,
+                                                  (None,));
+                except Exception as e:
+                    print("Error while requesting cache refresh: {}".format (e))
+        else:
+            # refresh not wanted, quit immediately
+            kapp.quit()
+    else:
+        # no changes, no cache refresh needed.
+        # we can quit.
+        kapp.quit()
+
 
   def on_button_add_cdrom_clicked(self):
     '''Show a dialog that allows to add a repository located on a CDROM