[devhelp/wip/gsettings-in-lib] gsettings: implement DhDconfMigration utility class



commit 386a6a5bb4015d762f438a036beddb0e26585c70
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Thu Mar 8 14:10:26 2018 +0100

    gsettings: implement DhDconfMigration utility class

 configure.ac                 |    2 +-
 devhelp/Makefile.am          |    2 +
 devhelp/dh-dconf-migration.c |  138 ++++++++++++++++++++++++++++++++++++++++++
 devhelp/dh-dconf-migration.h |   42 +++++++++++++
 docs/reference/Makefile.am   |    1 +
 po/POTFILES.in               |    1 +
 6 files changed, 185 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index b121ee8..88092ca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,7 +62,7 @@ LT_LIB_M
 AX_REQUIRE_DEFINED([AX_PKG_CHECK_MODULES])
 AX_PKG_CHECK_MODULES([DEVHELP],
                     [gio-2.0 >= 2.40  gtk+-3.0 >= 3.22  webkit2gtk-4.0 >= 2.19.2],
-                    [gsettings-desktop-schemas])
+                    [gsettings-desktop-schemas  dconf])
 
 # i18n stuff
 AM_GNU_GETTEXT([external])
diff --git a/devhelp/Makefile.am b/devhelp/Makefile.am
index 2b8fe0f..679a366 100644
--- a/devhelp/Makefile.am
+++ b/devhelp/Makefile.am
@@ -34,6 +34,7 @@ libdevhelp_public_c_files =           \
        $(NULL)
 
 libdevhelp_private_headers =           \
+       dh-dconf-migration.h            \
        dh-error.h                      \
        dh-parser.h                     \
        dh-search-context.h             \
@@ -42,6 +43,7 @@ libdevhelp_private_headers =          \
        $(NULL)
 
 libdevhelp_private_c_files =           \
+       dh-dconf-migration.c            \
        dh-error.c                      \
        dh-parser.c                     \
        dh-search-context.c             \
