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
=== modified file 'backend/src/ini.c'
--- backend/src/ini.c 2011-08-20 19:03:37 +0000
+++ backend/src/ini.c 2011-10-15 07:05:26 +0000
@@ -275,7 +275,7 @@
275 if (ccsIniGetString (data->iniFile, setting->parent->name,275 if (ccsIniGetString (data->iniFile, setting->parent->name,
276 keyName, &value))276 keyName, &value))
277 {277 {
278 ccsSetString (setting, value, TRUE);278 ccsSetString (setting, value, FALSE);
279 free (value);279 free (value);
280 status = TRUE;280 status = TRUE;
281 }281 }
@@ -287,7 +287,7 @@
287 if (ccsIniGetString (data->iniFile, setting->parent->name,287 if (ccsIniGetString (data->iniFile, setting->parent->name,
288 keyName, &value))288 keyName, &value))
289 {289 {
290 ccsSetMatch (setting, value, TRUE);290 ccsSetMatch (setting, value, FALSE);
291 free (value);291 free (value);
292 status = TRUE;292 status = TRUE;
293 }293 }
@@ -299,7 +299,7 @@
299 if (ccsIniGetInt (data->iniFile, setting->parent->name,299 if (ccsIniGetInt (data->iniFile, setting->parent->name,
300 keyName, &value))300 keyName, &value))
301 {301 {
302 ccsSetInt (setting, value, TRUE);302 ccsSetInt (setting, value, FALSE);
303 status = TRUE;303 status = TRUE;
304 }304 }
305 }305 }
@@ -310,7 +310,7 @@
310 if (ccsIniGetBool (data->iniFile, setting->parent->name,310 if (ccsIniGetBool (data->iniFile, setting->parent->name,
311 keyName, &value))311 keyName, &value))
312 {312 {
313 ccsSetBool (setting, (value != 0), TRUE);313 ccsSetBool (setting, (value != 0), FALSE);
314 status = TRUE;314 status = TRUE;
315 }315 }
316 }316 }
@@ -321,7 +321,7 @@
321 if (ccsIniGetFloat (data->iniFile, setting->parent->name,321 if (ccsIniGetFloat (data->iniFile, setting->parent->name,
322 keyName, &value))322 keyName, &value))
323 {323 {
324 ccsSetFloat (setting, value, TRUE);324 ccsSetFloat (setting, value, FALSE);
325 status = TRUE;325 status = TRUE;
326 }326 }
327 }327 }
@@ -333,7 +333,7 @@
333 if (ccsIniGetColor (data->iniFile, setting->parent->name,333 if (ccsIniGetColor (data->iniFile, setting->parent->name,
334 keyName, &color))334 keyName, &color))
335 {335 {
336 ccsSetColor (setting, color, TRUE);336 ccsSetColor (setting, color, FALSE);
337 status = TRUE;337 status = TRUE;
338 }338 }
339 }339 }
@@ -344,7 +344,7 @@
344 if (ccsIniGetKey (data->iniFile, setting->parent->name,344 if (ccsIniGetKey (data->iniFile, setting->parent->name,
345 keyName, &key))345 keyName, &key))
346 {346 {
347 ccsSetKey (setting, key, TRUE);347 ccsSetKey (setting, key, FALSE);
348 status = TRUE;348 status = TRUE;
349 }349 }
350 }350 }
@@ -355,7 +355,7 @@
355 if (ccsIniGetButton (data->iniFile, setting->parent->name,355 if (ccsIniGetButton (data->iniFile, setting->parent->name,
356 keyName, &button))356 keyName, &button))
357 {357 {
358 ccsSetButton (setting, button, TRUE);358 ccsSetButton (setting, button, FALSE);
359 status = TRUE;359 status = TRUE;
360 }360 }
361 }361 }
@@ -366,7 +366,7 @@
366 if (ccsIniGetEdge (data->iniFile, setting->parent->name,366 if (ccsIniGetEdge (data->iniFile, setting->parent->name,
367 keyName, &edges))367 keyName, &edges))
368 {368 {
369 ccsSetEdge (setting, edges, TRUE);369 ccsSetEdge (setting, edges, FALSE);
370 status = TRUE;370 status = TRUE;
371 }371 }
372 }372 }
@@ -377,7 +377,7 @@
377 if (ccsIniGetBell (data->iniFile, setting->parent->name,377 if (ccsIniGetBell (data->iniFile, setting->parent->name,
378 keyName, &bell))378 keyName, &bell))
379 {379 {
380 ccsSetBell (setting, bell, TRUE);380 ccsSetBell (setting, bell, FALSE);
381 status = TRUE;381 status = TRUE;
382 }382 }
383 }383 }
@@ -388,7 +388,7 @@
388 if (ccsIniGetList (data->iniFile, setting->parent->name,388 if (ccsIniGetList (data->iniFile, setting->parent->name,
389 keyName, &value, setting))389 keyName, &value, setting))
390 {390 {
391 ccsSetList (setting, value, TRUE);391 ccsSetList (setting, value, FALSE);
392 ccsSettingValueListFree (value, TRUE);392 ccsSettingValueListFree (value, TRUE);
393 status = TRUE;393 status = TRUE;
394 }394 }
@@ -401,7 +401,7 @@
401 if (!status)401 if (!status)
402 {402 {
403 /* reset setting to default if it could not be read */403 /* reset setting to default if it could not be read */
404 ccsResetToDefault (setting, TRUE);404 ccsResetToDefault (setting, FALSE);
405 }405 }
406406
407 if (keyName)407 if (keyName)
408408
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2010-05-21 02:55:08 +0000
+++ src/CMakeLists.txt 2011-10-15 07:05:26 +0000
@@ -24,6 +24,7 @@
24 -DIMAGEDIR=\\\"${COMPIZ_IMAGEDIR}\\\"24 -DIMAGEDIR=\\\"${COMPIZ_IMAGEDIR}\\\"
25 -DMETADATADIR=\\\"${COMPIZ_METADATADIR}\\\"25 -DMETADATADIR=\\\"${COMPIZ_METADATADIR}\\\"
26 -DSYSCONFDIR=\\\"${COMPIZ_SYSCONFDIR}\\\"26 -DSYSCONFDIR=\\\"${COMPIZ_SYSCONFDIR}\\\"
27 -DDATADIR=\\\"${COMPIZ_DATADIR}\\\"
27 -DLIBDIR=\\\"${COMPIZ_LIBDIR}\\\"28 -DLIBDIR=\\\"${COMPIZ_LIBDIR}\\\"
28)29)
2930
3031
=== modified file 'src/ccs-private.h'
--- src/ccs-private.h 2011-08-20 19:03:37 +0000
+++ src/ccs-private.h 2011-10-15 07:05:26 +0000
@@ -72,7 +72,14 @@
72 CCSSettingList replaceToValueSettings;72 CCSSettingList replaceToValueSettings;
73} CCSSettingsUpgrade;73} CCSSettingsUpgrade;
7474
75typedef struct _CCSSettingsTransition
76{
77 char *file;
78 char *name;
79} CCSSettingsTransition;
80
75Bool ccsCheckForSettingsUpgrade (CCSContext *context);81Bool ccsCheckForSettingsUpgrade (CCSContext *context);
82Bool ccsCheckForSettingsTransition (CCSContext *context);
7683
77void ccsLoadPlugins (CCSContext * context);84void ccsLoadPlugins (CCSContext * context);
78void ccsLoadPluginSettings (CCSPlugin * plugin);85void ccsLoadPluginSettings (CCSPlugin * plugin);
7986
=== modified file 'src/main.c'
--- src/main.c 2011-09-15 13:12:45 +0000
+++ src/main.c 2011-10-15 07:05:26 +0000
@@ -169,6 +169,9 @@
169169
170 ccsLoadPlugins (context);170 ccsLoadPlugins (context);
171171
172 /* Do settings transitions */
173 ccsCheckForSettingsTransition (context);
174
172 /* Do settings upgrades */175 /* Do settings upgrades */
173 ccsCheckForSettingsUpgrade (context);176 ccsCheckForSettingsUpgrade (context);
174177
@@ -3356,7 +3359,21 @@
3356 free (uname);3359 free (uname);
33573360
3358 return 1;3361 return 1;
3359} 3362}
3363
3364static int
3365transitionNameFilter (const struct dirent *name)
3366{
3367 int length = strlen (name->d_name);
3368
3369 if (length < 12)
3370 return 0;
3371
3372 if (strncmp (name->d_name + length - 11, ".transition", 11))
3373 return 0;
3374
3375 return 1;
3376}
33603377
3361/*3378/*
3362 * Process a filename into the properties3379 * Process a filename into the properties
@@ -3422,6 +3439,22 @@
3422 return upgrade;3439 return upgrade;
3423}3440}
34243441
3442CCSSettingsTransition *
3443ccsSettingsTransitionNew (char *path, char *name)
3444{
3445 CCSSettingsTransition *transition = calloc (1, sizeof (CCSSettingsTransition));
3446 unsigned int namelen = strlen (path);
3447 unsigned int pathlen = strlen (name);
3448 unsigned int fnlen = (pathlen + namelen + 1);
3449
3450 transition->file = calloc (fnlen, sizeof (char));
3451 snprintf (transition->file, fnlen, "%s%s", path, name);
3452
3453 transition->name = strndup (name, pathlen - 10);
3454
3455 return transition;
3456}
3457
3425Bool3458Bool
3426ccsCheckForSettingsUpgrade (CCSContext *context)3459ccsCheckForSettingsUpgrade (CCSContext *context)
3427{3460{
@@ -3503,6 +3536,380 @@
3503}3536}
35043537
3505Bool3538Bool
3539ccsProcessTransition (CCSContext *context,
3540 CCSSettingsTransition *transition)
3541{
3542 FILE *fp = fopen (transition->file, "r");
3543 char *ctBuffer;
3544 unsigned int ctSize;
3545 size_t ctReadSize;
3546 unsigned int i, j;
3547 char *tok;
3548 char *buf;
3549
3550 if (!fp)
3551 {
3552 D (D_FULL, "[WARNING] failed to open transition file %s\n", transition->name);
3553 return FALSE;
3554 }
3555
3556 fseek (fp, 0, SEEK_END);
3557 ctSize = ftell (fp);
3558 rewind (fp);
3559 ctBuffer = calloc (ctSize + 1, sizeof (char));
3560
3561 if (!ctBuffer)
3562 {
3563 D (D_FULL, "[WARNING] couldn't allocate transition file %s buffer\n", transition->name);
3564 fclose (fp);
3565 return FALSE;
3566 }
3567
3568 ctReadSize = fread (ctBuffer, sizeof (char), ctSize, fp);
3569
3570 if (ctReadSize != ctSize)
3571 {
3572 D (D_FULL, "[WARNING] couldn't read completed buffer for transition %s\n", transition->name);
3573 free (ctBuffer);
3574 fclose (fp);
3575 return FALSE;
3576 }
3577 ctBuffer[ctSize] ='\0';
3578
3579 /* Remove newlines */
3580 i = 0;
3581
3582 while (i < ctSize)
3583 {
3584 if (strncmp (&(ctBuffer[i]), "\n", 1) == 0)
3585 {
3586 (&(ctBuffer[i]))[0] = ' ';
3587 }
3588
3589 i++;
3590 }
3591
3592 /* Now break up the transition file into 4-sized chunks, with
3593 * old-plugin old-setting new-plugin new-setting (newline)
3594 * but first check to make sure that the number of tokens
3595 * we have is a multiple of 4 */
3596
3597 buf = strdup (ctBuffer);
3598 i = 0;
3599
3600 tok = strsep (&buf, " ");
3601
3602 while (tok)
3603 {
3604 i++;
3605 tok = strsep (&buf, " ");
3606 }
3607
3608 free (buf);
3609
3610 if ((i - 1) % 4 != 0)
3611 {
3612 D (D_FULL, "[WARNING] provided upgrade file %s format not correct!\n", transition->name);
3613 free (ctBuffer);
3614 fclose (fp);
3615 return FALSE;
3616 }
3617
3618 buf = strdup (ctBuffer);
3619
3620 for (j = 0; j < (i / 4); j++)
3621 {
3622 char *oldPlugin;
3623 char *newPlugin;
3624 char *oldSetting;
3625 char *newSetting;
3626 CCSPlugin *cOldPlugin, *cNewPlugin;
3627 CCSSetting *cOldSetting, *cNewSetting;
3628 CCSPluginList p = NULL;
3629 CCSSettingList s = NULL;
3630 Bool freeOldPlugin = FALSE, freeOldSetting = FALSE;
3631
3632 CONTEXT_PRIV (context);
3633
3634 oldPlugin = strsep (&buf, " ");
3635 oldSetting = strsep (&buf, " ");
3636 newPlugin = strsep (&buf, " ");
3637 newSetting = strsep (&buf, " ");
3638
3639 if (!cPrivate->backend)
3640 return FALSE;
3641
3642 if (!cPrivate->backend->vTable->readSetting)
3643 return FALSE;
3644
3645 if (cPrivate->backend->vTable->readInit)
3646 if (!(*cPrivate->backend->vTable->readInit) (context))
3647 return FALSE;
3648
3649 /* Find the new plugin and new setting, if neither can
3650 * be found, error out */
3651
3652 p = context->plugins;
3653
3654 while (p)
3655 {
3656 if (strcmp (((CCSPlugin *) p->data)->name, newPlugin) == 0)
3657 break;
3658
3659 p = p->next;
3660 }
3661
3662 if (!p)
3663 {
3664 D (D_FULL, "[WARNING]: Could not find new plugin %s for transition %s\n", newPlugin, transition->name);
3665 continue;
3666 }
3667 else
3668 {
3669 cNewPlugin = (CCSPlugin *) p->data;
3670
3671 if (!((CCSPluginPrivate *) cNewPlugin->ccsPrivate)->loaded)
3672 ccsLoadPluginSettings (cNewPlugin);
3673
3674 s = ((CCSPluginPrivate *) cNewPlugin->ccsPrivate)->settings;
3675
3676 while (s)
3677 {
3678 if (strcmp (((CCSSetting *) s->data)->name, newSetting) == 0)
3679 break;
3680
3681 s = s->next;
3682 }
3683
3684 if (!s)
3685 {
3686 D (D_FULL, "[WARNING]: Could not find new setting %s for transition %s\n", newSetting, transition->name);
3687 continue;
3688 }
3689 else
3690 cNewSetting = (CCSSetting *) s->data;
3691 }
3692
3693 /* Try and find the old plugin, if not, craft one
3694 * for the purposes of this function */
3695
3696 p = context->plugins;
3697
3698 while (p)
3699 {
3700 if (strcmp (((CCSPlugin *) p->data)->name, oldPlugin) == 0)
3701 break;
3702
3703 p = p->next;
3704 }
3705
3706 if (!p)
3707 {
3708 cOldPlugin = calloc (1, sizeof (CCSPlugin));
3709
3710 cOldPlugin->context = context;
3711 cOldPlugin->ccsPrivate = calloc (1, sizeof (CCSPluginPrivate));
3712 if (!cOldPlugin->ccsPrivate )
3713 {
3714 free (cOldPlugin);
3715 return FALSE;
3716 }
3717 ((CCSPluginPrivate *) cOldPlugin->ccsPrivate)->loaded = FALSE;
3718
3719 cOldPlugin->name = strdup (oldPlugin);
3720 cOldPlugin->shortDesc = strdup (oldPlugin);
3721 cOldPlugin->longDesc = strdup (oldPlugin);
3722 cOldPlugin->category = strdup ("");
3723 cOldPlugin->refCount = 1;
3724
3725 freeOldPlugin = TRUE;
3726 }
3727 else
3728 cOldPlugin = (CCSPlugin *) p->data;
3729
3730 s = NULL;
3731
3732 if (!freeOldPlugin)
3733 {
3734 /* Now try and find the old setting to transition from */
3735
3736 s = ((CCSPluginPrivate *) cOldPlugin->ccsPrivate)->settings;
3737
3738 while (s)
3739 {
3740 if (strcmp (((CCSSetting *) s->data)->name, oldSetting) == 0)
3741 break;
3742
3743 s = s->next;
3744 }
3745 }
3746
3747 if (!s)
3748 {
3749 cOldSetting = calloc (1, sizeof (CCSSetting));
3750
3751 cOldSetting = (CCSSetting *) calloc (1, sizeof (CCSSetting));
3752 if (!cOldSetting)
3753 return FALSE;
3754
3755 cOldSetting->parent = cOldPlugin;
3756 cOldSetting->isDefault = TRUE;
3757 cOldSetting->name = strdup (oldSetting);
3758 cOldSetting->refCount = 1;
3759
3760 cOldSetting->shortDesc = strdup (oldSetting);
3761 cOldSetting->longDesc = strdup ("");
3762 cOldSetting->hints = strdup ("");
3763 cOldSetting->group = strdup ("");
3764 cOldSetting->subGroup = strdup ("");
3765
3766 cOldSetting->value = &cOldSetting->defaultValue;
3767 cOldSetting->defaultValue.parent = cOldSetting;
3768 cOldSetting->type = cNewSetting->type;
3769
3770 switch (cOldSetting->type)
3771 {
3772 case TypeString:
3773 cOldSetting->defaultValue.value.asString = strdup ("");
3774 break;
3775 case TypeMatch:
3776 cOldSetting->defaultValue.value.asMatch = strdup ("");
3777 break;
3778 default:
3779 break;
3780 }
3781
3782 freeOldSetting = TRUE;
3783 }
3784 else
3785 cOldSetting = (CCSSetting *) s->data;
3786
3787 /* Now ask the backend for the value of the old setting */
3788 (*cPrivate->backend->vTable->readSetting) (context, cOldSetting);
3789 ccsSetValue (cNewSetting, cOldSetting->value, TRUE);
3790 D (D_FULL, "Moved setting %s/%s to %s/%s", oldPlugin, oldSetting, newPlugin, newSetting);
3791
3792 if (freeOldSetting)
3793 {
3794 free (cOldSetting->name);
3795 free (cOldSetting->shortDesc);
3796 free (cOldSetting->longDesc);
3797 free (cOldSetting->hints);
3798 free (cOldSetting->subGroup);
3799
3800 switch (cOldSetting->type)
3801 {
3802 case TypeString:
3803 free (cOldSetting->defaultValue.value.asString);
3804 break;
3805 case TypeMatch:
3806 free (cOldSetting->defaultValue.value.asMatch);
3807 break;
3808 default:
3809 break;
3810 }
3811
3812 free (cOldSetting);
3813 }
3814
3815 if (freeOldPlugin)
3816 {
3817 free (cOldPlugin->ccsPrivate);
3818 free (cOldPlugin->name);
3819 free (cOldPlugin->shortDesc);
3820 free (cOldPlugin->longDesc);
3821 free (cOldPlugin->category);
3822 free (cOldPlugin);
3823 }
3824 }
3825
3826 D (D_FULL, "Completed transition %s\n", transition->name);
3827 free (ctBuffer);
3828 fclose (fp);
3829
3830 return TRUE;
3831}
3832
3833Bool
3834ccsCheckForSettingsTransition (CCSContext *context)
3835{
3836 struct dirent **nameList;
3837 int nFile, i;
3838 char *path = DATADIR "/compizconfig/transitions/";
3839 char *dupath = NULL;
3840 FILE *completedTransitions;
3841 char *ctBuffer;
3842 unsigned int ctSize;
3843 size_t ctReadSize;
3844 char *home = getenv ("HOME");
3845
3846 if (!home)
3847 return FALSE;
3848
3849 asprintf (&dupath, "%s/.config/compiz-1/compizconfig/done_transitions", home);
3850
3851 completedTransitions = fopen (dupath, "a+");
3852
3853 if (!path)
3854 return FALSE;
3855
3856 nFile = scandir (path, &nameList, transitionNameFilter, alphasort);
3857 if (nFile <= 0)
3858 return FALSE;
3859
3860 if (!completedTransitions)
3861 {
3862 fprintf (stderr, "[WARNING] Error opening done_transitions\n");
3863 return FALSE;
3864 }
3865
3866 fseek (completedTransitions, 0, SEEK_END);
3867 ctSize = ftell (completedTransitions);
3868 rewind (completedTransitions);
3869
3870 ctBuffer = calloc (ctSize + 1, sizeof (char));
3871 ctReadSize = fread (ctBuffer, 1, ctSize, completedTransitions);
3872
3873 if (ctReadSize != ctSize)
3874 D (D_FULL, "[WARNING] Couldn't read completed transitions file!\n");
3875
3876 ctBuffer[ctSize] = '\0';
3877
3878 for (i = 0; i < nFile; i++)
3879 {
3880 char *matched = strstr (ctBuffer, nameList[i]->d_name);
3881 CCSSettingsTransition *transition;
3882
3883 if (matched)
3884 {
3885 D (D_FULL, "Skipping transition %s\n", nameList[i]->d_name);
3886 continue;
3887 }
3888
3889 transition = ccsSettingsTransitionNew (path, nameList[i]->d_name);
3890
3891 D (D_FULL, "Processing transition %s\n", nameList[i]->d_name);
3892
3893 ccsProcessTransition (context, transition);
3894 ccsWriteChangedSettings (context);
3895 ccsWriteAutoSortedPluginList (context);
3896 D (D_FULL, "Completed transition %s\n", nameList[i]->d_name);
3897 fprintf (completedTransitions, "%s\n", nameList[i]->d_name);
3898 free (transition->file);
3899 free (transition->name);
3900 free (transition);
3901 free (nameList[i]);
3902 }
3903
3904 free (dupath);
3905 fclose (completedTransitions);
3906 free (ctBuffer);
3907 free (nameList);
3908
3909 return TRUE;
3910}
3911
3912Bool
3506ccsImportFromFile (CCSContext *context,3913ccsImportFromFile (CCSContext *context,
3507 const char *fileName,3914 const char *fileName,
3508 Bool overwriteNonDefault)3915 Bool overwriteNonDefault)

Subscribers

People subscribed via source and target branches

to all changes: