diff options
-rw-r--r-- | common/dconf-changeset.c | 38 | ||||
-rw-r--r-- | tests/changeset.c | 69 |
2 files changed, 90 insertions, 17 deletions
diff --git a/common/dconf-changeset.c b/common/dconf-changeset.c index 705fec9..cea34c1 100644 --- a/common/dconf-changeset.c +++ b/common/dconf-changeset.c @@ -793,7 +793,7 @@ dconf_changeset_filter_changes (DConfChangeset *base, DConfChangeset *changes) { DConfChangeset *result = NULL; - GHashTableIter iter; + GHashTableIter iter_changes; gpointer key, val; g_return_val_if_fail (base->is_database, NULL); @@ -805,13 +805,43 @@ dconf_changeset_filter_changes (DConfChangeset *base, * Note: because 'base' is a database changeset we don't have to * worry about it containing NULL values (dir resets). */ - g_hash_table_iter_init (&iter, changes->table); - while (g_hash_table_iter_next (&iter, &key, &val)) + g_hash_table_iter_init (&iter_changes, changes->table); + while (g_hash_table_iter_next (&iter_changes, &key, &val)) { GVariant *base_val = g_hash_table_lookup (base->table, key); - if (base_val == NULL || !g_variant_equal (val, base_val)) + if (g_str_has_suffix (key, "/")) + { + // Path reset + gboolean reset_is_effective = FALSE; + GHashTableIter iter_base; + gpointer base_key = NULL; + + g_return_val_if_fail (val == NULL, NULL); + + // First we check whether there are any keys in base that would be reset + g_hash_table_iter_init (&iter_base, base->table); + while (g_hash_table_iter_next (&iter_base, &base_key, NULL)) + if (g_str_has_prefix (base_key, key) && !g_str_equal (base_key, key)) + { + reset_is_effective = TRUE; + break; + } + + if (reset_is_effective) + { + if (!result) + result = dconf_changeset_new (); + + dconf_changeset_set (result, key, val); + } + } + else if (base_val == NULL && val == NULL) + continue; // Resetting a key that wasn't set + else if (val == NULL || base_val == NULL || !g_variant_equal (val, base_val)) { + // Resetting an existing key, inserting a value under a key that was not + // set, or replacing an existing value with a different one. if (!result) result = dconf_changeset_new (); diff --git a/tests/changeset.c b/tests/changeset.c index d22dcb8..d75e8d0 100644 --- a/tests/changeset.c +++ b/tests/changeset.c @@ -639,12 +639,14 @@ test_filter_changes (void) // Define test changesets as serialised g_variant strings const gchar *empty = NULL; const gchar *a1 = "{'/a': @mv <'value1'>}"; - const gchar *a_null = "{'/a': @mv nothing}"; const gchar *a2 = "{'/a': @mv <'value2'>}"; const gchar *b2 = "{'/b': @mv <'value2'>}"; const gchar *a1b1 = "{'/a': @mv <'value1'>, '/b': @mv <'value1'>}"; const gchar *a1b2 = "{'/a': @mv <'value1'>, '/b': @mv <'value2'>}"; - const gchar *reset = "{'/': @mv nothing}"; + const gchar *a1r1 = "{'/a': @mv <'value1'>, '/r/c': @mv <'value3'>}"; + const gchar *key_reset = "{'/a': @mv nothing}"; + const gchar *root_reset = "{'/': @mv nothing}"; + const gchar *partial_reset = "{'/r/': @mv nothing}"; gchar *filtered; /* an empty changeset would not change an empty database */ @@ -662,7 +664,8 @@ test_filter_changes (void) g_assert_cmpstr (filtered, ==, a1); g_free (filtered); - /* a changeset would change a database with the same keys but different values */ + /* a changeset would change a database with the same keys but + * different values */ filtered = call_filter_changes (a1, a2); g_assert_cmpstr (filtered, ==, a2); g_free (filtered); @@ -675,25 +678,65 @@ test_filter_changes (void) g_assert_cmpstr (filtered, ==, b2); g_free (filtered); - /* A changeset would change a database with some equal and some new values */ + /* A changeset would change a database with some equal and some new + * values */ filtered = call_filter_changes (a1, a1b2); g_assert_cmpstr (filtered, ==, b2); g_free (filtered); - /* A changeset would not change a database with some equal and some new values */ + /* A changeset would not change a database with some equal and some + * new values */ g_assert_null (call_filter_changes (a1b2, a1)); - /* Resets should count when there are values to be reset */ - filtered = call_filter_changes (a_null, reset); - g_assert_cmpstr (filtered, ==, reset); + /* A root reset has an effect on a database with values */ + filtered = call_filter_changes (a1, root_reset); + g_assert_cmpstr (filtered, ==, root_reset); g_free (filtered); - filtered = call_filter_changes (a1b2, reset); - g_assert_cmpstr (filtered, ==, reset); + + filtered = call_filter_changes (a1b2, root_reset); + g_assert_cmpstr (filtered, ==, root_reset); + g_free (filtered); + + /* A root reset would have no effect on an empty database */ + filtered = call_filter_changes (empty, root_reset); + g_assert_cmpstr (filtered, ==, NULL); + g_free (filtered); + + /* A key reset would have no effect on an empty database */ + filtered = call_filter_changes (empty, key_reset); + g_assert_cmpstr (filtered, ==, NULL); + g_free (filtered); + + /* A key reset would have no effect on a database with other keys */ + filtered = call_filter_changes (b2, key_reset); + g_assert_cmpstr (filtered, ==, NULL); + g_free (filtered); + + /* A key reset would have an effect on a database containing that + * key */ + filtered = call_filter_changes (a1, key_reset); + g_assert_cmpstr (filtered, ==, key_reset); + g_free (filtered); + + filtered = call_filter_changes (a1b1, key_reset); + g_assert_cmpstr (filtered, ==, key_reset); + g_free (filtered); + + /* A partial reset would have no effect on an empty database */ + filtered = call_filter_changes (empty, partial_reset); + g_assert_cmpstr (filtered, ==, NULL); + g_free (filtered); + + /* A partial reset would have no effect on a database with other + * values */ + filtered = call_filter_changes (a1, partial_reset); + g_assert_cmpstr (filtered, ==, NULL); g_free (filtered); - /* FIXME: ideally, a reset would have no effect on an empty database */ - filtered = call_filter_changes (empty, reset); - g_assert_cmpstr (filtered, ==, reset); + /* A partial reset would have an effect on a database with some values + * under that path */ + filtered = call_filter_changes (a1r1, partial_reset); + g_assert_cmpstr (filtered, ==, partial_reset); g_free (filtered); } |