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)
 

Reply via email to