Merge lp:~compiz-team/compiz-libcompizconfig/compiz-libcompizconfig.fix_874830 into lp:compiz-libcompizconfig

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz-libcompizconfig/compiz-libcompizconfig.fix_874830
Merge into: lp:compiz-libcompizconfig
Diff against target: 583 lines (+428/-13)
4 files modified
backend/src/ini.c (+12/-12)
src/CMakeLists.txt (+1/-0)
src/ccs-private.h (+7/-0)
src/main.c (+408/-1)
To merge this branch: bzr merge lp:~compiz-team/compiz-libcompizconfig/compiz-libcompizconfig.fix_874830
Reviewer Review Type Date Requested Status
Tim Penhey (community) Needs Fixing
Review via email: mp+79452@code.launchpad.net

Description of the change

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

This is a clear place where we could have tests. There are stand alone methods that have defined behaviour.

Also another reason why I had boolean parameters:

- ccsSetString (setting, value, TRUE);
+ ccsSetString (setting, value, FALSE);

This tells the reviewer exactly nothing.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Should I include some sample files in a tests/ directory to demonstrate how the settings upgrade / key renames / default overrides ? They won't be installable at runtime (since we don't want users to accidentally create a profile which will have its key values changed by some testing code), but at least they could be there for example's sake.

> Also another reason why I had boolean parameters:

> - ccsSetString (setting, value, TRUE);
> + ccsSetString (setting, value, FALSE);

> This tells the reviewer exactly nothing.

Yes, that need to be changed to:

enum
{
    WriteSetting,
    SetTemporary
};

Though in reality, CCSSetting needs to be an abstracted class or something since this code really just abuses the structure into storing some temporary data.

Unmerged revisions

425. By Sam Spilsbury

Provide a generic method for system administrators and distributions
to handle renamed keys so that user settings will be transitioned to
the new key names and settings will not be lost.

Provide a file in DATADIR/compizconfig/transitions called your_item.transition
with the following format

oldPluginName oldSettingName newPluginName newSettingName
oldPluginName2 oldSettingName2 newPluginName2 newSettingName2

Keys will then be renamed appropriately.

