Broken GKeyfileSettingsBackend refactor
These were some changes to the keyfile settings backend that were being
made as the new GSettingsBackendChangeset API was being worked on.
Since there is now back-compat for old backends, these changes are not
needed. Additionally, nacho is currently working in this area.
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
index 8eb7681..e862b2a 100644
--- a/gio/gkeyfilesettingsbackend.c
+++ b/gio/gkeyfilesettingsbackend.c
@@ -27,7 +27,6 @@
#include "gfile.h"
#include "gfileinfo.h"
#include "gfilemonitor.h"
-#include "gsimplepermission.h"
#include "gsettingsbackend.h"
@@ -45,8 +44,9 @@
{
GSettingsBackend parent_instance;
+ GSettingsBackendChangeset *database;
+
GKeyFile *keyfile;
- GPermission *permission;
gboolean writable;
gchar *prefix;
@@ -167,148 +167,143 @@
}
static gboolean
-path_is_valid (GKeyfileSettingsBackend *kfsb,
- const gchar *path)
+g_keyfile_settings_backend_can_write (GKeyfileSettingsBackend *self,
+ const gchar *path,
+ gboolean is_reset)
{
- return convert_path (kfsb, path, NULL, NULL);
-}
+ /* reset is always successful */
+ if (is_reset)
+ return TRUE;
-static GVariant *
-get_from_keyfile (GKeyfileSettingsBackend *kfsb,
- const GVariantType *type,
- const gchar *key)
-{
- GVariant *return_value = NULL;
- gchar *group, *name;
+ /* can't write if this database does not contain user values */
+ if (self->does_not_contain & G_SETTINGS_BACKEND_READ_USER_VALUE)
+ return FALSE;
- if (convert_path (kfsb, key, &group, &name))
- {
- gchar *str;
-
- g_assert (*name);
-
- str = g_key_file_get_value (kfsb->keyfile, group, name, NULL);
-
- if (str)
- {
- return_value = g_variant_parse (type, str, NULL, NULL, NULL);
- g_free (str);
- }
-
- g_free (group);
- g_free (name);
- }
-
- return return_value;
+ /* otherwise, we can write it if it is a valid path within the keyfile */
+ return convert_path (self, path, NULL, NULL);
}
static gboolean
-set_to_keyfile (GKeyfileSettingsBackend *kfsb,
- const gchar *key,
- GVariant *value)
+g_keyfile_settings_backend_write_internal (GKeyfileSettingsBackend *self,
+ const gchar *key,
+ GVariant *value)
{
gchar *group, *name;
- if (convert_path (kfsb, key, &group, &name))
+ /* do not attempt the write if this is not a user database */
+ if (~self->does_not_contain & G_SETTINGS_BACKEND_READ_USER_VALUE)
{
- if (value)
+ /* or if the path is outside of the scope of the keyfile... */
+ if (convert_path (self, key, &group, &name))
{
- gchar *str = g_variant_print (value, FALSE);
- g_key_file_set_value (kfsb->keyfile, group, name, str);
- g_variant_unref (g_variant_ref_sink (value));
- g_free (str);
- }
- else
- {
- if (*name == '\0')
+ if (value)
{
- gchar **groups;
- gint i;
-
- groups = g_key_file_get_groups (kfsb->keyfile, NULL);
-
- for (i = 0; groups[i]; i++)
- if (group_name_matches (groups[i], group))
- g_key_file_remove_group (kfsb->keyfile, groups[i], NULL);
-
- g_strfreev (groups);
+ gchar *str = g_variant_print (value, FALSE);
+ g_key_file_set_value (self->keyfile, group, name, str);
+ g_settings_backend_changeset_set (self->database, key, value);
+ g_variant_unref (g_variant_ref_sink (value));
+ g_free (str);
}
else
- g_key_file_remove_key (kfsb->keyfile, group, name, NULL);
+ {
+ if (*name == '\0')
+ {
+ gchar **groups;
+ gint i;
+
+ groups = g_key_file_get_groups (self->keyfile, NULL);
+
+ for (i = 0; groups[i]; i++)
+ if (group_name_matches (groups[i], group))
+ g_key_file_remove_group (self->keyfile, groups[i], NULL);
+
+ g_strfreev (groups);
+ }
+ else
+ g_key_file_remove_key (self->keyfile, group, name, NULL);
+ }
+
+ g_free (group);
+ g_free (name);
+
+ return TRUE;
}
-
- g_free (group);
- g_free (name);
-
- return TRUE;
}
- return FALSE;
+ /* we didn't do anything, but resets are always successful */
+ return (value == NULL) ? TRUE : FALSE;
}
static GVariant *
-g_keyfile_settings_backend_read (GSettingsBackend *backend,
- const gchar *key,
- const GVariantType *expected_type,
- gboolean default_value)
+g_keyfile_settings_backend_read_value (GSettingsBackend *backend,
+ const gchar *key,
+ GSettingsBackendReadFlags flags,
+ GQueue *read_through,
+ const GVariantType *expected_type)
{
- GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend);
+ GKeyfileSettingsBackend *self = G_KEYFILE_SETTINGS_BACKEND (backend);
+ GVariant *string_form;
+ GVariant *value;
- if (default_value)
+ if (g_settings_backend_check_changeset_queue (read_through, key, flags, &value))
+ return value;
+
+ /* If the user is requesting information from a specific database,
+ * ensure that it's the one that we have.
+ */
+ if (flags & self->does_not_contain)
return NULL;
- return get_from_keyfile (kfsb, expected_type, key);
+ if (!g_settings_backend_changeset_get (kfsb->database, key, &string_form))
+ return NULL;
+
+ value_form = g_variant_parse (expected_type, g_variant_get_string (string_form, NULL), NULL, NULL, NULL);
+
+ g_variant_unref (string_form);
+
+ return value_form;
}
-typedef struct
-{
- GKeyfileSettingsBackend *kfsb;
- gboolean failed;
-} WriteManyData;
-
static gboolean
-g_keyfile_settings_backend_write_one (gpointer key,
- gpointer value,
- gpointer user_data)
+g_keyfile_settings_backend_write_one (const gchar *key,
+ GVariant *value,
+ gpointer user_data)
{
- WriteManyData *data = user_data;
+ GKeyfileSettingsBackend *self = user_data;
gboolean success;
- success = set_to_keyfile (data->kfsb, key, value);
+ success = g_keyfile_settings_backend_write_internal (self, key, value);
g_assert (success);
- return FALSE;
+ return TRUE;
}
static gboolean
-g_keyfile_settings_backend_check_one (gpointer key,
- gpointer value,
- gpointer user_data)
+g_keyfile_settings_backend_check_one (const gchar *key,
+ GVariant *value,
+ gpointer user_data)
{
- WriteManyData *data = user_data;
+ GKeyfileSettingsBackend *self = user_data;
- return data->failed = !path_is_valid (data->kfsb, key);
+ return path_is_valid (self, key);
}
static gboolean
-g_keyfile_settings_backend_write_tree (GSettingsBackend *backend,
- GTree *tree,
- gpointer origin_tag)
+g_keyfile_settings_backend_write_changeset (GSettingsBackend *backend,
+ GSettingsBackendChangeset *changeset,
+ gpointer origin_tag)
{
- WriteManyData data = { G_KEYFILE_SETTINGS_BACKEND (backend) };
+ GKeyfileSettingsBackend *self = G_KEYFILE_SETTINGS_BACKEND (backend);
+ gboolean success;
- if (!data.kfsb->writable)
+ if (!g_settings_backend_changeset_all (changeset, g_keyfile_settings_backend_check_one, self))
return FALSE;
- g_tree_foreach (tree, g_keyfile_settings_backend_check_one, &data);
+ success = g_settings_backend_changeset_all (changeset, g_keyfile_settings_backend_write_one, self);
+ g_assert (success); /* otherwise the check should have failed above */
- if (data.failed)
- return FALSE;
-
- g_tree_foreach (tree, g_keyfile_settings_backend_write_one, &data);
- g_keyfile_settings_backend_keyfile_write (data.kfsb);
-
- g_settings_backend_changed_tree (backend, tree, origin_tag);
+ g_settings_backend_changeset_applied (backend, changeset, origin_tag);
+ g_keyfile_settings_backend_keyfile_write (self);
return TRUE;
}
@@ -319,18 +314,18 @@
GVariant *value,
gpointer origin_tag)
{
- GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend);
+ GKeyfileSettingsBackend *self = G_KEYFILE_SETTINGS_BACKEND (backend);
gboolean success;
- if (!kfsb->writable)
+ if (!self->writable)
return FALSE;
- success = set_to_keyfile (kfsb, key, value);
+ success = g_keyfile_settings_backend_write_internal (self, key, value);
if (success)
{
g_settings_backend_changed (backend, key, origin_tag);
- g_keyfile_settings_backend_keyfile_write (kfsb);
+ g_keyfile_settings_backend_keyfile_write (self);
}
return success;
@@ -341,10 +336,10 @@
const gchar *key,
gpointer origin_tag)
{
- GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend);
+ GKeyfileSettingsBackend *self = G_KEYFILE_SETTINGS_BACKEND (backend);
- if (set_to_keyfile (kfsb, key, NULL))
- g_keyfile_settings_backend_keyfile_write (kfsb);
+ if (g_keyfile_settings_backend_write_internal (self, key, NULL))
+ g_keyfile_settings_backend_keyfile_write (self);
g_settings_backend_changed (backend, key, origin_tag);
}
@@ -358,24 +353,16 @@
return kfsb->writable && path_is_valid (kfsb, name);
}
-static GPermission *
-g_keyfile_settings_backend_get_permission (GSettingsBackend *backend,
- const gchar *path)
+static GSettingsBackendChangeset *
+g_keyfile_settings_backend_keyfile_to_changeset (GKeyfileSettingsBackend *kfsb,
+ GKeyFile *keyfile)
{
- GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend);
-
- return g_object_ref (kfsb->permission);
-}
-
-static void
-keyfile_to_tree (GKeyfileSettingsBackend *kfsb,
- GTree *tree,
- GKeyFile *keyfile,
- gboolean dup_check)
-{
+ GSettingsBackendChangeset *changeset;
gchar **groups;
gint i;
+ changeset = g_settings_backend_changeset_new_database (NULL);
+
groups = g_key_file_get_groups (keyfile, NULL);
for (i = 0; groups[i]; i++)
{
@@ -409,19 +396,17 @@
value = g_key_file_get_value (keyfile, groups[i], keys[j], NULL);
- if (dup_check && g_strcmp0 (g_tree_lookup (tree, path), value) == 0)
- {
- g_tree_remove (tree, path);
- g_free (value);
- g_free (path);
- }
- else
- g_tree_insert (tree, path, value);
+ g_settings_backend_changeset_set (changeset, path, g_variant_new_string (value));
+
+ g_free (value);
+ g_free (path);
}
g_strfreev (keys);
}
g_strfreev (groups);
+
+ return changeset;
}
static void
@@ -439,29 +424,26 @@
if (memcmp (kfsb->digest, digest, sizeof digest) != 0)
{
- GKeyFile *keyfiles[2];
- GTree *tree;
+ GSettingsBackendChangeset *old, *diff;
- tree = g_tree_new_full ((GCompareDataFunc) strcmp, NULL,
- g_free, g_free);
+ g_key_file_unref (kfsb->keyfile);
- keyfiles[0] = kfsb->keyfile;
- keyfiles[1] = g_key_file_new ();
+ kfsb->keyfile = g_key_file_new ();
if (length > 0)
- g_key_file_load_from_data (keyfiles[1], contents, length,
+ g_key_file_load_from_data (kfsb->keyfile, contents, length,
G_KEY_FILE_KEEP_COMMENTS |
G_KEY_FILE_KEEP_TRANSLATIONS, NULL);
- keyfile_to_tree (kfsb, tree, keyfiles[0], FALSE);
- keyfile_to_tree (kfsb, tree, keyfiles[1], TRUE);
- g_key_file_free (keyfiles[0]);
- kfsb->keyfile = keyfiles[1];
+ old = kfsb->database;
+ kfsb->database = g_keyfile_settings_backend_keyfile_to_changeset (kfsb, kfsb->keyfile);
- if (g_tree_nnodes (tree) > 0)
- g_settings_backend_changed_tree (&kfsb->parent_instance, tree, NULL);
+ diff = g_settings_backend_changeset_diff (old, kfsb->database);
- g_tree_unref (tree);
+ g_settings_backend_changeset_applied (G_SETTINGS_BACKEND (kfsb), diff, NULL);
+
+ g_settings_backend_changeset_unref (diff);
+ g_settings_backend_changeset_unref (old);
memcpy (kfsb->digest, digest, sizeof digest);
}
@@ -500,7 +482,6 @@
GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
g_key_file_free (kfsb->keyfile);
- g_object_unref (kfsb->permission);
g_file_monitor_cancel (kfsb->file_monitor);
g_object_unref (kfsb->file_monitor);
@@ -529,12 +510,11 @@
object_class->finalize = g_keyfile_settings_backend_finalize;
- class->read = g_keyfile_settings_backend_read;
+ class->read_value = g_keyfile_settings_backend_read_value;
class->write = g_keyfile_settings_backend_write;
- class->write_tree = g_keyfile_settings_backend_write_tree;
+ class->write_changeset = g_keyfile_settings_backend_write_changeset;
class->reset = g_keyfile_settings_backend_reset;
class->get_writable = g_keyfile_settings_backend_get_writable;
- class->get_permission = g_keyfile_settings_backend_get_permission;
/* No need to implement subscribed/unsubscribe: the only point would be to
* stop monitoring the file when there's no GSettings anymore, which is no
* big win.
@@ -636,7 +616,6 @@
kfsb = g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND, NULL);
kfsb->keyfile = g_key_file_new ();
- kfsb->permission = g_simple_permission_new (TRUE);
kfsb->file = g_file_new_for_path (filename);
kfsb->dir = g_file_get_parent (kfsb->file);