Merge lp:~psybers/docky/xdg-basedir into lp:docky
- xdg-basedir
- Merge into trunk
Proposed by
Robert Dyer
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 1451 | ||||
Proposed branch: | lp:~psybers/docky/xdg-basedir | ||||
Merge into: | lp:docky | ||||
Diff against target: |
395 lines (+151/-110) 3 files modified
Docky.Services/Docky.Services/PathsService.cs (+123/-40) Docky.Windowing/Windowing/WindowMatcher.cs (+21/-55) Docky/Docky/PluginManager.cs (+7/-15) |
||||
To merge this branch: | bzr merge lp:~psybers/docky/xdg-basedir | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Rico Tzschichholz | Needs Fixing | ||
Review via email: mp+26897@code.launchpad.net |
Commit message
Description of the change
Support the XDG Base Directory specification.
The paths service was reworked to support the spec and clean it up a bit. I attempted to make sure the rest of Docky uses that service now - specifically WindowManager.
To post a comment you must log in.
lp:~psybers/docky/xdg-basedir
updated
- 1422. By Robert Dyer
-
fix bug spotted in the diff
- 1423. By Robert Dyer
-
fix CX_APPS path
lp:~psybers/docky/xdg-basedir
updated
- 1424. By Robert Dyer
-
fix paths in PluginManager
- 1425. By Robert Dyer
-
clean code
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Docky.Services/Docky.Services/PathsService.cs' |
2 | --- Docky.Services/Docky.Services/PathsService.cs 2010-05-31 19:30:58 +0000 |
3 | +++ Docky.Services/Docky.Services/PathsService.cs 2010-06-08 09:03:26 +0000 |
4 | @@ -1,5 +1,5 @@ |
5 | // |
6 | -// Copyright (C) 2010 Chris Szikszoy |
7 | +// Copyright (C) 2010 Chris Szikszoy, Robert Dyer |
8 | // |
9 | // This program is free software: you can redistribute it and/or modify |
10 | // it under the terms of the GNU General Public License as published by |
11 | @@ -15,52 +15,135 @@ |
12 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
13 | // |
14 | using System; |
15 | +using System.Collections.Generic; |
16 | +using System.Linq; |
17 | |
18 | using GLib; |
19 | |
20 | namespace Docky.Services |
21 | { |
22 | + /// <summary> |
23 | + /// This class provides all paths used in Docky. |
24 | + /// |
25 | + /// It follows the XDG Base Directory specification. For more information see: |
26 | + /// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html |
27 | + /// </summary> |
28 | public class PathsService |
29 | { |
30 | - static readonly File home_folder = FileFactory.NewForPath (Environment.GetEnvironmentVariable ("HOME")); |
31 | - |
32 | - public File SystemDataFolder { |
33 | - get { return FileFactory.NewForPath (AssemblyInfo.DataDirectory).GetChild ("docky"); } |
34 | - } |
35 | - |
36 | - public File DockManagerUserDataFolder { |
37 | - get { return FileFactory.NewForPath (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData)).GetChild ("dockmanager"); } |
38 | - } |
39 | - |
40 | - public File UserDataFolder { |
41 | - get { return FileFactory.NewForPath (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData)).GetChild ("docky"); } |
42 | - } |
43 | - |
44 | - File user_cache_folder; |
45 | - public File UserCacheFolder { |
46 | - get { |
47 | - if (user_cache_folder != null) |
48 | - return user_cache_folder; |
49 | - |
50 | - string xdg_cache_home = Environment.GetEnvironmentVariable ("XDG_CACHE_HOME"); |
51 | - if (!string.IsNullOrEmpty (xdg_cache_home)) |
52 | - user_cache_folder = FileFactory.NewForPath (xdg_cache_home).GetChild ("docky"); |
53 | - else |
54 | - user_cache_folder = home_folder.GetChild (".cache").GetChild ("docky"); |
55 | - |
56 | - if (!user_cache_folder.Exists) |
57 | - try { |
58 | - user_cache_folder.MakeDirectoryWithParents (null); |
59 | - } catch { |
60 | - Log<PathsService>.Fatal ("Could not access the cache directory '" + user_cache_folder.Path + "' or create it. Docky will not work properly unless this folder is writable."); |
61 | - } |
62 | - |
63 | - return user_cache_folder; |
64 | - } |
65 | - } |
66 | - |
67 | - public File AutoStartFile { |
68 | - get { return FileFactory.NewForPath (Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData)).GetChild ("autostart").GetChild ("docky.desktop"); } |
69 | + #region XDG Base Directory independent paths |
70 | + |
71 | + /// <summary> |
72 | + /// User's home folder - $HOME |
73 | + /// </summary> |
74 | + public File HomeFolder { get; protected set; } |
75 | + |
76 | + /// <summary> |
77 | + /// Docky's installed data directory - defaults to /usr/share/docky for PPA |
78 | + /// </summary> |
79 | + public File SystemDataFolder { get; protected set; } |
80 | + |
81 | + #endregion |
82 | + |
83 | + |
84 | + #region XDG Base Directory paths |
85 | + |
86 | + /// <summary> |
87 | + /// $XDG_DATA_HOME - defaults to $HOME/.local/share |
88 | + /// </summary> |
89 | + public File XdgDataHomeFolder { get; protected set; } |
90 | + |
91 | + /// <summary> |
92 | + /// $XDG_CACHE_HOME - defaults to $HOME/.cache |
93 | + /// </summary> |
94 | + public File XdgCacheHomeFolder { get; protected set; } |
95 | + |
96 | + /// <summary> |
97 | + /// $XDG_DATA_DIRS - defaults to /usr/local/share/:/usr/share/ |
98 | + /// </summary> |
99 | + public IEnumerable<File> XdgDataDirFolders { get; protected set; } |
100 | + |
101 | + |
102 | + /// <summary> |
103 | + /// defaults to XdgCacheHomeFolder/docky |
104 | + /// </summary> |
105 | + public File UserCacheFolder { get; protected set; } |
106 | + |
107 | + /// <summary> |
108 | + /// defaults to XdgDataHomeFolder/docky |
109 | + /// </summary> |
110 | + public File UserDataFolder { get; protected set; } |
111 | + |
112 | + /// <summary> |
113 | + /// defaults to XdgDataHomeFolder/dockmanager |
114 | + /// </summary> |
115 | + public File DockManagerUserDataFolder { get; protected set; } |
116 | + |
117 | + |
118 | + /// <summary> |
119 | + /// Path to the autostart file - defaults to |
120 | + /// </summary> |
121 | + public File AutoStartFile { get; protected set; } |
122 | + |
123 | + #endregion |
124 | + |
125 | + |
126 | + public PathsService () |
127 | + { |
128 | + // get environment-based settings |
129 | + File env_home = FileFactory.NewForPath (Environment.GetFolderPath (Environment.SpecialFolder.Personal)); |
130 | + File env_data_install = FileFactory.NewForPath (AssemblyInfo.DataDirectory); |
131 | + |
132 | + |
133 | + // set the non-XDG Base Directory specified directories to use |
134 | + HomeFolder = env_home; |
135 | + SystemDataFolder = env_data_install.GetChild ("docky"); |
136 | + |
137 | + |
138 | + // get XDG Base Directory settings |
139 | + string xdg_data_home = Environment.GetEnvironmentVariable ("XDG_DATA_HOME"); |
140 | + string xdg_data_dirs = Environment.GetEnvironmentVariable ("XDG_DATA_DIRS"); |
141 | + string xdg_cache_home = Environment.GetEnvironmentVariable ("XDG_CACHE_HOME"); |
142 | + |
143 | + |
144 | + // determine directories based on XDG with fallbacks |
145 | + if (string.IsNullOrEmpty (xdg_cache_home)) |
146 | + XdgCacheHomeFolder = HomeFolder.GetChild (".cache"); |
147 | + else |
148 | + XdgCacheHomeFolder = FileFactory.NewForPath (xdg_cache_home); |
149 | + |
150 | + if (string.IsNullOrEmpty (xdg_data_home)) |
151 | + XdgDataHomeFolder = HomeFolder.GetChild (".local").GetChild ("share"); |
152 | + else |
153 | + XdgDataHomeFolder = FileFactory.NewForPath (xdg_data_home); |
154 | + |
155 | + if (string.IsNullOrEmpty (xdg_data_dirs)) |
156 | + XdgDataDirFolders = new [] { GLib.FileFactory.NewForPath ("/usr/local/share"), GLib.FileFactory.NewForPath ("/usr/share") }; |
157 | + else |
158 | + XdgDataDirFolders = xdg_data_dirs.Split (':').Select (d => GLib.FileFactory.NewForPath (d)); |
159 | + |
160 | + |
161 | + // set the XDG Base Directory specified directories to use |
162 | + UserCacheFolder = XdgCacheHomeFolder.GetChild ("docky"); |
163 | + UserDataFolder = XdgDataHomeFolder.GetChild ("docky"); |
164 | + DockManagerUserDataFolder = XdgDataHomeFolder.GetChild ("dockmanager"); |
165 | + AutoStartFile = XdgDataHomeFolder.GetChild ("autostart").GetChild ("docky.desktop"); |
166 | + |
167 | + |
168 | + // ensure all writable directories exist |
169 | + EnsureDirectoryExists (UserCacheFolder); |
170 | + EnsureDirectoryExists (UserDataFolder); |
171 | + EnsureDirectoryExists (DockManagerUserDataFolder); |
172 | + EnsureDirectoryExists (XdgDataHomeFolder.GetChild ("autostart")); |
173 | + } |
174 | + |
175 | + void EnsureDirectoryExists (File dir) |
176 | + { |
177 | + if (!dir.Exists) |
178 | + try { |
179 | + dir.MakeDirectoryWithParents (null); |
180 | + } catch { |
181 | + Log<PathsService>.Fatal ("Could not access the directory '" + dir.Path + "' or create it. Docky will not work properly unless this folder is writable."); |
182 | + } |
183 | } |
184 | } |
185 | } |
186 | |
187 | === modified file 'Docky.Windowing/Windowing/WindowMatcher.cs' |
188 | --- Docky.Windowing/Windowing/WindowMatcher.cs 2010-06-08 08:20:21 +0000 |
189 | +++ Docky.Windowing/Windowing/WindowMatcher.cs 2010-06-08 09:03:26 +0000 |
190 | @@ -140,7 +140,7 @@ |
191 | SetupWindow (w); |
192 | |
193 | // Set up monitors for cache files and desktop directories |
194 | - foreach (GLib.File dir in DesktopFileDirectories.Select (d => GLib.FileFactory.NewForPath (d))) |
195 | + foreach (GLib.File dir in DesktopFileDirectories) |
196 | MonitorDesktopFileDirs (dir); |
197 | MonitorDesktopFileSystemCacheFiles (); |
198 | |
199 | @@ -149,12 +149,12 @@ |
200 | } |
201 | |
202 | #region Handle DesktopItems |
203 | - static IEnumerable<string> DesktopFileSystemCacheFiles |
204 | + static IEnumerable<GLib.File> DesktopFileSystemCacheFiles |
205 | { |
206 | get { |
207 | return DesktopFileDirectories |
208 | - .Select (d => Path.Combine (d, string.Format ("desktop.{0}.cache", Locale))) |
209 | - .Where (f => File.Exists (f)); |
210 | + .Select (d => d.GetChild (string.Format ("desktop.{0}.cache", Locale))) |
211 | + .Where (f => f.Exists); |
212 | } |
213 | } |
214 | |
215 | @@ -167,49 +167,18 @@ |
216 | } |
217 | } |
218 | |
219 | - static IEnumerable<string> DesktopFileDirectories |
220 | + static IEnumerable<GLib.File> DesktopFileDirectories |
221 | { |
222 | get { |
223 | - return new [] { |
224 | - // These are XDG variables... |
225 | - "XDG_DATA_HOME", |
226 | - "XDG_DATA_DIRS", |
227 | - // Crossover apps |
228 | - "CX_APPS", |
229 | - }.SelectMany (v => ExpandPathVar (v)) |
230 | - .Where (d => Directory.Exists (d)); |
231 | + return DockServices.Paths.XdgDataDirFolders.Select (d => d.GetChild ("applications")) |
232 | + .Union(new [] { |
233 | + DockServices.Paths.XdgDataHomeFolder.GetChild ("applications"), |
234 | + DockServices.Paths.HomeFolder.GetChild (".cxoffice"), |
235 | + }) |
236 | + .Where (d => d.Exists); |
237 | } |
238 | } |
239 | |
240 | - static IEnumerable<string> ExpandPathVar (string xdgVar) |
241 | - { |
242 | - string envPath = Environment.GetEnvironmentVariable (xdgVar); |
243 | - |
244 | - if (string.IsNullOrEmpty (envPath)) { |
245 | - switch (xdgVar) { |
246 | - case "XDG_DATA_HOME": |
247 | - yield return Path.Combine ( |
248 | - Environment.GetFolderPath (Environment.SpecialFolder.Personal), |
249 | - new [] {".local", "share", "applications"}.Aggregate ((w, s) => Path.Combine (w, s)) |
250 | - ); |
251 | - break; |
252 | - case "XDG_DATA_DIRS": |
253 | - yield return new [] {"/usr", "local", "share", "applications"}.Aggregate ((w, s) => Path.Combine (w,s)); |
254 | - yield return new [] {"/usr", "share", "applications"}.Aggregate ((w, s) => Path.Combine (w, s)); |
255 | - break; |
256 | - case "CX_APPS": |
257 | - yield return Path.Combine ( |
258 | - Environment.GetFolderPath (Environment.SpecialFolder.Personal), |
259 | - ".cxoffice" |
260 | - ); |
261 | - break; |
262 | - } |
263 | - } else { |
264 | - foreach (string dir in envPath.Split (':')) |
265 | - yield return Path.Combine (dir, "applications"); |
266 | - } |
267 | - } |
268 | - |
269 | void UpdateDesktopItemsList () |
270 | { |
271 | if (desktop_items == null) |
272 | @@ -220,8 +189,8 @@ |
273 | |
274 | // Get desktop items for new "valid" desktop files |
275 | new_items = DesktopFileDirectories |
276 | - .SelectMany (dir => GLib.FileFactory.NewForPath (dir).SubDirs ()) |
277 | - .Union (DesktopFileDirectories.Select (f => GLib.FileFactory.NewForPath (f))) |
278 | + .SelectMany (dir => dir.SubDirs ()) |
279 | + .Union (DesktopFileDirectories) |
280 | .SelectMany (file => file.GetFiles (".desktop")) |
281 | .Where (file => !known_desktop_files.Exists (known_file => (known_file.Path == file.Path))) |
282 | .Select (file => new DesktopItem (file)) |
283 | @@ -244,19 +213,19 @@ |
284 | |
285 | void ProcessAndMergeAllSystemCacheFiles (List<DesktopItem> items) |
286 | { |
287 | - foreach (string cache_file in DesktopFileSystemCacheFiles) |
288 | + foreach (GLib.File cache_file in DesktopFileSystemCacheFiles) |
289 | ProcessAndMergeSystemCacheFile (cache_file, items); |
290 | } |
291 | |
292 | - void ProcessAndMergeSystemCacheFile (string cache_file, List<DesktopItem> items) |
293 | + void ProcessAndMergeSystemCacheFile (GLib.File cache_file, List<DesktopItem> items) |
294 | { |
295 | - if (!GLib.FileFactory.NewForPath (cache_file).Exists) |
296 | + if (!cache_file.Exists) |
297 | return; |
298 | |
299 | - Log<WindowMatcher>.Debug ("Processing {0}", cache_file); |
300 | + Log<WindowMatcher>.Debug ("Processing {0}", cache_file.Path); |
301 | |
302 | try { |
303 | - using (StreamReader reader = new StreamReader (cache_file)) { |
304 | + using (StreamReader reader = new StreamReader (cache_file.Path)) { |
305 | DesktopItem desktop_item = null; |
306 | string line; |
307 | |
308 | @@ -269,9 +238,7 @@ |
309 | if (match.Success) { |
310 | string section = match.Groups["Section"].Value; |
311 | if (section != null) { |
312 | - GLib.File file = GLib.FileFactory |
313 | - .NewForPath (Path.Combine (Path.GetDirectoryName (cache_file), |
314 | - string.Format ("{0}.desktop", section))); |
315 | + GLib.File file = cache_file.Parent.GetChild (string.Format ("{0}.desktop", section)); |
316 | desktop_item = items.First (item => item.File.Path == file.Path); |
317 | if (desktop_item == null && file.Exists) { |
318 | desktop_item = new DesktopItem (file); |
319 | @@ -413,14 +380,13 @@ |
320 | |
321 | void MonitorDesktopFileSystemCacheFiles () |
322 | { |
323 | - foreach (string filename in DesktopFileSystemCacheFiles) { |
324 | - GLib.File file = GLib.FileFactory.NewForPath (filename); |
325 | + foreach (GLib.File file in DesktopFileSystemCacheFiles) { |
326 | GLib.FileMonitor mon = file.Monitor (GLib.FileMonitorFlags.None, null); |
327 | mon.RateLimit = 2500; |
328 | mon.Changed += delegate { |
329 | DockServices.System.RunOnThread (() => { |
330 | lock (update_lock) { |
331 | - ProcessAndMergeSystemCacheFile (file.Path, desktop_items); |
332 | + ProcessAndMergeSystemCacheFile (file, desktop_items); |
333 | DesktopItemsChanged (); |
334 | } |
335 | }); |
336 | |
337 | === modified file 'Docky/Docky/PluginManager.cs' |
338 | --- Docky/Docky/PluginManager.cs 2010-04-11 00:41:58 +0000 |
339 | +++ Docky/Docky/PluginManager.cs 2010-06-08 09:03:26 +0000 |
340 | @@ -47,10 +47,6 @@ |
341 | { |
342 | public static readonly string DefaultPluginIcon = "package"; |
343 | |
344 | - const string PluginsDirectory = "plugins"; |
345 | - const string ApplicationDirectory = "docky"; |
346 | - const string DefaultAddinsDirectory = "addins"; |
347 | - |
348 | const string IPExtensionPath = "/Docky/ItemProvider"; |
349 | const string ConfigExtensionPath = "/Docky/Configuration"; |
350 | |
351 | @@ -59,15 +55,12 @@ |
352 | //// <value> |
353 | /// Directory where Docky saves its Mono.Addins repository cache. |
354 | /// </value> |
355 | - public static string UserPluginsDirectory { |
356 | - get { |
357 | - string userData = Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData); |
358 | - return Path.Combine (Path.Combine (userData, ApplicationDirectory), PluginsDirectory); |
359 | - } |
360 | + public static GLib.File UserPluginsDirectory { |
361 | + get { return DockServices.Paths.UserDataFolder.GetChild ("plugins"); } |
362 | } |
363 | |
364 | - public static string UserAddinInstallationDirectory { |
365 | - get { return Path.Combine (UserPluginsDirectory, DefaultAddinsDirectory); } |
366 | + public static GLib.File UserAddinInstallationDirectory { |
367 | + get { return UserPluginsDirectory.GetChild ("addins"); } |
368 | } |
369 | |
370 | /// <summary> |
371 | @@ -78,13 +71,13 @@ |
372 | { |
373 | // Initialize Mono.Addins. |
374 | try { |
375 | - AddinManager.Initialize (UserPluginsDirectory); |
376 | + AddinManager.Initialize (UserPluginsDirectory.Path); |
377 | } catch (InvalidOperationException e) { |
378 | Log<PluginManager>.Error ("AddinManager.Initialize: {0}", e.Message); |
379 | Log<PluginManager>.Warn ("Rebuild Addin.Registry and reinitialize AddinManager"); |
380 | AddinManager.Registry.Rebuild (null); |
381 | AddinManager.Shutdown (); |
382 | - AddinManager.Initialize (UserPluginsDirectory); |
383 | + AddinManager.Initialize (UserPluginsDirectory.Path); |
384 | } |
385 | |
386 | AddinManager.Registry.Update (null); |
387 | @@ -160,8 +153,7 @@ |
388 | { |
389 | IEnumerable<string> manual; |
390 | |
391 | - manual = Directory.GetFiles (UserAddinInstallationDirectory, "*.dll") |
392 | - .Select (s => Path.GetFileName (s)); |
393 | + manual = UserAddinInstallationDirectory.GetFiles ("*.dll").Select (f => f.Basename); |
394 | |
395 | manual.ToList ().ForEach (dll => Log<PluginManager>.Info ("Installing {0}", dll)); |
396 |
PluginManager.cs uses some Paths: UserAddinInstal lationDirectory , UserPluginsDire ctory which could be created in PathServices