Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package dconf for openSUSE:Factory checked in at 2021-04-12 12:35:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/dconf (Old) and /work/SRC/openSUSE:Factory/.dconf.new.2401 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dconf" Mon Apr 12 12:35:07 2021 rev:53 rq:881091 version:0.40.0 Changes: -------- --- /work/SRC/openSUSE:Factory/dconf/dconf.changes 2020-11-23 10:24:58.980989898 +0100 +++ /work/SRC/openSUSE:Factory/.dconf.new.2401/dconf.changes 2021-04-12 12:37:37.341387248 +0200 @@ -1,0 +2,18 @@ +Thu Mar 18 14:20:52 UTC 2021 - Dominique Leuenberger <dims...@opensuse.org> + +- Update to version 0.40.0: + + common: Add missing G_BEGIN/END_DECLS to allow use of headers + from C++ code. + +------------------------------------------------------------------- +Tue Feb 9 12:40:42 UTC 2021 - Dominique Leuenberger <dims...@opensuse.org> + +- Update to version 0.39.1: + + Build: + - Improve libdconf visible symbols. + - Minor fixes to bash completion script. + + Engine: do not emit optimistic change notifications unless the + local value is different. + + service: add a systemd unit for D-Bus activation. + +------------------------------------------------------------------- Old: ---- dconf-0.38.0.tar.xz New: ---- dconf-0.40.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dconf.spec ++++++ --- /var/tmp/diff_new_pack.OvLJ22/_old 2021-04-12 12:37:37.797387779 +0200 +++ /var/tmp/diff_new_pack.OvLJ22/_new 2021-04-12 12:37:37.797387779 +0200 @@ -1,7 +1,7 @@ # # spec file for package dconf # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,13 +17,13 @@ Name: dconf -Version: 0.38.0 +Version: 0.40.0 Release: 0 Summary: Key-based configuration system License: LGPL-2.1-or-later Group: System/Libraries URL: https://live.gnome.org/dconf -Source0: https://download.gnome.org/sources/dconf/0.38/%{name}-%{version}.tar.xz +Source0: https://download.gnome.org/sources/dconf/0.40/%{name}-%{version}.tar.xz Source99: baselibs.conf BuildRequires: docbook-xsl-stylesheets BuildRequires: gtk-doc @@ -125,6 +125,7 @@ %{_mandir}/man1/dconf-service.1%{?ext_man} # alternative databases %{_sysconfdir}/dconf/ +%{_userunitdir}/dconf.service %files -n libdconf1 %{_libdir}/libdconf.so.* ++++++ dconf-0.38.0.tar.xz -> dconf-0.40.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/NEWS new/dconf-0.40.0/NEWS --- old/dconf-0.38.0/NEWS 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/NEWS 2021-03-13 02:05:23.383886000 +0100 @@ -1,3 +1,20 @@ +Changes in dconf 0.40.0 +======================= + + - common: Add missing G_BEGIN/END_DECLS to allow use of headers from C++ + code (Philip Withnall, !67) + + +Changes in dconf 0.39.1 +======================= + + - build: improve libdconf visible symbols (Inigo Martinez, Daniel Playfair + Cal, !59) + - engine: do not emit optimistic change notifications unless the local value + is different (Daniel Playfair Cal, !2) + - build: minor fixes to bash completion script (Philip Withnall, !64) + - service: add a systemd unit for D-Bus activation (Simon McVittie, !63) + Changes in dconf 0.38.0 ======================= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/bin/completion/dconf new/dconf-0.40.0/bin/completion/dconf --- old/dconf-0.38.0/bin/completion/dconf 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/bin/completion/dconf 2021-03-13 02:05:23.387219400 +0100 @@ -9,15 +9,15 @@ case "${COMP_CWORD}" in 1) - choices=$'help \nread \nlist \nwrite \nreset \nupdate \nlock \nunlock \nwatch \ndump \nload \ncompile ' + choices=$'help \nread \nlist \nlist-locks \nwrite \nreset \ncompile \nupdate \nwatch \ndump \nload \nblame ' ;; 2) case "${COMP_WORDS[1]}" in help) - choices=$'help \nread \nlist \nwrite \nreset \nupdate \nlock \nunlock \nwatch \ndump \nload \ncompile ' + choices=$'help \nread \nlist \nlist-locks \nwrite \nreset \ncompile \nupdate \nwatch \ndump \nload \nblame ' ;; - list|dump|load) + list|list-locks|dump|load) choices="$(dconf _complete / "${COMP_WORDS[2]}")" ;; read|list|write|lock|unlock|watch|reset) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/client/meson.build new/dconf-0.40.0/client/meson.build --- old/dconf-0.38.0/client/meson.build 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/client/meson.build 2021-03-13 02:05:23.387219400 +0100 @@ -12,11 +12,6 @@ sources = files('dconf-client.c') -deps = [ - libdconf_common_hidden_dep, - libdconf_gdbus_thread_dep, -] - libdconf_client = static_library( 'dconf-client', sources: sources, @@ -31,14 +26,25 @@ link_with: libdconf_client, ) +client_deps = [ + libdconf_common_dep, + libdconf_engine_dep, + libdconf_gdbus_thread_dep, +] + +symbol_map = join_paths(meson.current_source_dir(), 'symbol.map') +ldflags = cc.get_supported_link_arguments('-Wl,--version-script,@0@'.format(symbol_map)) + libdconf = shared_library( 'dconf', sources: sources, version: libversion, soversion: soversion, include_directories: top_inc, - dependencies: deps, + dependencies: client_deps, c_args: dconf_c_args, + link_args: ldflags, + link_depends: symbol_map, install: true, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/client/symbol.map new/dconf-0.40.0/client/symbol.map --- old/dconf-0.38.0/client/symbol.map 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/client/symbol.map 2021-03-13 02:05:23.387219400 +0100 @@ -0,0 +1,14 @@ +{ +global: + dconf_client_*; + dconf_changeset_*; + dconf_error_quark; + dconf_is_path; + dconf_is_key; + dconf_is_dir; + dconf_is_rel_path; + dconf_is_rel_key; + dconf_is_rel_dir; +local: + *; +}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/client/symbols.txt new/dconf-0.40.0/client/symbols.txt --- old/dconf-0.38.0/client/symbols.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/client/symbols.txt 2021-03-13 02:05:23.387219400 +0100 @@ -0,0 +1,40 @@ +dconf_changeset_all +dconf_changeset_change +dconf_changeset_describe +dconf_changeset_deserialise +dconf_changeset_diff +dconf_changeset_filter_changes +dconf_changeset_get +dconf_changeset_is_empty +dconf_changeset_is_similar_to +dconf_changeset_new +dconf_changeset_new_database +dconf_changeset_new_write +dconf_changeset_ref +dconf_changeset_seal +dconf_changeset_serialise +dconf_changeset_set +dconf_changeset_unref +dconf_client_change_fast +dconf_client_change_sync +dconf_client_get_type +dconf_client_is_writable +dconf_client_list +dconf_client_list_locks +dconf_client_new +dconf_client_read +dconf_client_read_full +dconf_client_sync +dconf_client_unwatch_fast +dconf_client_unwatch_sync +dconf_client_watch_fast +dconf_client_watch_sync +dconf_client_write_fast +dconf_client_write_sync +dconf_error_quark +dconf_is_dir +dconf_is_key +dconf_is_path +dconf_is_rel_dir +dconf_is_rel_key +dconf_is_rel_path diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/common/dconf-changeset.h new/dconf-0.40.0/common/dconf-changeset.h --- old/dconf-0.38.0/common/dconf-changeset.h 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/common/dconf-changeset.h 2021-03-13 02:05:23.387219400 +0100 @@ -22,6 +22,8 @@ #include <glib.h> +G_BEGIN_DECLS + typedef struct _DConfChangeset DConfChangeset; typedef gboolean (* DConfChangesetPredicate) (const gchar *path, @@ -75,4 +77,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(DConfChangeset, dconf_changeset_unref) +G_END_DECLS + #endif /* __dconf_changeset_h__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/common/dconf-enums.h new/dconf-0.40.0/common/dconf-enums.h --- old/dconf-0.38.0/common/dconf-enums.h 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/common/dconf-enums.h 2021-03-13 02:05:23.387219400 +0100 @@ -22,6 +22,8 @@ #include <glib.h> +G_BEGIN_DECLS + #define DCONF_ERROR (dconf_error_quark ()) GQuark dconf_error_quark (void); @@ -39,4 +41,6 @@ DCONF_READ_USER_VALUE = (1u << 1) } DConfReadFlags; +G_END_DECLS + #endif /* __dconf_error_h__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/common/dconf-gvdb-utils.c new/dconf-0.40.0/common/dconf-gvdb-utils.c --- old/dconf-0.38.0/common/dconf-gvdb-utils.c 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/common/dconf-gvdb-utils.c 2021-03-13 02:05:23.390553000 +0100 @@ -0,0 +1,235 @@ +/* + * Copyright ?? 2010 Codethink Limited + * Copyright ?? 2012 Canonical Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <de...@desrt.ca> + */ + +#include "config.h" + +#include "dconf-gvdb-utils.h" + +#include "./dconf-paths.h" +#include "../gvdb/gvdb-builder.h" +#include "../gvdb/gvdb-reader.h" + +#include <errno.h> +#include <glib.h> +#include <glib/gstdio.h> +#include <string.h> + +DConfChangeset * +dconf_gvdb_utils_changeset_from_table (GvdbTable *table) +{ + DConfChangeset *database = dconf_changeset_new_database (NULL); + gchar **names; + gsize n_names; + gsize i; + + names = gvdb_table_get_names (table, &n_names); + for (i = 0; i < n_names; i++) + { + if (dconf_is_key (names[i], NULL)) + { + GVariant *value; + + value = gvdb_table_get_value (table, names[i]); + + if (value != NULL) + { + dconf_changeset_set (database, names[i], value); + g_variant_unref (value); + } + } + + g_free (names[i]); + } + + g_free (names); + return database; +} + +DConfChangeset * +dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, + gboolean *file_missing, + GError **error) +{ + DConfChangeset *database; + GError *my_error = NULL; + GvdbTable *table = NULL; + gchar *contents; + gsize size; + + if (g_file_get_contents (filename, &contents, &size, &my_error)) + { + GBytes *bytes; + + bytes = g_bytes_new_take (contents, size); + table = gvdb_table_new_from_bytes (bytes, FALSE, &my_error); + g_bytes_unref (bytes); + } + + /* It is perfectly fine if the file does not exist -- then it's + * just empty. + */ + if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + g_clear_error (&my_error); + + /* Otherwise, we should report errors to prevent ourselves from + * overwriting the database in other situations... + */ + if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_INVAL)) + { + /* Move the database to a backup file, warn and continue with a new + * database. The alternative is erroring out and exiting the daemon, + * which leaves the user???s session essentially unusable. + * + * The code to find an unused backup filename is racy, but this is an + * error handling path. Who cares. */ + g_autofree gchar *backup_filename = NULL; + guint i; + + for (i = 0; + i < G_MAXUINT && + (backup_filename == NULL || g_file_test (backup_filename, G_FILE_TEST_EXISTS)); + i++) + { + g_free (backup_filename); + backup_filename = g_strdup_printf ("%s~%u", filename, i); + } + + if (g_rename (filename, backup_filename) != 0) + g_warning ("Error renaming corrupt database from ???%s??? to ???%s???: %s", + filename, backup_filename, g_strerror (errno)); + else + g_warning ("Database ???%s??? was corrupt: moved it to ???%s??? and created an empty replacement", + filename, backup_filename); + + g_clear_error (&my_error); + } + else if (my_error) + { + g_propagate_prefixed_error (error, my_error, "Cannot open dconf database: "); + return NULL; + } + + /* Fill the table up with the initial state */ + if (table != NULL) + { + database = dconf_gvdb_utils_changeset_from_table (table); + gvdb_table_free (table); + } + else + database = dconf_changeset_new_database (NULL); + + if (file_missing) + *file_missing = (table == NULL); + + return database; +} + +static GvdbItem * +dconf_gvdb_utils_get_parent (GHashTable *table, + const gchar *key) +{ + GvdbItem *grandparent, *parent; + gchar *parent_name; + gint len; + + if (g_str_equal (key, "/")) + return NULL; + + len = strlen (key); + if (key[len - 1] == '/') + len--; + + while (key[len - 1] != '/') + len--; + + parent_name = g_strndup (key, len); + parent = g_hash_table_lookup (table, parent_name); + + if (parent == NULL) + { + parent = gvdb_hash_table_insert (table, parent_name); + + grandparent = dconf_gvdb_utils_get_parent (table, parent_name); + + if (grandparent != NULL) + gvdb_item_set_parent (parent, grandparent); + } + + g_free (parent_name); + + return parent; +} + +static gboolean +dconf_gvdb_utils_add_key (const gchar *path, + GVariant *value, + gpointer user_data) +{ + GHashTable *gvdb = user_data; + GvdbItem *item; + + g_assert (g_hash_table_lookup (gvdb, path) == NULL); + item = gvdb_hash_table_insert (gvdb, path); + gvdb_item_set_parent (item, dconf_gvdb_utils_get_parent (gvdb, path)); + gvdb_item_set_value (item, value); + + return TRUE; +} + +GHashTable * +dconf_gvdb_utils_table_from_changeset (DConfChangeset *database) +{ + GHashTable *table; + + table = gvdb_hash_table_new (NULL, NULL); + dconf_changeset_all (database, dconf_gvdb_utils_add_key, table); + return table; +} + +gboolean +dconf_gvdb_utils_write_file (const gchar *filename, + DConfChangeset *database, + GError **error) +{ + GHashTable *gvdb; + gboolean success; + + gvdb = dconf_gvdb_utils_table_from_changeset (database); + success = gvdb_table_write_contents (gvdb, filename, FALSE, error); + + if (!success) + { + gchar *dirname; + + /* Maybe it failed because the directory doesn't exist. Try + * again, after mkdir(). + */ + dirname = g_path_get_dirname (filename); + g_mkdir_with_parents (dirname, 0700); + g_free (dirname); + + g_clear_error (error); + success = gvdb_table_write_contents (gvdb, filename, FALSE, error); + } + + g_hash_table_unref (gvdb); + + return success; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/common/dconf-gvdb-utils.h new/dconf-0.40.0/common/dconf-gvdb-utils.h --- old/dconf-0.38.0/common/dconf-gvdb-utils.h 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/common/dconf-gvdb-utils.h 2021-03-13 02:05:23.390553000 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright ?? 2010 Codethink Limited + * Copyright ?? 2012 Canonical Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * Author: Ryan Lortie <de...@desrt.ca> + */ + +#ifndef __dconf_gvdb_utils_h__ +#define __dconf_gvdb_utils_h__ + +#include "../gvdb/gvdb-reader.h" +#include "./dconf-changeset.h" + +DConfChangeset * dconf_gvdb_utils_changeset_from_table (GvdbTable *table); +DConfChangeset * dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, + gboolean *file_missing, + GError **error); +GHashTable * dconf_gvdb_utils_table_from_changeset (DConfChangeset *database); +gboolean dconf_gvdb_utils_write_file (const gchar *filename, + DConfChangeset *database, + GError **error); + +#endif /* __dconf_gvdb_utils_h__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/common/dconf-paths.h new/dconf-0.40.0/common/dconf-paths.h --- old/dconf-0.38.0/common/dconf-paths.h 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/common/dconf-paths.h 2021-03-13 02:05:23.390553000 +0100 @@ -23,6 +23,8 @@ #include <glib.h> +G_BEGIN_DECLS + gboolean dconf_is_path (const gchar *string, GError **error); gboolean dconf_is_key (const gchar *string, @@ -37,4 +39,6 @@ gboolean dconf_is_rel_dir (const gchar *string, GError **error); +G_END_DECLS + #endif /* __dconf_paths_h__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/common/meson.build new/dconf-0.40.0/common/meson.build --- old/dconf-0.38.0/common/meson.build 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/common/meson.build 2021-03-13 02:05:23.390553000 +0100 @@ -15,32 +15,19 @@ 'dconf-changeset.c', 'dconf-error.c', 'dconf-paths.c', + 'dconf-gvdb-utils.c', ) libdconf_common = static_library( 'dconf-common', sources: sources, include_directories: top_inc, - dependencies: glib_dep, + dependencies: [glib_dep, libgvdb_dep], c_args: dconf_c_args, pic: true, ) libdconf_common_dep = declare_dependency( - dependencies: glib_dep, - link_whole: libdconf_common, -) - -libdconf_common_hidden = static_library( - 'dconf-common-hidden', - sources: sources, - include_directories: top_inc, - dependencies: glib_dep, - c_args: dconf_c_args + cc.get_supported_arguments('-fvisibility=hidden'), - pic: true, -) - -libdconf_common_hidden_dep = declare_dependency( - dependencies: glib_dep, - link_with: libdconf_common_hidden, + dependencies: [glib_dep, libgvdb_dep], + link_with: libdconf_common, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/engine/dconf-engine.c new/dconf-0.40.0/engine/dconf-engine.c --- old/dconf-0.38.0/engine/dconf-engine.c 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/engine/dconf-engine.c 2021-03-13 02:05:23.390553000 +0100 @@ -24,6 +24,7 @@ #include "../common/dconf-enums.h" #include "../common/dconf-paths.h" +#include "../common/dconf-gvdb-utils.h" #include "../gvdb/gvdb-reader.h" #include <string.h> #include <stdlib.h> @@ -822,6 +823,54 @@ return list; } +static gboolean +dconf_engine_dir_has_writable_contents (DConfEngine *engine, + const gchar *dir) +{ + DConfChangeset *database; + GHashTable *current_state; + + /* Read the on disk state */ + if (engine->n_sources == 0 || !engine->sources[0]->writable) + // If there are no writable sources, there won't be any pending writes either + return FALSE; + + dconf_engine_acquire_sources (engine); + database = dconf_gvdb_utils_changeset_from_table (engine->sources[0]->values); + dconf_engine_release_sources (engine); + + /* Apply pending and in_flight changes to the on disk state */ + dconf_engine_lock_queue (engine); + + if (engine->in_flight != NULL) + dconf_changeset_change (database, engine->in_flight); + + if (engine->pending != NULL) + { + /** + * We don't want to seal the pending changeset because it may still be changed, + * and sealing the changeset would be a side effect of passing engine->pending + * directly into dconf_changeset_change. + */ + DConfChangeset *changes = dconf_changeset_filter_changes (database, engine->pending); + if (changes != NULL) + { + dconf_changeset_change (database, changes); + dconf_changeset_unref (changes); + } + } + + dconf_engine_unlock_queue (engine); + + /* Check if there are writable contents at the given directory in the current state */ + current_state = dconf_gvdb_utils_table_from_changeset (database); + gboolean result = g_hash_table_contains (current_state, dir); + + g_hash_table_unref (current_state); + dconf_changeset_unref (database); + return result; +} + typedef void (* DConfEngineCallHandleCallback) (DConfEngine *engine, gpointer handle, GVariant *parameter, @@ -1129,6 +1178,34 @@ */ static void dconf_engine_manage_queue (DConfEngine *engine); +/** + * a #DConfChangesetPredicate which determines whether the given path and + * value is already present in the given engine. "Already present" means + * that setting that path to that value would have no effect on the + * engine, including for directory resets. + */ +static gboolean +dconf_engine_path_has_value_predicate (const gchar *path, + GVariant *new_value, + gpointer user_data) +{ + DConfEngine *engine = user_data; + + // Path reset are handled specially + if (g_str_has_suffix (path, "/")) + return !dconf_engine_dir_has_writable_contents (engine, path); + + g_autoptr(GVariant) current_value = dconf_engine_read ( + engine, + DCONF_READ_USER_VALUE, + NULL, + path + ); + return ((current_value == NULL && new_value == NULL) || + (current_value != NULL && new_value != NULL && + g_variant_equal (current_value, new_value))); +} + static void dconf_engine_emit_changes (DConfEngine *engine, DConfChangeset *changeset, @@ -1208,6 +1285,7 @@ G_VARIANT_TYPE ("(s)"), sizeof (OutstandingChange)); oc->change = engine->in_flight = g_steal_pointer (&engine->pending); + dconf_changeset_seal (engine->in_flight); parameters = dconf_engine_prepare_change (engine, oc->change); @@ -1273,6 +1351,10 @@ if (dconf_changeset_is_empty (changeset)) return TRUE; + gboolean has_no_effect = dconf_changeset_all (changeset, + dconf_engine_path_has_value_predicate, + engine); + if (!dconf_engine_changeset_changes_only_writable_keys (engine, changeset, error)) return FALSE; @@ -1297,7 +1379,8 @@ dconf_engine_unlock_queue (engine); /* Emit the signal after dropping the lock to avoid deadlock on re-entry. */ - dconf_engine_emit_changes (engine, changeset, origin_tag); + if (!has_no_effect) + dconf_engine_emit_changes (engine, changeset, origin_tag); return TRUE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/gsettings/abicheck.sh new/dconf-0.40.0/gsettings/abicheck.sh --- old/dconf-0.38.0/gsettings/abicheck.sh 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/gsettings/abicheck.sh 1970-01-01 01:00:00.000000000 +0100 @@ -1,26 +0,0 @@ -#!/bin/sh - -# The following checks that gsettings/libdconfsettings.so only has -# dconf_* symbols. -# -# We also make sure to ignore gcov symbols included when building with -# --coverage, which usually means the following: -# -# __gcov_error_file -# __gcov_master -# __gcov_sort_n_vals -# __gcov_var -# -# And starting with gcc-9, also this one: -# -# mangle_path - -${NM:-nm} --dynamic --defined-only $GSETTINGS_LIB > public-abi - -test "`\ - cat public-abi | \ - cut -f 3 -d ' ' | \ - grep -v ^_ | \ - grep -v ^mangle_path | \ - grep -v ^g_io_module | \ - wc -l`" -eq 0 && rm public-abi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/gsettings/meson.build new/dconf-0.40.0/gsettings/meson.build --- old/dconf-0.38.0/gsettings/meson.build 2020-09-13 03:10:05.902783900 +0200 +++ new/dconf-0.40.0/gsettings/meson.build 2021-03-13 02:05:23.390553000 +0100 @@ -1,32 +1,19 @@ -# We use the libraries directly, as the dependency objects use -# link_whole; this avoids the gsettings backend module exposing -# symbols other than g_io_module_* backend_deps = [ - libdconf_common_hidden, - libdconf_gdbus_thread, + libdconf_common_dep, + libdconf_gdbus_thread_dep, ] +symbol_map = join_paths(meson.current_source_dir(), 'symbol.map') +ldflags = cc.get_supported_link_arguments('-Wl,--version-script,@0@'.format(symbol_map)) + libdconf_settings = shared_library( 'dconfsettings', sources: 'dconfsettingsbackend.c', include_directories: top_inc, - link_with: backend_deps, - dependencies: gio_dep, + dependencies: backend_deps, c_args: dconf_c_args, + link_args: ldflags, + link_depends: symbol_map, install: true, install_dir: gio_module_dir, ) - -envs = test_env + [ - 'G_TEST_SRCDIR=' + meson.current_source_dir(), - 'G_TEST_BUILDDIR=' + meson.current_build_dir(), - 'GSETTINGS_LIB=' + libdconf_settings.full_path(), -] - -unit_test = 'abicheck' - -test( - unit_test, - find_program(unit_test + '.sh'), - env: envs, -) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/gsettings/symbol.map new/dconf-0.40.0/gsettings/symbol.map --- old/dconf-0.38.0/gsettings/symbol.map 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/gsettings/symbol.map 2021-03-13 02:05:23.390553000 +0100 @@ -0,0 +1,10 @@ +{ +global: + g_io_module_load; + g_io_module_unload; + g_io_module_query; + environ; + __progname; +local: + *; +}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/gsettings/symbols.txt new/dconf-0.40.0/gsettings/symbols.txt --- old/dconf-0.38.0/gsettings/symbols.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/gsettings/symbols.txt 2021-03-13 02:05:23.390553000 +0100 @@ -0,0 +1,3 @@ +g_io_module_load +g_io_module_query +g_io_module_unload diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/meson.build new/dconf-0.40.0/meson.build --- old/dconf-0.38.0/meson.build 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/meson.build 2021-03-13 02:05:23.393886300 +0100 @@ -1,6 +1,6 @@ project( 'dconf', ['c'], - version: '0.38.0', + version: '0.40.0', license: 'LGPL2.1+', meson_version: '>= 0.47.0', ) @@ -48,6 +48,20 @@ gio_module_dir = gio_dep.get_pkgconfig_variable('giomoduledir', define_variable: ['libdir', dconf_libdir]) dbus_session_service_dir = dependency('dbus-1').get_pkgconfig_variable('session_bus_services_dir', define_variable: ['datadir', dconf_datadir]) +systemd_userunitdir = get_option('systemduserunitdir') + +if systemd_userunitdir == '' + systemd_dep = dependency('systemd', required: false) + + if systemd_dep.found() + systemd_userunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir') + else + # Fall back to the upstream default. + # Note that this is always 'lib', even if libdir is something else + systemd_userunitdir = join_paths(dconf_prefix, 'lib', 'systemd', 'user') + endif +endif + enable_bash_completion = get_option('bash_completion') if enable_bash_completion bash_completion_dep = dependency('bash-completion') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/meson_options.txt new/dconf-0.40.0/meson_options.txt --- old/dconf-0.38.0/meson_options.txt 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/meson_options.txt 2021-03-13 02:05:23.393886300 +0100 @@ -2,3 +2,4 @@ option('man', type: 'boolean', value: true, description: 'generate man pages') option('gtk_doc', type: 'boolean', value: false, description: 'use gtk-doc to build documentation') option('vapi', type: 'boolean', value: true, description: 'install dconf client vapi') +option('systemduserunitdir', type: 'string', value: '', description: 'override systemd user unit directory') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/service/ca.desrt.dconf.service.in new/dconf-0.40.0/service/ca.desrt.dconf.service.in --- old/dconf-0.38.0/service/ca.desrt.dconf.service.in 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/service/ca.desrt.dconf.service.in 2021-03-13 02:05:23.393886300 +0100 @@ -1,3 +1,4 @@ [D-BUS Service] Name=ca.desrt.dconf Exec=@libexecdir@/dconf-service +SystemdService=dconf.service diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/service/dconf-gvdb-utils.c new/dconf-0.40.0/service/dconf-gvdb-utils.c --- old/dconf-0.38.0/service/dconf-gvdb-utils.c 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/service/dconf-gvdb-utils.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,219 +0,0 @@ -/* - * Copyright ?? 2010 Codethink Limited - * Copyright ?? 2012 Canonical Limited - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - * Author: Ryan Lortie <de...@desrt.ca> - */ - -#include "config.h" - -#include "dconf-gvdb-utils.h" - -#include "../common/dconf-paths.h" -#include "../gvdb/gvdb-builder.h" -#include "../gvdb/gvdb-reader.h" - -#include <errno.h> -#include <glib.h> -#include <glib/gstdio.h> -#include <string.h> - -DConfChangeset * -dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, - gboolean *file_missing, - GError **error) -{ - DConfChangeset *database; - GError *my_error = NULL; - GvdbTable *table = NULL; - gchar *contents; - gsize size; - - if (g_file_get_contents (filename, &contents, &size, &my_error)) - { - GBytes *bytes; - - bytes = g_bytes_new_take (contents, size); - table = gvdb_table_new_from_bytes (bytes, FALSE, &my_error); - g_bytes_unref (bytes); - } - - /* It is perfectly fine if the file does not exist -- then it's - * just empty. - */ - if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) - g_clear_error (&my_error); - - /* Otherwise, we should report errors to prevent ourselves from - * overwriting the database in other situations... - */ - if (g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_INVAL)) - { - /* Move the database to a backup file, warn and continue with a new - * database. The alternative is erroring out and exiting the daemon, - * which leaves the user???s session essentially unusable. - * - * The code to find an unused backup filename is racy, but this is an - * error handling path. Who cares. */ - g_autofree gchar *backup_filename = NULL; - guint i; - - for (i = 0; - i < G_MAXUINT && - (backup_filename == NULL || g_file_test (backup_filename, G_FILE_TEST_EXISTS)); - i++) - { - g_free (backup_filename); - backup_filename = g_strdup_printf ("%s~%u", filename, i); - } - - if (g_rename (filename, backup_filename) != 0) - g_warning ("Error renaming corrupt database from ???%s??? to ???%s???: %s", - filename, backup_filename, g_strerror (errno)); - else - g_warning ("Database ???%s??? was corrupt: moved it to ???%s??? and created an empty replacement", - filename, backup_filename); - - g_clear_error (&my_error); - } - else if (my_error) - { - g_propagate_prefixed_error (error, my_error, "Cannot open dconf database: "); - return NULL; - } - - /* Only allocate once we know we are in a non-error situation */ - database = dconf_changeset_new_database (NULL); - - /* Fill the table up with the initial state */ - if (table != NULL) - { - gchar **names; - gsize n_names; - gsize i; - - names = gvdb_table_get_names (table, &n_names); - for (i = 0; i < n_names; i++) - { - if (dconf_is_key (names[i], NULL)) - { - GVariant *value; - - value = gvdb_table_get_value (table, names[i]); - - if (value != NULL) - { - dconf_changeset_set (database, names[i], value); - g_variant_unref (value); - } - } - - g_free (names[i]); - } - - gvdb_table_free (table); - g_free (names); - } - - if (file_missing) - *file_missing = (table == NULL); - - return database; -} - -static GvdbItem * -dconf_gvdb_utils_get_parent (GHashTable *table, - const gchar *key) -{ - GvdbItem *grandparent, *parent; - gchar *parent_name; - gint len; - - if (g_str_equal (key, "/")) - return NULL; - - len = strlen (key); - if (key[len - 1] == '/') - len--; - - while (key[len - 1] != '/') - len--; - - parent_name = g_strndup (key, len); - parent = g_hash_table_lookup (table, parent_name); - - if (parent == NULL) - { - parent = gvdb_hash_table_insert (table, parent_name); - - grandparent = dconf_gvdb_utils_get_parent (table, parent_name); - - if (grandparent != NULL) - gvdb_item_set_parent (parent, grandparent); - } - - g_free (parent_name); - - return parent; -} - -static gboolean -dconf_gvdb_utils_add_key (const gchar *path, - GVariant *value, - gpointer user_data) -{ - GHashTable *gvdb = user_data; - GvdbItem *item; - - g_assert (g_hash_table_lookup (gvdb, path) == NULL); - item = gvdb_hash_table_insert (gvdb, path); - gvdb_item_set_parent (item, dconf_gvdb_utils_get_parent (gvdb, path)); - gvdb_item_set_value (item, value); - - return TRUE; -} - -gboolean -dconf_gvdb_utils_write_file (const gchar *filename, - DConfChangeset *database, - GError **error) -{ - GHashTable *gvdb; - gboolean success; - - gvdb = gvdb_hash_table_new (NULL, NULL); - dconf_changeset_all (database, dconf_gvdb_utils_add_key, gvdb); - success = gvdb_table_write_contents (gvdb, filename, FALSE, error); - - if (!success) - { - gchar *dirname; - - /* Maybe it failed because the directory doesn't exist. Try - * again, after mkdir(). - */ - dirname = g_path_get_dirname (filename); - g_mkdir_with_parents (dirname, 0700); - g_free (dirname); - - g_clear_error (error); - success = gvdb_table_write_contents (gvdb, filename, FALSE, error); - } - - g_hash_table_unref (gvdb); - - return success; -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/service/dconf-gvdb-utils.h new/dconf-0.40.0/service/dconf-gvdb-utils.h --- old/dconf-0.38.0/service/dconf-gvdb-utils.h 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/service/dconf-gvdb-utils.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,33 +0,0 @@ -/* - * Copyright ?? 2010 Codethink Limited - * Copyright ?? 2012 Canonical Limited - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - * Author: Ryan Lortie <de...@desrt.ca> - */ - -#ifndef __dconf_gvdb_utils_h__ -#define __dconf_gvdb_utils_h__ - -#include "../common/dconf-changeset.h" - -DConfChangeset * dconf_gvdb_utils_read_and_back_up_file (const gchar *filename, - gboolean *file_missing, - GError **error); -gboolean dconf_gvdb_utils_write_file (const gchar *filename, - DConfChangeset *database, - GError **error); - -#endif /* __dconf_gvdb_utils_h__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/service/dconf-writer.c new/dconf-0.40.0/service/dconf-writer.c --- old/dconf-0.38.0/service/dconf-writer.c 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/service/dconf-writer.c 2021-03-13 02:05:23.393886300 +0100 @@ -23,7 +23,7 @@ #include "dconf-writer.h" #include "../shm/dconf-shm.h" -#include "dconf-gvdb-utils.h" +#include "../common/dconf-gvdb-utils.h" #include "dconf-generated.h" #include "dconf-blame.h" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/service/dconf.service.in new/dconf-0.40.0/service/dconf.service.in --- old/dconf-0.38.0/service/dconf.service.in 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/service/dconf.service.in 2021-03-13 02:05:23.393886300 +0100 @@ -0,0 +1,8 @@ +[Unit] +Description=User preferences database +Documentation=man:dconf-service(1) + +[Service] +ExecStart=@libexecdir@/dconf-service +Type=dbus +BusName=ca.desrt.dconf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/service/meson.build new/dconf-0.40.0/service/meson.build --- old/dconf-0.38.0/service/meson.build 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/service/meson.build 2021-03-13 02:05:23.393886300 +0100 @@ -10,9 +10,17 @@ install_dir: dbus_session_service_dir, ) +systemd_service = 'dconf.service' + +configure_file( + input: systemd_service + '.in', + output: systemd_service, + configuration: service_conf, + install_dir: systemd_userunitdir, +) + lib_sources = [ 'dconf-blame.c', - 'dconf-gvdb-utils.c', 'dconf-keyfile-writer.c', 'dconf-service.c', 'dconf-shm-writer.c', @@ -36,7 +44,7 @@ sources: lib_sources, include_directories: top_inc, c_args: dconf_c_args, - dependencies: gio_unix_dep, + dependencies: [gio_unix_dep, libdconf_common_dep], link_with: [ libdconf_common, libdconf_shm, @@ -46,7 +54,7 @@ libdconf_service_dep = declare_dependency( link_with: libdconf_service, - dependencies: gio_unix_dep, + dependencies: [gio_unix_dep, libdconf_common_dep], sources: dconf_generated, ) @@ -55,7 +63,7 @@ sources, include_directories: top_inc, c_args: dconf_c_args, - dependencies: gio_unix_dep, + dependencies: [gio_unix_dep, libdconf_common_dep], link_with: libdconf_service, install: true, install_dir: dconf_libexecdir, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/tests/abicheck.sh new/dconf-0.40.0/tests/abicheck.sh --- old/dconf-0.38.0/tests/abicheck.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/dconf-0.40.0/tests/abicheck.sh 2021-03-13 02:05:23.393886300 +0100 @@ -0,0 +1,35 @@ +#!/bin/sh + +# The following checks that a given binary only defines the symbols +# specified +# +# We also make sure to ignore gcov symbols included when building with +# --coverage, which usually means the following: +# +# __gcov_error_file +# __gcov_master +# __gcov_sort_n_vals +# __gcov_var +# +# And starting with gcc-9, also this one: +# +# mangle_path + +set -x + +if test $# != 2; then + echo " Usage: $0 <binary> <symbol_file>" + echo " symbol_file is a file where each line is the name of an exported symbol" + exit 1 +fi + +BINARY="$1" +SYMBOL_FILE="$2" + +${NM:-nm} --dynamic --defined-only "$BINARY" | \ + cut -f 3 -d ' ' | \ + grep -v ^_ | \ + grep -v ^environ | \ + grep -v __progname | \ + grep -v ^mangle_path | \ + diff "$SYMBOL_FILE" - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/tests/engine.c new/dconf-0.40.0/tests/engine.c --- old/dconf-0.38.0/tests/engine.c 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/tests/engine.c 2021-03-13 02:05:23.393886300 +0100 @@ -1466,7 +1466,7 @@ static void test_change_fast (void) { - DConfChangeset *empty, *good_write, *bad_write, *very_good_write, *slightly_bad_write; + DConfChangeset *empty, *good_write, *good_write2, *bad_write, *very_good_write, *slightly_bad_write; GvdbTable *table, *locks; DConfEngine *engine; gboolean success; @@ -1483,6 +1483,7 @@ empty = dconf_changeset_new (); good_write = dconf_changeset_new_write ("/value", g_variant_new_string ("value")); + good_write2 = dconf_changeset_new_write ("/value2", g_variant_new_string ("value2")); bad_write = dconf_changeset_new_write ("/locked", g_variant_new_string ("value")); very_good_write = dconf_changeset_new_write ("/value", g_variant_new_string ("value")); dconf_changeset_set (very_good_write, "/to-reset", NULL); @@ -1517,6 +1518,15 @@ dconf_mock_dbus_assert_no_async (); g_assert_cmpstr (change_log->str, ==, ""); + /* Verify that value is unset initially */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value"); + g_assert (value == NULL); + + /* Verify that value2 is unset initially */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value2"); + g_assert (value == NULL); + + /* change /value */ success = dconf_engine_change_fast (engine, good_write, NULL, &error); g_assert_no_error (error); g_assert (success); @@ -1530,7 +1540,48 @@ g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "value"); g_variant_unref (value); - /* Fail the attempted write. This should cause a warning and a change. */ + /* Repeat the same write for /value (which is already in the in_flight queue) */ + success = dconf_engine_change_fast (engine, good_write, NULL, &error); + g_assert_no_error (error); + g_assert (success); + + /* Verify that /value is (still) set */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value"); + g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "value"); + g_variant_unref (value); + + /* That should not have emitted a synthetic change event, since the (local) value did not change */ + g_assert_cmpstr (change_log->str, ==, ""); + g_string_set_size (change_log, 0); + + /* change /value2 */ + success = dconf_engine_change_fast (engine, good_write2, NULL, &error); + g_assert_no_error (error); + g_assert (success); + + /* That should have emitted a synthetic change event */ + g_assert_cmpstr (change_log->str, ==, "/value2:1::nil;"); + g_string_set_size (change_log, 0); + + /* Verify that /value2 is set */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value2"); + g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "value2"); + g_variant_unref (value); + + /* change /value2 a second time */ + success = dconf_engine_change_fast (engine, good_write2, NULL, &error); + g_assert_no_error (error); + g_assert (success); + + /* That should not have emitted a synthetic change event because the (local) value didn't change */ + g_assert_cmpstr (change_log->str, ==, ""); + + /* Verify that /value2 is still set */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value2"); + g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "value2"); + g_variant_unref (value); + + /* Fail the first attempted write. This should cause a warning and a signal. */ error = g_error_new_literal (G_FILE_ERROR, G_FILE_ERROR_NOENT, "something failed"); dconf_mock_dbus_async_reply (NULL, error); g_clear_error (&error); @@ -1539,8 +1590,25 @@ assert_pop_message ("dconf", G_LOG_LEVEL_WARNING, "failed to commit changes to dconf: something failed"); - /* Verify that the value became unset due to the failure */ - value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "value"); + /* Verify that /value is still set (because the second write is in progress) */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value"); + g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "value"); + g_variant_unref (value); + + /* Verify that /value2 is still set because the write is in progress */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value2"); + g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "value2"); + g_variant_unref (value); + + /* Now allow the second set of writes to succeed */ + dconf_mock_dbus_async_reply (g_variant_new ("(s)", "tag"), NULL); + + /* Verify that /value became unset due to the in flight queue clearing */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value"); + g_assert (value == NULL); + + /* Verify that /value2 became unset due to the in flight queue clearing */ + value = dconf_engine_read (engine, DCONF_READ_FLAGS_NONE, NULL, "/value2"); g_assert (value == NULL); /* Now try a successful write */ @@ -1619,6 +1687,91 @@ change_log = NULL; } +/** + * Tests that dconf_engine_change_fast() emits local optimistic change + * notifications in the right circumstances + */ +static void +test_change_fast_redundant (void) +{ + DConfChangeset *change; + DConfEngine *engine; + change_log = g_string_new (NULL); + + // Initialise an empty engine + engine = dconf_engine_new (SRCDIR "/profile/dos", NULL, NULL); + + // Send an empty changeset, which has no effect + change = dconf_changeset_new (); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, ""); + + // Reset the root directory, which has no effect since the database is empty + change = dconf_changeset_new_write ("/", NULL); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, ""); + + // Set apple to NULL, which has no effect because it was already unset + change = dconf_changeset_new_write ("/apple", NULL); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, ""); + + // Set apple to apple + change = dconf_changeset_new_write ("/apple", g_variant_new_string ("apple")); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, "/apple:1::nil;"); + g_string_set_size (change_log, 0); + + // Set apple to apple, which has no effect because it is the same as the old value + change = dconf_changeset_new_write ("/apple", g_variant_new_string ("apple")); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, ""); + g_string_set_size (change_log, 0); + + // Set apple to orange, which has an effect because it is different to the old value + change = dconf_changeset_new_write ("/apple", g_variant_new_string ("orange")); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, "/apple:1::nil;"); + g_string_set_size (change_log, 0); + + // Set apple to NULL, which has an effect because it was previously set + change = dconf_changeset_new_write ("/apple", NULL); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, "/apple:1::nil;"); + g_string_set_size (change_log, 0); + + // Set apple to apple + change = dconf_changeset_new_write ("/apple", g_variant_new_string ("apple")); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, "/apple:1::nil;"); + g_string_set_size (change_log, 0); + + // Reset the root directory, which has an effect since the database is not empty + change = dconf_changeset_new_write ("/", NULL); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, "/:1::nil;"); + g_string_set_size (change_log, 0); + + // Reset the root directory again, which has no effect since the database is empty + change = dconf_changeset_new_write ("/", NULL); + dconf_engine_change_fast (engine, change, NULL, NULL); + dconf_changeset_unref (change); + g_assert_cmpstr (change_log->str, ==, ""); + + dconf_engine_unref (engine); + g_string_free (change_log, TRUE); + change_log = NULL; +} + static GError *change_sync_error; static GVariant *change_sync_result; @@ -2087,6 +2240,7 @@ g_test_add_func ("/engine/watch/fast/short_lived", test_watch_fast_short_lived_subscriptions); g_test_add_func ("/engine/watch/sync", test_watch_sync); g_test_add_func ("/engine/change/fast", test_change_fast); + g_test_add_func ("/engine/change/fast_redundant", test_change_fast_redundant); g_test_add_func ("/engine/change/sync", test_change_sync); g_test_add_func ("/engine/signals", test_signals); g_test_add_func ("/engine/sync", test_sync); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dconf-0.38.0/tests/meson.build new/dconf-0.40.0/tests/meson.build --- old/dconf-0.38.0/tests/meson.build 2020-09-13 03:10:05.906117200 +0200 +++ new/dconf-0.40.0/tests/meson.build 2021-03-13 02:05:23.393886300 +0100 @@ -48,6 +48,23 @@ test(unit_test[0], exe, is_parallel: false, env: envs) endforeach +symbol_test = find_program('abicheck.sh') + +abi_tests = [ + ['gsettings', libdconf_settings, files('../gsettings/symbols.txt')[0]], + ['libdconf', libdconf, files('../client/symbols.txt')[0]], +] + +foreach abi_test: abi_tests + test( + abi_test[0], + symbol_test, + env: envs, + args: [abi_test[1].full_path(), abi_test[2]], + ) +endforeach + + python3 = find_program('python3', required: false) dbus_daemon = find_program('dbus-daemon', required: false)