diff options
author | Allison Ryan Lortie <desrt@desrt.ca> | 2015-11-30 16:40:25 +0000 |
---|---|---|
committer | Allison Ryan Lortie <desrt@desrt.ca> | 2015-11-30 16:40:32 +0000 |
commit | c6423fa1cacb9fb3178016e712be9323a743bce4 (patch) | |
tree | e26e41de0cee7d0eb5f9de82159fe37e73ba5674 | |
parent | 4ef5a2a4c6ac349f51a1cd5f9013efe8c5f26f12 (diff) | |
download | dconf-c6423fa1cacb9fb3178016e712be9323a743bce4.tar.gz |
DConfChangeset: implement dir resets properly
If a dir is reset against a DConfChangeset then the result ought to be
that all keys under that dir read as NULL (until such a time as they are
set to a new value).
This is consistent with the (existing) behaviour that a key will read as
NULL if it, itself, was reset.
In order to make that efficient, we create a separate GHashTable to
serve as a cache of all of the directories that have been reset and
iterate it whenever we do a key lookup that doesn't have a direct hit.
We update (and expand) the test case to reflect this new reality -- the
tests actually had a case that relied on the inconsistent behaviour.
https://bugzilla.gnome.org/show_bug.cgi?id=744678
-rw-r--r-- | common/dconf-changeset.c | 57 | ||||
-rw-r--r-- | tests/changeset.c | 27 |
2 files changed, 69 insertions, 15 deletions
diff --git a/common/dconf-changeset.c b/common/dconf-changeset.c index 89f340c..eb370d6 100644 --- a/common/dconf-changeset.c +++ b/common/dconf-changeset.c @@ -54,6 +54,7 @@ struct _DConfChangeset { GHashTable *table; + GHashTable *dir_resets; guint is_database : 1; guint is_sealed : 1; gint ref_count; @@ -157,6 +158,9 @@ dconf_changeset_unref (DConfChangeset *changeset) g_hash_table_unref (changeset->table); + if (changeset->dir_resets) + g_hash_table_unref (changeset->dir_resets); + g_slice_free (DConfChangeset, changeset); } } @@ -177,6 +181,21 @@ dconf_changeset_ref (DConfChangeset *changeset) return changeset; } +void +dconf_changeset_record_dir_reset (DConfChangeset *changeset, + const gchar *dir) +{ + g_return_if_fail (dconf_is_dir (dir, NULL)); + g_return_if_fail (!changeset->is_database); + g_return_if_fail (!changeset->is_sealed); + + if (!changeset->dir_resets) + changeset->dir_resets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + g_hash_table_insert (changeset->table, g_strdup (dir), NULL); + g_hash_table_add (changeset->dir_resets, g_strdup (dir)); +} + /** * dconf_changeset_set: * @changeset: a #DConfChangeset @@ -217,7 +236,7 @@ dconf_changeset_set (DConfChangeset *changeset, /* If this is a non-database then record the reset itself. */ if (!changeset->is_database) - g_hash_table_insert (changeset->table, g_strdup (path), NULL); + dconf_changeset_record_dir_reset (changeset, path); } /* ...or a value reset */ @@ -263,7 +282,26 @@ dconf_changeset_get (DConfChangeset *changeset, gpointer tmp; if (!g_hash_table_lookup_extended (changeset->table, key, NULL, &tmp)) - return FALSE; + { + /* Did not find an exact match, so check for dir resets */ + if (changeset->dir_resets) + { + GHashTableIter iter; + gpointer dir; + + g_hash_table_iter_init (&iter, changeset->dir_resets); + while (g_hash_table_iter_next (&iter, &dir, NULL)) + if (g_str_has_prefix (key, dir)) + { + if (value) + *value = NULL; + + return TRUE; + } + } + + return FALSE; + } if (value) *value = tmp ? g_variant_ref (tmp) : NULL; @@ -624,16 +662,11 @@ dconf_changeset_deserialise (GVariant *serialised) * * If we get an invalid case, just fall through and ignore it. */ - if (value == NULL) - { - if (dconf_is_path (key, NULL)) - g_hash_table_insert (changeset->table, g_strdup (key), NULL); - } - else - { - if (dconf_is_key (key, NULL)) - g_hash_table_insert (changeset->table, g_strdup (key), g_variant_ref (value)); - } + if (dconf_is_key (key, NULL)) + g_hash_table_insert (changeset->table, g_strdup (key), value ? g_variant_ref (value) : NULL); + + else if (dconf_is_dir (key, NULL) && value == NULL) + dconf_changeset_record_dir_reset (changeset, key); } return changeset; diff --git a/tests/changeset.c b/tests/changeset.c index 90b8de6..5f046df 100644 --- a/tests/changeset.c +++ b/tests/changeset.c @@ -281,37 +281,58 @@ static void test_reset (void) { DConfChangeset *changeset; + GVariant *value; changeset = dconf_changeset_new (); g_assert (!dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (!dconf_changeset_get (changeset, "/value/a", &value)); + /* value was not set */ /* set a value */ dconf_changeset_set (changeset, "/value/a", g_variant_new_boolean (TRUE)); g_assert (dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", &value)); + g_assert (value != NULL); + g_variant_unref (value); /* record the reset */ dconf_changeset_set (changeset, "/value/", NULL); - g_assert (!dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", &value)); + g_assert (value == NULL); /* write it back */ dconf_changeset_set (changeset, "/value/a", g_variant_new_boolean (TRUE)); g_assert (dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", &value)); + g_assert (value != NULL); + g_variant_unref (value); /* reset again */ dconf_changeset_set (changeset, "/value/", NULL); - g_assert (!dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", &value)); + g_assert (value == NULL); /* write again */ dconf_changeset_set (changeset, "/value/a", g_variant_new_boolean (TRUE)); g_assert (dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", &value)); + g_assert (value != NULL); + g_variant_unref (value); /* reset a different way */ - dconf_changeset_set (changeset, "/value/a", g_variant_new_boolean (TRUE)); + dconf_changeset_set (changeset, "/value/a", NULL); g_assert (dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", &value)); + g_assert (value == NULL); /* write last time */ dconf_changeset_set (changeset, "/value/a", g_variant_new_boolean (TRUE)); g_assert (dconf_changeset_get (changeset, "/value/a", NULL)); + g_assert (dconf_changeset_get (changeset, "/value/a", &value)); + g_assert (value != NULL); + g_variant_unref (value); dconf_changeset_unref (changeset); } |