diff options
Diffstat (limited to 'common/dconf-changeset.c')
-rw-r--r-- | common/dconf-changeset.c | 100 |
1 files changed, 85 insertions, 15 deletions
diff --git a/common/dconf-changeset.c b/common/dconf-changeset.c index c80c88c..cea34c1 100644 --- a/common/dconf-changeset.c +++ b/common/dconf-changeset.c @@ -772,6 +772,87 @@ dconf_changeset_change (DConfChangeset *changeset, } /** + * dconf_changeset_filter_changes: + * @base: a database mode changeset + * @changes: a changeset + * + * Produces a changeset that contains all the changes in @changes that + * are not already present in @base + * + * If there are no such changes, %NULL is returned + * + * Applying the result to @base will yield the same result as applying + * @changes to @base + * + * Returns: (transfer full) (nullable): the minimal changes, or %NULL + * + * Since: 0.35.1 + */ +DConfChangeset * +dconf_changeset_filter_changes (DConfChangeset *base, + DConfChangeset *changes) +{ + DConfChangeset *result = NULL; + GHashTableIter iter_changes; + gpointer key, val; + + g_return_val_if_fail (base->is_database, NULL); + + /* We create the list of changes by iterating the 'changes' changeset + * and noting any keys that are not in the 'base' changeset or do not + * have the same value in the 'base' changeset + * + * 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, changes->table); + while (g_hash_table_iter_next (&iter_changes, &key, &val)) + { + GVariant *base_val = g_hash_table_lookup (base->table, key); + + 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 (); + + dconf_changeset_set (result, key, val); + } + } + + return result; +} + +/** * dconf_changeset_diff: * @from: a database mode changeset * @to: a database mode changeset @@ -793,7 +874,7 @@ DConfChangeset * dconf_changeset_diff (DConfChangeset *from, DConfChangeset *to) { - DConfChangeset *changeset = NULL; + DConfChangeset *changeset; GHashTableIter iter; gpointer key, val; @@ -806,8 +887,8 @@ dconf_changeset_diff (DConfChangeset *from, * * We create our list of changes in two steps: * - * - iterate the 'to' changeset and note any keys that do not have - * the same value in the 'from' changeset + * - call dconf_changeset_filter_changes to find values from 'to' + * which are not present in 'from' or hold different values to 'to' * * - iterate the 'from' changeset and note any keys not present in * the 'to' changeset, recording resets for them @@ -817,19 +898,8 @@ dconf_changeset_diff (DConfChangeset *from, * Note: because 'from' and 'to' are database changesets we don't have * to worry about seeing NULL values or dirs. */ - g_hash_table_iter_init (&iter, to->table); - while (g_hash_table_iter_next (&iter, &key, &val)) - { - GVariant *from_val = g_hash_table_lookup (from->table, key); - - if (from_val == NULL || !g_variant_equal (val, from_val)) - { - if (!changeset) - changeset = dconf_changeset_new (); - dconf_changeset_set (changeset, key, val); - } - } + changeset = dconf_changeset_filter_changes (from, to); g_hash_table_iter_init (&iter, from->table); while (g_hash_table_iter_next (&iter, &key, &val)) |