diff --git a/devhelp/dh-dconf-migration.c b/devhelp/dh-dconf-migration.c
new file mode 100644
index 0000000..82355ea
--- /dev/null
+++ b/devhelp/dh-dconf-migration.c
@@ -0,0 +1,138 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2018 Sébastien Wilmet <swilmet gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dh-dconf-migration.h"
+#include <dconf.h>
+
+/* #DhDconfMigration is a utility class to copy the value of dconf keys from old
+ * paths to new paths.
+ *
+ * You'll probably need to add a "migration-done" #GSettings key to know if the
+ * migration has already been done or not (either with a boolean, or an integer
+ * if you plan to have other migrations in the future).
+ *
+ * Use-case examples:
+ * - When a project is renamed. The old #GSettings schema may no longer be
+ *   installed, so it is not possible to use the #GSettings API to retrieve the
+ *   values at the old locations. But the values are still stored in the dconf
+ *   database.
+ * - Be able to do refactorings in the #GSettings schema without users losing
+ *   their settings when *upgrading* to a new version (doesn't work when
+ *   downgrading).
+ * - When a library uses #GSettings, with parallel-installability for different
+ *   major versions, each major version provides a different #GSettings schema,
+ *   but when upgrading to a new major version we don't want all the users to
+ *   lose their settings. An alternative is for the library to install only
+ *   relocatable schemas, relocated to an old common path (if all the keys of
+ *   that schema are still compatible). When a schema (or sub-schema) becomes
+ *   incompatible, the compatible keys can be migrated individually with
+ *   #DhDconfMigration.
+ */
+
+struct _DhDconfMigration {
+        DConfClient *client;
+};
+
+DhDconfMigration *
+_dh_dconf_migration_new (void)
+{
+        DhDconfMigration *migration;
+
+        migration = g_new0 (DhDconfMigration, 1);
+        migration->client = dconf_client_new ();
+
+        return migration;
+}
+
+void
+_dh_dconf_migration_free (DhDconfMigration *migration)
+{
+        if (migration == NULL)
+                return;
+
+        dconf_client_sync (migration->client);
+
+        g_object_unref (migration->client);
+        g_free (migration);
+}
+
+/*
+ * _dh_dconf_migration_migrate_key:
+ * @migration: a #DhDconfMigration.
+ * @new_key_path: the dconf path to the new key.
+ * @first_old_key_path: the dconf path to the first old key.
+ * @...: %NULL-terminated list of strings containing the dconf paths to the old
+ *   keys (usually from most recent to the oldest).
+ *
+ * Copies a value from an old path to a new path. The values on the old paths
+ * are not reset, it is just a copy.
+ *
+ * The function loops on the old key paths, in the same order as provided; as
+ * soon as an old key contains a value, that value is copied to @new_key_path
+ * and the function returns. Which means that, usually, all the keys must be
+ * provided in reverse chronological order.
+ */
+void
+_dh_dconf_migration_migrate_key (DhDconfMigration *migration,
+                                 const gchar      *new_key_path,
+                                 const gchar      *first_old_key_path,
+                                 ...)
+{
+        va_list old_key_paths;
+        GVariant *value;
+
+        g_return_if_fail (migration != NULL);
+        g_return_if_fail (new_key_path != NULL);
+        g_return_if_fail (first_old_key_path != NULL);
+
+        va_start (old_key_paths, first_old_key_path);
+
+        value = dconf_client_read (migration->client, first_old_key_path);
+
+        while (value == NULL) {
+                const gchar *next_old_key_path;
+
+                next_old_key_path = va_arg (old_key_paths, const gchar *);
+                if (next_old_key_path == NULL)
+                        break;
+
+                value = dconf_client_read (migration->client, next_old_key_path);
+        }
+
+        if (value != NULL) {
+                GError *error = NULL;
+
+                /* The GVariant type is not checked against the new GSettings
+                 * schema. If we write a value with an incompatible type by
+                 * mistake, no problem, GSettings will take the default value
+                 * from the schema (without printing a warning).
+                 */
+                dconf_client_write_fast (migration->client, new_key_path, value, &error);
+
+                if (error != NULL) {
+                        g_warning ("Error when migrating dconf key %s: %s",
+                                   new_key_path,
+                                   error->message);
+                        g_clear_error (&error);
+                }
+
+                g_variant_unref (value);
+        }
+
+        va_end (old_key_paths);
+}
diff --git a/devhelp/dh-dconf-migration.h b/devhelp/dh-dconf-migration.h
new file mode 100644
index 0000000..4bcfdcd
--- /dev/null
+++ b/devhelp/dh-dconf-migration.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2018 Sébastien Wilmet <swilmet gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DH_DCONF_MIGRATION_H
+#define DH_DCONF_MIGRATION_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _DhDconfMigration DhDconfMigration;
+
+G_GNUC_INTERNAL
+DhDconfMigration *      _dh_dconf_migration_new         (void);
+
+G_GNUC_INTERNAL
+void                    _dh_dconf_migration_free        (DhDconfMigration *migration);
+
+G_GNUC_INTERNAL
+void                    _dh_dconf_migration_migrate_key (DhDconfMigration *migration,
+                                                         const gchar      *new_key_path,
+                                                         const gchar      *first_old_key_path,
+                                                         ...);
+
+G_END_DECLS
+
+#endif /* DH_DCONF_MIGRATION_H */
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 9a7db47..a515f71 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -47,6 +47,7 @@ EXTRA_HFILES = \
 # Header files or dirs to ignore when scanning. Use base file/dir names
 # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
 IGNORE_HFILES = \
+       dh-dconf-migration.h \
        dh-error.h \
        dh-parser.h \
        dh-search-context.h \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 85cd99b..23cb03b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,6 +8,7 @@ devhelp/dh-book.c
 devhelp/dh-book-manager.c
 devhelp/dh-book-tree.c
 devhelp/dh-completion.c
+devhelp/dh-dconf-migration.c
 devhelp/dh-error.c
 devhelp/dh-init.c
 devhelp/dh-keyword-model.c


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]