Note that this requires backend support. If your backend does not support
reading from keys that don't have an installed schema, then those settings
will be erased as soon as the user upgrades since the schema data will be
lost. That includes GSettings at the moment.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'backend/src/ini.c'
2--- backend/src/ini.c 2011-08-20 19:03:37 +0000
3+++ backend/src/ini.c 2011-10-15 07:05:26 +0000
4@@ -275,7 +275,7 @@
5 if (ccsIniGetString (data->iniFile, setting->parent->name,
6 keyName, &value))
7 {
8- ccsSetString (setting, value, TRUE);
9+ ccsSetString (setting, value, FALSE);
10 free (value);
11 status = TRUE;
12 }
13@@ -287,7 +287,7 @@
14 if (ccsIniGetString (data->iniFile, setting->parent->name,
15 keyName, &value))
16 {
17- ccsSetMatch (setting, value, TRUE);
18+ ccsSetMatch (setting, value, FALSE);
19 free (value);
20 status = TRUE;
21 }
22@@ -299,7 +299,7 @@
23 if (ccsIniGetInt (data->iniFile, setting->parent->name,
24 keyName, &value))
25 {
26- ccsSetInt (setting, value, TRUE);
27+ ccsSetInt (setting, value, FALSE);
28 status = TRUE;
29 }
30 }
31@@ -310,7 +310,7 @@
32 if (ccsIniGetBool (data->iniFile, setting->parent->name,
33 keyName, &value))
34 {
35- ccsSetBool (setting, (value != 0), TRUE);
36+ ccsSetBool (setting, (value != 0), FALSE);
37 status = TRUE;
38 }
39 }
40@@ -321,7 +321,7 @@
41 if (ccsIniGetFloat (data->iniFile, setting->parent->name,
42 keyName, &value))
43 {
44- ccsSetFloat (setting, value, TRUE);
45+ ccsSetFloat (setting, value, FALSE);
46 status = TRUE;
47 }
48 }
49@@ -333,7 +333,7 @@
50 if (ccsIniGetColor (data->iniFile, setting->parent->name,
51 keyName, &color))
52 {
53- ccsSetColor (setting, color, TRUE);
54+ ccsSetColor (setting, color, FALSE);
55 status = TRUE;
56 }
57 }
58@@ -344,7 +344,7 @@
59 if (ccsIniGetKey (data->iniFile, setting->parent->name,
60 keyName, &key))
61 {
62- ccsSetKey (setting, key, TRUE);
63+ ccsSetKey (setting, key, FALSE);
64 status = TRUE;
65 }
66 }
67@@ -355,7 +355,7 @@
68 if (ccsIniGetButton (data->iniFile, setting->parent->name,
69 keyName, &button))
70 {
71- ccsSetButton (setting, button, TRUE);
72+ ccsSetButton (setting, button, FALSE);
73 status = TRUE;
74 }
75 }
76@@ -366,7 +366,7 @@
77 if (ccsIniGetEdge (data->iniFile, setting->parent->name,
78 keyName, &edges))
79 {
80- ccsSetEdge (setting, edges, TRUE);
81+ ccsSetEdge (setting, edges, FALSE);
82 status = TRUE;
83 }
84 }
85@@ -377,7 +377,7 @@
86 if (ccsIniGetBell (data->iniFile, setting->parent->name,
87 keyName, &bell))
88 {
89- ccsSetBell (setting, bell, TRUE);
90+ ccsSetBell (setting, bell, FALSE);
91 status = TRUE;
92 }
93 }
94@@ -388,7 +388,7 @@
95 if (ccsIniGetList (data->iniFile, setting->parent->name,
96 keyName, &value, setting))
97 {
98- ccsSetList (setting, value, TRUE);
99+ ccsSetList (setting, value, FALSE);
100 ccsSettingValueListFree (value, TRUE);
101 status = TRUE;
102 }
103@@ -401,7 +401,7 @@
104 if (!status)
105 {
106 /* reset setting to default if it could not be read */
107- ccsResetToDefault (setting, TRUE);
108+ ccsResetToDefault (setting, FALSE);
109 }
110
111 if (keyName)
112
113=== modified file 'src/CMakeLists.txt'
114--- src/CMakeLists.txt 2010-05-21 02:55:08 +0000
115+++ src/CMakeLists.txt 2011-10-15 07:05:26 +0000
116@@ -24,6 +24,7 @@
117 -DIMAGEDIR=\\\"${COMPIZ_IMAGEDIR}\\\"
118 -DMETADATADIR=\\\"${COMPIZ_METADATADIR}\\\"
119 -DSYSCONFDIR=\\\"${COMPIZ_SYSCONFDIR}\\\"
120+ -DDATADIR=\\\"${COMPIZ_DATADIR}\\\"
121 -DLIBDIR=\\\"${COMPIZ_LIBDIR}\\\"
122 )
123
124
125=== modified file 'src/ccs-private.h'
126--- src/ccs-private.h 2011-08-20 19:03:37 +0000
127+++ src/ccs-private.h 2011-10-15 07:05:26 +0000
128@@ -72,7 +72,14 @@
129 CCSSettingList replaceToValueSettings;
130 } CCSSettingsUpgrade;
131
132+typedef struct _CCSSettingsTransition
133+{
134+ char *file;
135+ char *name;
136+} CCSSettingsTransition;
137+
138 Bool ccsCheckForSettingsUpgrade (CCSContext *context);
139+Bool ccsCheckForSettingsTransition (CCSContext *context);
140
141 void ccsLoadPlugins (CCSContext * context);
142 void ccsLoadPluginSettings (CCSPlugin * plugin);
143
144=== modified file 'src/main.c'
145--- src/main.c 2011-09-15 13:12:45 +0000
146+++ src/main.c 2011-10-15 07:05:26 +0000
147@@ -169,6 +169,9 @@
148
149 ccsLoadPlugins (context);
150
151+ /* Do settings transitions */
152+ ccsCheckForSettingsTransition (context);
153+
154 /* Do settings upgrades */
155 ccsCheckForSettingsUpgrade (context);
156
157@@ -3356,7 +3359,21 @@
158 free (uname);
159
160 return 1;
161-}
162+}
163+
164+static int
165+transitionNameFilter (const struct dirent *name)
166+{
167+ int length = strlen (name->d_name);
168+
169+ if (length < 12)
170+ return 0;
171+
172+ if (strncmp (name->d_name + length - 11, ".transition", 11))
173+ return 0;
174+
175+ return 1;
176+}
177
178 /*
179 * Process a filename into the properties
180@@ -3422,6 +3439,22 @@
181 return upgrade;
182 }
183
184+CCSSettingsTransition *
185+ccsSettingsTransitionNew (char *path, char *name)
186+{
187+ CCSSettingsTransition *transition = calloc (1, sizeof (CCSSettingsTransition));
188+ unsigned int namelen = strlen (path);
189+ unsigned int pathlen = strlen (name);
190+ unsigned int fnlen = (pathlen + namelen + 1);
191+
192+ transition->file = calloc (fnlen, sizeof (char));
193+ snprintf (transition->file, fnlen, "%s%s", path, name);
194+
195+ transition->name = strndup (name, pathlen - 10);
196+
197+ return transition;
198+}
199+
200 Bool
201 ccsCheckForSettingsUpgrade (CCSContext *context)
202 {
203@@ -3503,6 +3536,380 @@
204 }
205
206 Bool
207+ccsProcessTransition (CCSContext *context,
208+ CCSSettingsTransition *transition)
209+{
210+ FILE *fp = fopen (transition->file, "r");
211+ char *ctBuffer;
212+ unsigned int ctSize;
213+ size_t ctReadSize;
214+ unsigned int i, j;
215+ char *tok;
216+ char *buf;
217+
218+ if (!fp)
219+ {
220+ D (D_FULL, "[WARNING] failed to open transition file %s\n", transition->name);
221+ return FALSE;
222+ }
223+
224+ fseek (fp, 0, SEEK_END);
225+ ctSize = ftell (fp);
226+ rewind (fp);
227+ ctBuffer = calloc (ctSize + 1, sizeof (char));
228+
229+ if (!ctBuffer)
230+ {
231+ D (D_FULL, "[WARNING] couldn't allocate transition file %s buffer\n", transition->name);
232+ fclose (fp);
233+ return FALSE;
234+ }
235+
236+ ctReadSize = fread (ctBuffer, sizeof (char), ctSize, fp);
237+
238+ if (ctReadSize != ctSize)
239+ {
240+ D (D_FULL, "[WARNING] couldn't read completed buffer for transition %s\n", transition->name);
241+ free (ctBuffer);
242+ fclose (fp);
243+ return FALSE;
244+ }
245+ ctBuffer[ctSize] ='\0';
246+
247+ /* Remove newlines */
248+ i = 0;
249+
250+ while (i < ctSize)
251+ {
252+ if (strncmp (&(ctBuffer[i]), "\n", 1) == 0)
253+ {
254+ (&(ctBuffer[i]))[0] = ' ';
255+ }
256+
257+ i++;
258+ }
259+
260+ /* Now break up the transition file into 4-sized chunks, with
261+ * old-plugin old-setting new-plugin new-setting (newline)
262+ * but first check to make sure that the number of tokens
263+ * we have is a multiple of 4 */
264+
265+ buf = strdup (ctBuffer);
266+ i = 0;
267+
268+ tok = strsep (&buf, " ");
269+
270+ while (tok)
271+ {
272+ i++;
273+ tok = strsep (&buf, " ");
274+ }
275+
276+ free (buf);
277+
278+ if ((i - 1) % 4 != 0)
279+ {
280+ D (D_FULL, "[WARNING] provided upgrade file %s format not correct!\n", transition->name);
281+ free (ctBuffer);
282+ fclose (fp);
283+ return FALSE;
284+ }
285+
286+ buf = strdup (ctBuffer);
287+
288+ for (j = 0; j < (i / 4); j++)
289+ {
290+ char *oldPlugin;
291+ char *newPlugin;
292+ char *oldSetting;
293+ char *newSetting;
294+ CCSPlugin *cOldPlugin, *cNewPlugin;
295+ CCSSetting *cOldSetting, *cNewSetting;
296+ CCSPluginList p = NULL;
297+ CCSSettingList s = NULL;
298+ Bool freeOldPlugin = FALSE, freeOldSetting = FALSE;
299+
300+ CONTEXT_PRIV (context);
301+
302+ oldPlugin = strsep (&buf, " ");
303+ oldSetting = strsep (&buf, " ");
304+ newPlugin = strsep (&buf, " ");
305+ newSetting = strsep (&buf, " ");
306+
307+ if (!cPrivate->backend)
308+ return FALSE;
309+
310+ if (!cPrivate->backend->vTable->readSetting)
311+ return FALSE;
312+
313+ if (cPrivate->backend->vTable->readInit)
314+ if (!(*cPrivate->backend->vTable->readInit) (context))
315+ return FALSE;
316+
317+ /* Find the new plugin and new setting, if neither can
318+ * be found, error out */
319+
320+ p = context->plugins;
321+
322+ while (p)
323+ {
324+ if (strcmp (((CCSPlugin *) p->data)->name, newPlugin) == 0)
325+ break;
326+
327+ p = p->next;
328+ }
329+
330+ if (!p)
331+ {
332+ D (D_FULL, "[WARNING]: Could not find new plugin %s for transition %s\n", newPlugin, transition->name);
333+ continue;
334+ }
335+ else
336+ {
337+ cNewPlugin = (CCSPlugin *) p->data;
338+
339+ if (!((CCSPluginPrivate *) cNewPlugin->ccsPrivate)->loaded)
340+ ccsLoadPluginSettings (cNewPlugin);
341+
342+ s = ((CCSPluginPrivate *) cNewPlugin->ccsPrivate)->settings;
343+
344+ while (s)
345+ {
346+ if (strcmp (((CCSSetting *) s->data)->name, newSetting) == 0)
347+ break;
348+
349+ s = s->next;
350+ }
351+
352+ if (!s)
353+ {
354+ D (D_FULL, "[WARNING]: Could not find new setting %s for transition %s\n", newSetting, transition->name);
355+ continue;
356+ }
357+ else
358+ cNewSetting = (CCSSetting *) s->data;
359+ }
360+
361+ /* Try and find the old plugin, if not, craft one
362+ * for the purposes of this function */
363+
364+ p = context->plugins;
365+
366+ while (p)
367+ {
368+ if (strcmp (((CCSPlugin *) p->data)->name, oldPlugin) == 0)
369+ break;
370+
371+ p = p->next;
372+ }
373+
374+ if (!p)
375+ {
376+ cOldPlugin = calloc (1, sizeof (CCSPlugin));
377+
378+ cOldPlugin->context = context;
379+ cOldPlugin->ccsPrivate = calloc (1, sizeof (CCSPluginPrivate));
380+ if (!cOldPlugin->ccsPrivate )
381+ {
382+ free (cOldPlugin);
383+ return FALSE;
384+ }
385+ ((CCSPluginPrivate *) cOldPlugin->ccsPrivate)->loaded = FALSE;
386+
387+ cOldPlugin->name = strdup (oldPlugin);
388+ cOldPlugin->shortDesc = strdup (oldPlugin);
389+ cOldPlugin->longDesc = strdup (oldPlugin);
390+ cOldPlugin->category = strdup ("");
391+ cOldPlugin->refCount = 1;
392+
393+ freeOldPlugin = TRUE;
394+ }
395+ else
396+ cOldPlugin = (CCSPlugin *) p->data;
397+
398+ s = NULL;
399+
400+ if (!freeOldPlugin)
401+ {
402+ /* Now try and find the old setting to transition from */
403+
404+ s = ((CCSPluginPrivate *) cOldPlugin->ccsPrivate)->settings;
405+
406+ while (s)
407+ {
408+ if (strcmp (((CCSSetting *) s->data)->name, oldSetting) == 0)
409+ break;
410+
411+ s = s->next;
412+ }
413+ }
414+
415+ if (!s)
416+ {
417+ cOldSetting = calloc (1, sizeof (CCSSetting));
418+
419+ cOldSetting = (CCSSetting *) calloc (1, sizeof (CCSSetting));
420+ if (!cOldSetting)
421+ return FALSE;
422+
423+ cOldSetting->parent = cOldPlugin;
424+ cOldSetting->isDefault = TRUE;
425+ cOldSetting->name = strdup (oldSetting);
426+ cOldSetting->refCount = 1;
427+
428+ cOldSetting->shortDesc = strdup (oldSetting);
429+ cOldSetting->longDesc = strdup ("");
430+ cOldSetting->hints = strdup ("");
431+ cOldSetting->group = strdup ("");
432+ cOldSetting->subGroup = strdup ("");
433+
434+ cOldSetting->value = &cOldSetting->defaultValue;
435+ cOldSetting->defaultValue.parent = cOldSetting;
436+ cOldSetting->type = cNewSetting->type;
437+
438+ switch (cOldSetting->type)
439+ {
440+ case TypeString:
441+ cOldSetting->defaultValue.value.asString = strdup ("");
442+ break;
443+ case TypeMatch:
444+ cOldSetting->defaultValue.value.asMatch = strdup ("");
445+ break;
446+ default:
447+ break;
448+ }
449+
450+ freeOldSetting = TRUE;
451+ }
452+ else
453+ cOldSetting = (CCSSetting *) s->data;
454+
455+ /* Now ask the backend for the value of the old setting */
456+ (*cPrivate->backend->vTable->readSetting) (context, cOldSetting);
457+ ccsSetValue (cNewSetting, cOldSetting->value, TRUE);
458+ D (D_FULL, "Moved setting %s/%s to %s/%s", oldPlugin, oldSetting, newPlugin, newSetting);
459+
460+ if (freeOldSetting)
461+ {
462+ free (cOldSetting->name);
463+ free (cOldSetting->shortDesc);
464+ free (cOldSetting->longDesc);
465+ free (cOldSetting->hints);
466+ free (cOldSetting->subGroup);
467+
468+ switch (cOldSetting->type)
469+ {
470+ case TypeString:
471+ free (cOldSetting->defaultValue.value.asString);
472+ break;
473+ case TypeMatch:
474+ free (cOldSetting->defaultValue.value.asMatch);
475+ break;
476+ default:
477+ break;
478+ }
479+
480+ free (cOldSetting);
481+ }
482+
483+ if (freeOldPlugin)
484+ {
485+ free (cOldPlugin->ccsPrivate);
486+ free (cOldPlugin->name);
487+ free (cOldPlugin->shortDesc);
488+ free (cOldPlugin->longDesc);
489+ free (cOldPlugin->category);
490+ free (cOldPlugin);
491+ }
492+ }
493+
494+ D (D_FULL, "Completed transition %s\n", transition->name);
495+ free (ctBuffer);
496+ fclose (fp);
497+
498+ return TRUE;
499+}
500+
501+Bool
502+ccsCheckForSettingsTransition (CCSContext *context)
503+{
504+ struct dirent **nameList;
505+ int nFile, i;
506+ char *path = DATADIR "/compizconfig/transitions/";
507+ char *dupath = NULL;
508+ FILE *completedTransitions;
509+ char *ctBuffer;
510+ unsigned int ctSize;
511+ size_t ctReadSize;
512+ char *home = getenv ("HOME");
513+
514+ if (!home)
515+ return FALSE;
516+
517+ asprintf (&dupath, "%s/.config/compiz-1/compizconfig/done_transitions", home);
518+
519+ completedTransitions = fopen (dupath, "a+");
520+
521+ if (!path)
522+ return FALSE;
523+
524+ nFile = scandir (path, &nameList, transitionNameFilter, alphasort);
525+ if (nFile <= 0)
526+ return FALSE;
527+
528+ if (!completedTransitions)
529+ {
530+ fprintf (stderr, "[WARNING] Error opening done_transitions\n");
531+ return FALSE;
532+ }
533+
534+ fseek (completedTransitions, 0, SEEK_END);
535+ ctSize = ftell (completedTransitions);
536+ rewind (completedTransitions);
537+
538+ ctBuffer = calloc (ctSize + 1, sizeof (char));
539+ ctReadSize = fread (ctBuffer, 1, ctSize, completedTransitions);
540+
541+ if (ctReadSize != ctSize)
542+ D (D_FULL, "[WARNING] Couldn't read completed transitions file!\n");
543+
544+ ctBuffer[ctSize] = '\0';
545+
546+ for (i = 0; i < nFile; i++)
547+ {
548+ char *matched = strstr (ctBuffer, nameList[i]->d_name);
549+ CCSSettingsTransition *transition;
550+
551+ if (matched)
552+ {
553+ D (D_FULL, "Skipping transition %s\n", nameList[i]->d_name);
554+ continue;
555+ }
556+
557+ transition = ccsSettingsTransitionNew (path, nameList[i]->d_name);
558+
559+ D (D_FULL, "Processing transition %s\n", nameList[i]->d_name);
560+
561+ ccsProcessTransition (context, transition);
562+ ccsWriteChangedSettings (context);
563+ ccsWriteAutoSortedPluginList (context);
564+ D (D_FULL, "Completed transition %s\n", nameList[i]->d_name);
565+ fprintf (completedTransitions, "%s\n", nameList[i]->d_name);
566+ free (transition->file);
567+ free (transition->name);
568+ free (transition);
569+ free (nameList[i]);
570+ }
571+
572+ free (dupath);
573+ fclose (completedTransitions);
574+ free (ctBuffer);
575+ free (nameList);
576+
577+ return TRUE;
578+}
579+
580+Bool
581 ccsImportFromFile (CCSContext *context,
582 const char *fileName,
583 Bool overwriteNonDefault)

Subscribers

People subscribed via source and target branches

to all changes: