Merge ~enr0n/software-properties:deb822 into software-properties:ubuntu/master

Proposed by Nick Rosbrook
Status: Merged
Merged at revision: 71ffbcd33e0a35e5e03d325c45c2254163597379
Proposed branch: ~enr0n/software-properties:deb822
Merge into: software-properties:ubuntu/master
Diff against target: 617 lines (+496/-11)
7 files modified
data/gtkbuilder/dialog-edit-deb822-source.ui (+298/-0)
debian/changelog (+12/-0)
debian/control (+2/-3)
softwareproperties/SoftwareProperties.py (+7/-4)
softwareproperties/dbus/SoftwarePropertiesDBus.py (+2/-1)
softwareproperties/gtk/DialogEditDeb822.py (+163/-0)
softwareproperties/gtk/SoftwarePropertiesGtk.py (+12/-3)
Reviewer Review Type Date Requested Status
Julian Andres Klode Needs Fixing
Review via email: mp+437803@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Julian Andres Klode (juliank) wrote :

Can you bump Depends: python3-apt to `(>= 2.5.3~)`? I'll still have to release that of course, but um, this will prevent software-properties from breaking if you edit deb822 sources (because python-apt 2.5.2 doesn't accept strings for Deb822SourceEntry).

review: Needs Fixing
Revision history for this message
Nick Rosbrook (enr0n) wrote :

