Versioned config for Elementary.
authorIván Briano <sachieru@gmail.com>
Thu, 2 Sep 2010 14:33:04 +0000 (14:33 +0000)
committerIván Briano <sachieru@gmail.com>
Thu, 2 Sep 2010 14:33:04 +0000 (14:33 +0000)
This is not doing much now, just the version field in the struct,
some stuff stolen from E and a base to use when new things are added.
There are some comments in the code about what to do in certain cases
that E does not have, like a system update, new config and apps linked
to the old version still running when the config Atoms are updated. These
things we'll probably be addressed as they are needed, as well as come
clean up in quick code I ditched in there, but it would be good to do so
with more feedback from the good guys around that like to break SVN
every now and then.

Since the commit message is already long enough, I'm adding some more crap
just for the sake of doing so. I could go with some tl;dr thing as well,
but I don't feel like resuming what's up there.

Have a nice day.

SVN revision: 51843

config/default/base.src
config/illume/base.src
config/standard/base.src
src/lib/elm_config.c
src/lib/elm_priv.h

index 9cd5c20..f305f68 100644 (file)
@@ -1,4 +1,5 @@
 group "Elm_Config" struct {
+  value "config_version" int: 65537;
   value "engine" int: 0;
   value "thumbscroll_enable" int: 1;
   value "thumbscroll_threshhold" int: 24;
index 9cd5c20..f305f68 100644 (file)
@@ -1,4 +1,5 @@
 group "Elm_Config" struct {
+  value "config_version" int: 65537;
   value "engine" int: 0;
   value "thumbscroll_enable" int: 1;
   value "thumbscroll_threshhold" int: 24;
index 4df5eda..f498b48 100644 (file)
@@ -1,4 +1,5 @@
 group "Elm_Config" struct {
+  value "config_version" int: 65537;
   value "engine" int: 0;
   value "thumbscroll_enable" int: 1;
   value "thumbscroll_threshhold" int: 4;
index a8315e3..5bb0b30 100644 (file)
@@ -18,7 +18,10 @@ static void _desc_shutdown(void);
 static void _profile_get(void);
 static void _config_free(void);
 static void _config_apply(void);
+static Elm_Config * _config_user_load(void);
+static Elm_Config * _config_system_load(void);
 static void _config_load(void);
+static void _config_update(void);
 static void _env_get(void);
 
 #ifdef HAVE_ELEMENTARY_X
@@ -79,6 +82,16 @@ _prop_config_get(void)
    config_data = eet_data_descriptor_decode(_config_edd, data, size);
    free(data);
    if (!config_data) return EINA_FALSE;
+
+   /* What do we do on version mismatch when someone changes the
+    * config in the rootwindow? */
+   /* Most obvious case, new version and we are still linked to
+    * whatever was there before, we just ignore until user restarts us */
+   if (config_data->config_version > ELM_CONFIG_VERSION)
+     return EINA_TRUE;
+   /* What in the case the version is older? Do we even support those
+    * cases or we only check for equality above? */
+
    _config_free();
    _elm_config = config_data;
    _config_apply();
@@ -143,7 +156,6 @@ _prop_change(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
              
              val = ecore_x_window_prop_string_get(event->win,
                                                   event->atom);
-            eina_stringshare_replace(&_elm_config->theme, val);
             if (val)
               {
                   int changed = 0;
@@ -191,6 +203,7 @@ _desc_init(void)
         printf("EEEK! eet_data_descriptor_file_new() failed\n");
         return;
      }
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "config_version", config_version, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "engine", engine, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "thumbscroll_enable", thumbscroll_enable, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "thumbscroll_threshhold", thumbscroll_threshhold, EET_T_INT);
@@ -307,38 +320,70 @@ _config_apply(void)
    edje_scale_set(_elm_config->scale);
 }
 
-static void
-_config_load(void)
+static Elm_Config *
+_config_user_load(void)
 {
-   Eet_File *ef = NULL;
+   Elm_Config *cfg = NULL;
+   Eet_File *ef;
    char buf[PATH_MAX];
-   const char *home = NULL;
-   
+   const char *home;
+
    home = getenv("HOME");
-   if (!home) home = "/";
-   
-   // user config
-   snprintf(buf, sizeof(buf), "%s/.elementary/config/%s/base.cfg", home, _elm_profile);
+   if (!home) home = "";
+
+   snprintf(buf, sizeof(buf), "%s/.elementary/config/%s/base.cfg", home,
+            _elm_profile);
    ef = eet_open(buf, EET_FILE_MODE_READ);
    if (ef)
      {
-        _elm_config = eet_data_read(ef, _config_edd, "config");
+        cfg = eet_data_read(ef, _config_edd, "config");
         eet_close(ef);
      }
-   if (_elm_config) return;
-   
-   // system config
-   snprintf(buf, sizeof(buf), "%s/config/%s/base.cfg", _elm_data_dir, _elm_profile);
+   return cfg;
+}
+
+static Elm_Config *
+_config_system_load(void)
+{
+   Elm_Config *cfg = NULL;
+   Eet_File *ef;
+   char buf[PATH_MAX];
+
+   snprintf(buf, sizeof(buf), "%s/config/%s/base.cfg", _elm_data_dir,
+            _elm_profile);
    ef = eet_open(buf, EET_FILE_MODE_READ);
    if (ef)
      {
-        _elm_config = eet_data_read(ef, _config_edd, "config");
+        cfg = eet_data_read(ef, _config_edd, "config");
         eet_close(ef);
      }
+   return cfg;
+}
+
+static void
+_config_load(void)
+{
+   _elm_config = _config_user_load();
+   if (_elm_config)
+     {
+        if (_elm_config->config_version < ELM_CONFIG_VERSION)
+          _config_update();
+        return;
+     }
+
+   /* no user config, fallback for system. No need to check version for
+    * this one, if it's not the right one, someone screwed up at the time
+    * of installing it */
+   _elm_config = _config_system_load();
    if (_elm_config) return;
+   /* FIXME: config load could have failed because of a non-existent
+    * profile. Fallback to default before moving on */
 
    // config load fail - defaults
+   /* XXX: do these make sense? Only if it's valid to install the lib
+    * without the config, but do we want that? */
    _elm_config = ELM_NEW(Elm_Config);
+   _elm_config->config_version = ELM_CONFIG_VERSION;
    _elm_config->engine = ELM_SOFTWARE_X11;
    _elm_config->thumbscroll_enable = 1;
    _elm_config->thumbscroll_threshhold = 24;
@@ -363,6 +408,46 @@ _config_load(void)
 }
 
 static void
+_config_update(void)
+{
+   Elm_Config *tcfg;
+
+   tcfg = _config_system_load();
+   if (!tcfg)
+     {
+        /* weird profile or something? We should probably fill
+         * with hardcoded defaults, or get from default previx */
+        return;
+     }
+#define IFCFG(v) if ((_elm_config->config_version & 0xffff) < (v)) {
+#define IFCFGELSE } else {
+#define IFCFGEND }
+#define COPYVAL(x) do {_elm_config->x = tcfg->x;} while(0)
+#define COPYPTR(x) do {_elm_config->x = tcfg->x; tcfg->x = NULL; } while(0)
+#define COPYSTR(x) COPYPTR(x)
+
+   /* we also need to update for property changes in the root window
+    * if needed, but that will be dependant on new properties added
+    * with each version */
+
+   /* nothing here, just an example */
+   /*
+   IFCFG(0x0002);
+   COPYVAL(some_value);
+   IFCFGEND;
+   */
+
+#undef COPYSTR
+#undef COPYPTR
+#undef COPYVAL
+#undef IFCFGEND
+#undef IFCFGELSE
+#undef IFCFG
+
+   /* after updating user config, we must save */
+}
+
+static void
 _env_get(void)
 {
    char *s;
index 5a1524a..963ca43 100644 (file)
@@ -50,8 +50,19 @@ typedef enum _Elm_Engine
 
 typedef struct _Elm_Config Elm_Config;
 
+/* increment this whenever we change config enough that you need new
+ * defaults for elm to work.
+ */
+#define ELM_CONFIG_EPOCH           0x0001
+/* increment this whenever a new set of config values are added but the users
+ * config doesn't need to be wiped - simply new values need to be put in
+ */
+#define ELM_CONFIG_FILE_GENERATION 0x0001
+#define ELM_CONFIG_VERSION         ((ELM_CONFIG_EPOCH << 16) | ELM_CONFIG_FILE_GENERATION)
+
 struct _Elm_Config
 {
+   int config_version;
    int engine;
    int thumbscroll_enable;
    int thumbscroll_threshhold;