Merge lp:~a-j-buxton/xfpanel-switch/orphan-plugins into lp:~xfpanel-switch-dev/xfpanel-switch/trunk

Proposed by Alistair Buxton
Status: Merged
Merged at revision: 146
Proposed branch: lp:~a-j-buxton/xfpanel-switch/orphan-plugins
Merge into: lp:~xfpanel-switch-dev/xfpanel-switch/trunk
Diff against target: 84 lines (+39/-7)
1 file modified
xfpanel-switch/panelconfig.py (+39/-7)
To merge this branch: bzr merge lp:~a-j-buxton/xfpanel-switch/orphan-plugins
Reviewer Review Type Date Requested Status
Xfce4 Panel Profiles Team Pending
Review via email: mp+343664@code.launchpad.net

Commit message

Fix (LP: #1765565): Don't crash on corrupted panel configs.

1. Fix the problem directly:

Catch the exception if the .desktop file is missing and return false.
This will remove launchers with missing .desktop (not just the binary).

2. Fix the problem more generally:

Ignore orphan plugin configurations. This is a plugin configuration
section which is not refered to by any panel and therefore is not used.
Some old versions of xfce4-panel seem to create these, but I can't
reproduce with the latest version.

These orphans are completely ignored by the panel. Xfpanel-switch also
ignores them, unless they are launchers with missing .desktop files.
The second part of this patch cleans them out anyway.

Description of the change

This is tricky to test as it requires you to have a previously unidentified corruption in your panel config. However, the reporter reported that it worked on IRC. I have not heavily tested it, but it appears to have saved my configuration okay too.

In order to test it you'll have to intentionally break the panel config: add a bunch of launchers, plugins etc, then delete them from panels/panel-N/plugin-ids using settings editor so that they become orphans. Then save the configuration and load it again. The orphans should be gone.

Next add a launcher and delete the .desktop from ~/.config/xfce4/panel/. Again save and load and thebroken launcher should be gone.

In neither case should it crash. :)

To post a comment you must log in.
143. By Alistair Buxton

Be careful about which plugins are deleted.

If the key /plugins/plugin-2 is deemed to be bad, we should not delete
/plugins/plugin-20 for example. So check that the keys to be deleted
either exactly match, or start with the pattern + '/'.

144. By Alistair Buxton

Check for orphans also when loading a config.

Because of the way the configuration copying is used, sometimes orphans
can persist in configs (because they don't go through xfconf.)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'xfpanel-switch/panelconfig.py'
2--- xfpanel-switch/panelconfig.py 2018-04-13 21:34:06 +0000
3+++ xfpanel-switch/panelconfig.py 2018-04-20 05:14:55 +0000
4@@ -61,6 +61,7 @@
5
6 pc.properties[pp] = pv
7
8+ pc.remove_orphans()
9 pc.find_desktops()
10
11 pc.source = None
12@@ -80,12 +81,40 @@
13 except:
14 pass
15
16+ pc.remove_orphans()
17 pc.find_desktops()
18
19 return pc
20
21+ def remove_orphans(self):
22+ plugin_ids = set()
23+ rem_keys = []
24+
25+ for pp, pv in self.properties.items():
26+ path = pp.split('/')
27+ if len(path) == 4 and path[0] == '' and path[1] == 'panels' and \
28+ path[2].startswith('panel-') and path[3] == 'plugin-ids':
29+ plugin_ids.update(pv)
30+
31+ for pp, pv in self.properties.items():
32+ path = pp.split('/')
33+ if len(path) == 3 and path[0] == '' and path[1] == 'plugins' and \
34+ path[2].startswith('plugin-'):
35+ number = path[2].split('-')[1]
36+ try:
37+ if int(number) not in plugin_ids:
38+ rem_keys.append('/plugins/plugin-' + number)
39+ except ValueError:
40+ pass
41+
42+ self.remove_keys(rem_keys)
43+
44 def check_desktop(self, path):
45- bytes = self.get_desktop_source_file(path).read()
46+ try:
47+ bytes = self.get_desktop_source_file(path).read()
48+ except FileNotFoundError:
49+ # If the .desktop file does not exist at all return False
50+ return False
51
52 # Check if binary exists
53 keyfile = GLib.KeyFile.new()
54@@ -99,7 +128,7 @@
55 return False
56
57 def find_desktops(self):
58- remove_keys = []
59+ rem_keys = []
60
61 for pp, pv in self.properties.items():
62 path = pp.split('/')
63@@ -114,13 +143,16 @@
64 if self.check_desktop(desktop_path):
65 self.desktops.append(desktop_path)
66 else:
67- remove_keys.append('/plugins/plugin-' + number)
68-
69+ rem_keys.append('/plugins/plugin-' + number)
70+
71+ self.remove_keys(rem_keys)
72+
73+ def remove_keys(self, rem_keys):
74 keys = list(self.properties.keys())
75 for param in keys:
76- for bad_plugin in remove_keys:
77- if param.startswith(bad_plugin):
78- self.properties.pop(param, None)
79+ for bad_plugin in rem_keys:
80+ if param == bad_plugin or param.startswith(bad_plugin+'/'):
81+ del self.properties[param]
82
83 def get_desktop_source_file(self, desktop):
84 if getattr(self, 'source', None) is None:

Subscribers

People subscribed via source and target branches