Good catch, thanks. I pushed the change.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/data/gtkbuilder/dialog-edit-deb822-source.ui b/data/gtkbuilder/dialog-edit-deb822-source.ui
2new file mode 100644
3index 0000000..b819c9a
4--- /dev/null
5+++ b/data/gtkbuilder/dialog-edit-deb822-source.ui
6@@ -0,0 +1,298 @@
7+<?xml version="1.0" encoding="UTF-8"?>
8+<!-- Generated with glade 3.40.0 -->
9+<interface>
10+ <requires lib="gtk+" version="3.24"/>
11+ <object class="GtkDialog" id="dialog_edit_deb822">
12+ <property name="can-focus">False</property>
13+ <property name="border-width">6</property>
14+ <property name="title" translatable="yes">Edit Source</property>
15+ <property name="default-width">400</property>
16+ <property name="type-hint">dialog</property>
17+ <child internal-child="vbox">
18+ <object class="GtkBox">
19+ <property name="can-focus">False</property>
20+ <property name="orientation">vertical</property>
21+ <property name="spacing">12</property>
22+ <child internal-child="action_area">
23+ <object class="GtkButtonBox">
24+ <property name="can-focus">False</property>
25+ <property name="layout-style">end</property>
26+ <child>
27+ <object class="GtkButton" id="button_edit_cancel">
28+ <property name="label">gtk-cancel</property>
29+ <property name="visible">True</property>
30+ <property name="can-focus">True</property>
31+ <property name="can-default">True</property>
32+ <property name="receives-default">False</property>
33+ <property name="use-stock">True</property>
34+ </object>
35+ <packing>
36+ <property name="expand">True</property>
37+ <property name="fill">True</property>
38+ <property name="position">0</property>
39+ </packing>
40+ </child>
41+ <child>
42+ <object class="GtkButton" id="button_edit_ok">
43+ <property name="label">gtk-ok</property>
44+ <property name="visible">True</property>
45+ <property name="can-focus">True</property>
46+ <property name="has-focus">True</property>
47+ <property name="can-default">True</property>
48+ <property name="has-default">True</property>
49+ <property name="receives-default">False</property>
50+ <property name="use-stock">True</property>
51+ </object>
52+ <packing>
53+ <property name="expand">True</property>
54+ <property name="fill">True</property>
55+ <property name="position">1</property>
56+ </packing>
57+ </child>
58+ </object>
59+ <packing>
60+ <property name="expand">False</property>
61+ <property name="fill">False</property>
62+ <property name="position">0</property>
63+ </packing>
64+ </child>
65+ <child>
66+ <object class="GtkTable">
67+ <property name="visible">True</property>
68+ <property name="can-focus">False</property>
69+ <property name="n-rows">10</property>
70+ <property name="n-columns">2</property>
71+ <property name="column-spacing">12</property>
72+ <property name="row-spacing">6</property>
73+ <child>
74+ <placeholder/>
75+ </child>
76+ <child>
77+ <placeholder/>
78+ </child>
79+ <child>
80+ <placeholder/>
81+ </child>
82+ <child>
83+ <placeholder/>
84+ </child>
85+ <child>
86+ <placeholder/>
87+ </child>
88+ <child>
89+ <placeholder/>
90+ </child>
91+ <child>
92+ <placeholder/>
93+ </child>
94+ <child>
95+ <placeholder/>
96+ </child>
97+ <child>
98+ <object class="GtkLabel">
99+ <property name="visible">True</property>
100+ <property name="can-focus">False</property>
101+ <property name="label" translatable="yes">Types:</property>
102+ <property name="use-markup">True</property>
103+ <property name="xalign">1</property>
104+ </object>
105+ <packing>
106+ <property name="top-attach">1</property>
107+ <property name="bottom-attach">2</property>
108+ </packing>
109+ </child>
110+ <child>
111+ <object class="GtkLabel">
112+ <property name="visible">True</property>
113+ <property name="can-focus">False</property>
114+ <property name="label" translatable="yes">URIs:</property>
115+ <property name="xalign">1</property>
116+ </object>
117+ <packing>
118+ <property name="top-attach">3</property>
119+ <property name="bottom-attach">4</property>
120+ </packing>
121+ </child>
122+ <child>
123+ <placeholder/>
124+ </child>
125+ <child>
126+ <object class="GtkLabel">
127+ <property name="visible">True</property>
128+ <property name="can-focus">False</property>
129+ <property name="label" translatable="yes">Suites:</property>
130+ <property name="xalign">1</property>
131+ </object>
132+ <packing>
133+ <property name="top-attach">5</property>
134+ <property name="bottom-attach">6</property>
135+ </packing>
136+ </child>
137+ <child>
138+ <object class="GtkLabel">
139+ <property name="visible">True</property>
140+ <property name="can-focus">False</property>
141+ <property name="label" translatable="yes">Components:</property>
142+ <property name="xalign">1</property>
143+ </object>
144+ <packing>
145+ <property name="top-attach">7</property>
146+ <property name="bottom-attach">8</property>
147+ </packing>
148+ </child>
149+ <child>
150+ <object class="GtkLabel">
151+ <property name="visible">True</property>
152+ <property name="can-focus">False</property>
153+ <property name="label" translatable="yes">Comment:</property>
154+ <property name="xalign">1</property>
155+ </object>
156+ <packing>
157+ <property name="top-attach">9</property>
158+ <property name="bottom-attach">10</property>
159+ </packing>
160+ </child>
161+ <child>
162+ <object class="GtkEntry" id="entry_types">
163+ <property name="visible">True</property>
164+ <property name="can-focus">True</property>
165+ </object>
166+ <packing>
167+ <property name="left-attach">1</property>
168+ <property name="right-attach">2</property>
169+ <property name="top-attach">1</property>
170+ <property name="bottom-attach">2</property>
171+ </packing>
172+ </child>
173+ <child>
174+ <object class="GtkEntry" id="entry_uris">
175+ <property name="visible">True</property>
176+ <property name="can-focus">True</property>
177+ </object>
178+ <packing>
179+ <property name="left-attach">1</property>
180+ <property name="right-attach">2</property>
181+ <property name="top-attach">3</property>
182+ <property name="bottom-attach">4</property>
183+ </packing>
184+ </child>
185+ <child>
186+ <object class="GtkEntry" id="entry_suites">
187+ <property name="visible">True</property>
188+ <property name="can-focus">True</property>
189+ </object>
190+ <packing>
191+ <property name="left-attach">1</property>
192+ <property name="right-attach">2</property>
193+ <property name="top-attach">5</property>
194+ <property name="bottom-attach">6</property>
195+ </packing>
196+ </child>
197+ <child>
198+ <object class="GtkEntry" id="entry_comps">
199+ <property name="visible">True</property>
200+ <property name="can-focus">True</property>
201+ </object>
202+ <packing>
203+ <property name="left-attach">1</property>
204+ <property name="right-attach">2</property>
205+ <property name="top-attach">7</property>
206+ <property name="bottom-attach">8</property>
207+ </packing>
208+ </child>
209+ <child>
210+ <object class="GtkEntry" id="entry_comment">
211+ <property name="visible">True</property>
212+ <property name="can-focus">True</property>
213+ </object>
214+ <packing>
215+ <property name="left-attach">1</property>
216+ <property name="right-attach">2</property>
217+ <property name="top-attach">9</property>
218+ <property name="bottom-attach">10</property>
219+ </packing>
220+ </child>
221+ <child>
222+ <placeholder/>
223+ </child>
224+ <child>
225+ <placeholder/>
226+ </child>
227+ </object>
228+ <packing>
229+ <property name="expand">False</property>
230+ <property name="fill">True</property>
231+ <property name="position">0</property>
232+ </packing>
233+ </child>
234+ <child>
235+ <object class="GtkSeparator">
236+ <property name="visible">True</property>
237+ <property name="can-focus">False</property>
238+ </object>
239+ <packing>
240+ <property name="expand">False</property>
241+ <property name="fill">True</property>
242+ <property name="padding">12</property>
243+ <property name="position">1</property>
244+ </packing>
245+ </child>
246+ <child>
247+ <!-- n-columns=1 n-rows=2 -->
248+ <object class="GtkGrid">
249+ <property name="visible">True</property>
250+ <property name="can-focus">False</property>
251+ <property name="row-spacing">12</property>
252+ <child>
253+ <object class="GtkLabel">
254+ <property name="visible">True</property>
255+ <property name="can-focus">False</property>
256+ <property name="label" translatable="yes">Additional Fields:</property>
257+ </object>
258+ <packing>
259+ <property name="left-attach">0</property>
260+ <property name="top-attach">0</property>
261+ </packing>
262+ </child>
263+ <child>
264+ <object class="GtkButton" id="button_add_field">
265+ <property name="label">gtk-add</property>
266+ <property name="visible">True</property>
267+ <property name="can-focus">True</property>
268+ <property name="receives-default">True</property>
269+ <property name="use-stock">True</property>
270+ </object>
271+ <packing>
272+ <property name="left-attach">0</property>
273+ <property name="top-attach">1</property>
274+ </packing>
275+ </child>
276+ </object>
277+ <packing>
278+ <property name="expand">False</property>
279+ <property name="fill">False</property>
280+ <property name="position">2</property>
281+ </packing>
282+ </child>
283+ <child>
284+ <object class="GtkListBox" id="list_box_additional_fields">
285+ <property name="visible">True</property>
286+ <property name="can-focus">False</property>
287+ <property name="selection-mode">none</property>
288+ <property name="activate-on-single-click">False</property>
289+ </object>
290+ <packing>
291+ <property name="expand">False</property>
292+ <property name="fill">False</property>
293+ <property name="padding">12</property>
294+ <property name="position">4</property>
295+ </packing>
296+ </child>
297+ </object>
298+ </child>
299+ <action-widgets>
300+ <action-widget response="-6">button_edit_cancel</action-widget>
301+ <action-widget response="-5">button_edit_ok</action-widget>
302+ </action-widgets>
303+ </object>
304+</interface>
305diff --git a/debian/changelog b/debian/changelog
306index 74ca49e..9acc69d 100644
307--- a/debian/changelog
308+++ b/debian/changelog
309@@ -1,3 +1,15 @@
310+software-properties (0.99.33) lunar; urgency=medium
311+
312+ [ Sebastien Bacher ]
313+ * Replace the ubuntu pro images using the version provided by design
314+
315+ [ Nick Rosbrook ]
316+ * Add GTK edit dialog for deb822 sources
317+ * Add deb822 parameter to SoftwareProperties class
318+ * Bump python3-apt dependency to >= 2.5.3
319+
320+ -- Nick Rosbrook <nick.rosbrook@canonical.com> Thu, 23 Feb 2023 11:27:37 -0500
321+
322 software-properties (0.99.32) lunar; urgency=medium
323
324 [ Nathan Pratta Teodosio ]
325diff --git a/debian/control b/debian/control
326index 1453ad0..fcb6123 100644
327--- a/debian/control
328+++ b/debian/control
329@@ -14,7 +14,7 @@ Build-Depends: dbus-x11 <!nocheck>,
330 lsb-release <!nocheck>,
331 pyflakes3 <!nocheck>,
332 python3-all,
333- python3-apt <!nocheck>,
334+ python3-apt (>= 2.5.3~) <!nocheck>,
335 python3-dateutil <!nocheck>,
336 python3-dbus <!nocheck>,
337 python3-distro-info <!nocheck>,
338@@ -37,8 +37,7 @@ Depends: gpg,
339 iso-codes,
340 lsb-release,
341 python3,
342- python3-apt (>=
343- 0.6.20ubuntu16),
344+ python3-apt (>= 2.5.3~),
345 python3-gi,
346 python3-launchpadlib,
347 ${misc:Depends},
348diff --git a/softwareproperties/SoftwareProperties.py b/softwareproperties/SoftwareProperties.py
349index 835a1c6..d8f7435 100644
350--- a/softwareproperties/SoftwareProperties.py
351+++ b/softwareproperties/SoftwareProperties.py
352@@ -57,7 +57,7 @@ import aptsources.distro
353 import softwareproperties
354
355 from .AptAuth import AptAuth
356-from aptsources.sourceslist import (SourcesList, SourceEntry)
357+from aptsources.sourceslist import (SourcesList, SourceEntry, Deb822SourceEntry)
358 from softwareproperties.shortcuthandler import InvalidShortcutException
359 from softwareproperties.shortcuts import shortcut_handler
360
361@@ -83,7 +83,7 @@ class SoftwareProperties(object):
362 RELEASE_UPGRADES_NEVER : 'never',
363 }
364
365- def __init__(self, datadir=None, options=None, rootdir="/"):
366+ def __init__(self, datadir=None, options=None, rootdir="/", deb822=False):
367 """ Provides the core functionality to configure the used software
368 repositories, the corresponding authentication keys and
369 update automation """
370@@ -99,7 +99,7 @@ class SoftwareProperties(object):
371 self.options = options
372 self.datadir = datadir
373
374- self.sourceslist = SourcesList()
375+ self.sourceslist = SourcesList(deb822=deb822)
376 self.distro = aptsources.distro.get_distro()
377
378 self.seen_server = []
379@@ -458,7 +458,10 @@ class SoftwareProperties(object):
380 for (index, entry) in enumerate(self.sourceslist.list):
381 if str(entry) == old_entry:
382 file = self.sourceslist.list[index].file
383- self.sourceslist.list[index] = SourceEntry(new_entry, file)
384+ if isinstance(entry, Deb822SourceEntry):
385+ self.sourceslist.list[index] = Deb822SourceEntry(new_entry, file)
386+ else:
387+ self.sourceslist.list[index] = SourceEntry(new_entry, file)
388 self.set_modified_sourceslist()
389 return True
390 return False
391diff --git a/softwareproperties/dbus/SoftwarePropertiesDBus.py b/softwareproperties/dbus/SoftwarePropertiesDBus.py
392index fcdd2ab..26eb131 100644
393--- a/softwareproperties/dbus/SoftwarePropertiesDBus.py
394+++ b/softwareproperties/dbus/SoftwarePropertiesDBus.py
395@@ -50,7 +50,8 @@ class SoftwarePropertiesDBus(dbus.service.Object, SoftwareProperties):
396
397 def __init__(self, bus, options=None, datadir=None, rootdir="/"):
398 # init software properties
399- SoftwareProperties.__init__(self, options=options, datadir=datadir, rootdir=rootdir)
400+ SoftwareProperties.__init__(self, options=options, datadir=datadir,
401+ rootdir=rootdir, deb822=True)
402 # used in _check_policykit_priviledge
403 self.dbus_info = None
404 self.polkit = None
405diff --git a/softwareproperties/gtk/DialogEditDeb822.py b/softwareproperties/gtk/DialogEditDeb822.py
406new file mode 100644
407index 0000000..ae8b438
408--- /dev/null
409+++ b/softwareproperties/gtk/DialogEditDeb822.py
410@@ -0,0 +1,163 @@
411+# Copyright (c) 2023 Canonical
412+#
413+# This program is free software; you can redistribute it and/or
414+# modify it under the terms of the GNU General Public License as
415+# published by the Free Software Foundation; either version 2 of the
416+# License, or (at your option) any later version.
417+#
418+# This program is distributed in the hope that it will be useful,
419+# but WITHOUT ANY WARRANTY; without even the implied warranty of
420+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
421+# GNU General Public License for more details.
422+#
423+# You should have received a copy of the GNU General Public License
424+# along with this program; if not, write to the Free Software
425+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
426+# USA
427+
428+import os
429+import gi
430+gi.require_version("Gtk", "3.0")
431+from gi.repository import Gtk
432+
433+from aptsources.sourceslist import Deb822SourceEntry
434+from softwareproperties.gtk.utils import (
435+ setup_ui,
436+)
437+
438+
439+class _CustomSourceEntryField(Gtk.Grid):
440+ def __init__(self, window, input_changed_callback, key=None, value=None):
441+ super(Gtk.Grid, self).__init__()
442+
443+ self.window = window
444+ self.entry_key = Gtk.Entry(name='field_key', placeholder_text='Key')
445+ self.entry_val = Gtk.Entry(name='field_value', placeholder_text='Value')
446+ self.button_delete = Gtk.Button.new_from_stock('gtk-delete')
447+
448+ if key is not None:
449+ self.entry_key.set_text(key)
450+
451+ if value is not None:
452+ self.entry_val.set_text(value)
453+
454+ self.set_column_spacing(12)
455+ self.attach(self.entry_key, 0, 0, 1, 1)
456+ self.attach(self.entry_val, 1, 0, 1, 1)
457+ self.attach(self.button_delete, 2, 0, 1, 1)
458+
459+ self.connect('destroy', input_changed_callback)
460+ self.entry_key.connect('changed', input_changed_callback)
461+ self.entry_val.connect('changed', input_changed_callback)
462+ self.button_delete.connect('clicked',
463+ self._button_del_field_clicked_callback)
464+
465+ def _button_del_field_clicked_callback(self, *data):
466+ parent = self.get_parent()
467+ parent.get_parent().remove(parent)
468+
469+ # Shrink the height back to size after deleting items.
470+ width = self.window.get_default_size()[0]
471+ self.window.resize(width, 1)
472+
473+ def get_key(self):
474+ return self.entry_key.get_text()
475+
476+ def get_val(self):
477+ return self.entry_val.get_text()
478+
479+
480+class DialogEditDeb822:
481+ def __init__(self, parent, sourceslist, source_entry, datadir):
482+ self.sourceslist = sourceslist
483+ self.source_entry = source_entry
484+ self.new_source_entry = None
485+
486+ setup_ui(
487+ self,
488+ os.path.join(datadir, 'gtkbuilder', 'dialog-edit-deb822-source.ui'),
489+ domain='software-properties'
490+ )
491+ self.main = self.dialog_edit_deb822
492+ self.main.set_transient_for(parent)
493+
494+ self._populate_with_existing_source_entry()
495+ self._connect_signal_callbacks()
496+
497+ def _populate_with_existing_source_entry(self):
498+ self.entry_types.set_text(" ".join(self.source_entry.types))
499+ self.entry_uris.set_text(" ".join(self.source_entry.uris))
500+ self.entry_suites.set_text(" ".join(self.source_entry.suites))
501+ self.entry_comps.set_text(" ".join(self.source_entry.comps))
502+ self.entry_comment.set_text(self.source_entry.comment.rstrip())
503+
504+ for key, value in self.source_entry.section.tags.items():
505+ if key not in ['Types', 'URIs', 'Suites', 'Components']:
506+ self._append_custom_source_entry_field(key=key, value=value)
507+
508+ def _append_custom_source_entry_field(self, key=None, value=None):
509+ row = Gtk.ListBoxRow(selectable=False, activatable=False)
510+ field = _CustomSourceEntryField(
511+ self.main, self._input_changed_callback, key, value
512+ )
513+
514+ row.add(field)
515+
516+ self.list_box_additional_fields.insert(row, -1)
517+ self.list_box_additional_fields.show_all()
518+
519+ def _get_custom_source_entry_fields(self):
520+ rows = self.list_box_additional_fields.get_children()
521+ fields = [r.get_children()[0] for r in rows]
522+
523+ return [f for f in fields if any((f.get_key(), f.get_val()))]
524+
525+ def _is_current_input_valid(self):
526+ if '' in (self.entry_types.get_text(),
527+ self.entry_uris.get_text(),
528+ self.entry_suites.get_text(),
529+ self.entry_comps.get_text()):
530+ return False
531+
532+ for field in self._get_custom_source_entry_fields():
533+ if '' in (field.get_key(), field.get_val()):
534+ return False
535+
536+ return True
537+
538+ def _connect_signal_callbacks(self):
539+ for entry in (self.entry_types, self.entry_uris, self.entry_suites,
540+ self.entry_comps, self.entry_comment):
541+ entry.connect('changed', self._input_changed_callback)
542+
543+ self.button_add_field.connect('clicked',
544+ self._button_add_field_clicked_callback)
545+
546+ def _input_changed_callback(self, *data):
547+ self.button_edit_ok.set_sensitive(self._is_current_input_valid())
548+
549+ def _button_add_field_clicked_callback(self, *data):
550+ self._append_custom_source_entry_field()
551+
552+ def _source_entry_from_input(self):
553+ source_entry = Deb822SourceEntry(None, self.source_entry.file)
554+
555+ source_entry.types = self.entry_types.get_text().split()
556+ source_entry.uris = self.entry_uris.get_text().split()
557+ source_entry.suites = self.entry_suites.get_text().split()
558+ source_entry.comps = self.entry_comps.get_text().split()
559+ source_entry.comment = self.entry_comment.get_text()
560+
561+ for field in self._get_custom_source_entry_fields():
562+ source_entry.section[field.get_key()] = field.get_val()
563+
564+ return source_entry
565+
566+ def run(self):
567+ res = self.main.run()
568+ if res == Gtk.ResponseType.OK:
569+ self.new_source_entry = self._source_entry_from_input()
570+
571+ self.main.hide()
572+
573+ return res
574diff --git a/softwareproperties/gtk/SoftwarePropertiesGtk.py b/softwareproperties/gtk/SoftwarePropertiesGtk.py
575index 707b25c..0cced00 100644
576--- a/softwareproperties/gtk/SoftwarePropertiesGtk.py
577+++ b/softwareproperties/gtk/SoftwarePropertiesGtk.py
578@@ -46,10 +46,13 @@ gi.require_version("PackageKitGlib", "1.0")
579 from gi.repository import PackageKitGlib as packagekit
580 from gi.repository import GObject, Gdk, Gtk, Gio, GLib, Handy
581
582+from aptsources.sourceslist import Deb822SourceEntry
583+
584 from .SimpleGtkbuilderApp import SimpleGtkbuilderApp
585 from .DialogAdd import DialogAdd
586 from .DialogMirror import DialogMirror
587 from .DialogEdit import DialogEdit
588+from .DialogEditDeb822 import DialogEditDeb822
589 from .DialogCacheOutdated import DialogCacheOutdated
590 from .DialogAddSourcesList import DialogAddSourcesList
591 from .UbuntuProPage import UbuntuProPage
592@@ -157,7 +160,8 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
593 """ Provide a GTK based graphical user interface to configure
594 the used software repositories, corresponding authentication keys
595 and update automation """
596- SoftwareProperties.__init__(self, options=options, datadir=datadir)
597+ SoftwareProperties.__init__(self, options=options, datadir=datadir,
598+ deb822=True)
599 Gtk.Window.set_default_icon_name("software-properties")
600
601 # Support GNOME 42 dark mode
602@@ -1101,8 +1105,13 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
603 if not iter:
604 return
605 old_source_entry = model.get_value(iter, LIST_ENTRY_OBJ)
606- dialog = DialogEdit(self.window_main, self.sourceslist,
607- old_source_entry, self.datadir)
608+
609+ if isinstance(old_source_entry, Deb822SourceEntry):
610+ dialog = DialogEditDeb822(self.window_main, self.sourceslist,
611+ old_source_entry, self.datadir)
612+ else:
613+ dialog = DialogEdit(self.window_main, self.sourceslist,
614+ old_source_entry, self.datadir)
615 if dialog.run() == Gtk.ResponseType.OK:
616 try:
617 self.backend.ReplaceSourceEntry(str(old_source_entry),

Subscribers

People subscribed via source and target branches