[dconf: 2/3] bin: Add an option to ignore changes to locked keys during load
- From: Daniel Playfair Cal <danielplayfaircal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf: 2/3] bin: Add an option to ignore changes to locked keys during load
- Date: Tue, 12 Feb 2019 22:16:21 +0000 (UTC)
commit c963f9eec8d72d6e17099d456330cd988294c0af
Author: Tomasz Miąsko <tomasz miasko gmail com>
Date: Sat Feb 9 00:00:00 2019 +0000
bin: Add an option to ignore changes to locked keys during load
If load command attempts to change one of non-writable keys, the whole
operation fails with an error and no changes are made. Add an `-f`
option to the load command that skips non-writable keys and proceeds
with remaining changes.
Closes issue #1.
bin/dconf.c | 43 +++++++++++++++++++++++++++++++++++--------
docs/dconf-tool.xml | 9 ++++++++-
tests/test-dconf.py | 25 +++++++++++++++++++++++--
3 files changed, 66 insertions(+), 11 deletions(-)
---
diff --git a/bin/dconf.c b/bin/dconf.c
index 8e3f060..c91f82a 100644
--- a/bin/dconf.c
+++ b/bin/dconf.c
@@ -578,14 +578,29 @@ keyfile_foreach (GKeyFile *kf,
return TRUE;
}
+typedef struct {
+ DConfClient *client;
+ DConfChangeset *changeset;
+ gboolean force;
+} LoadContext;
+
static void
changeset_set (const gchar *path,
GVariant *value,
gpointer user_data)
{
- DConfChangeset *changeset = user_data;
+ LoadContext *ctx = user_data;
+
+ /* When force option is used, ignore changes made to non-writeable keys to
+ * avoid rejecting the whole changeset.
+ */
+ if (ctx->force && !dconf_client_is_writable (ctx->client, path))
+ {
+ g_fprintf (stderr, "warning: ignored non-writable key '%s'\n", path);
+ return;
+ }
- dconf_changeset_set (changeset, path, value);
+ dconf_changeset_set (ctx->changeset, path, value);
}
static gboolean
@@ -593,27 +608,39 @@ dconf_load (const gchar **argv,
GError **error)
{
const gchar *dir;
+ gint index = 0;
+ gboolean force = FALSE;
g_autoptr(GError) local_error = NULL;
g_autoptr(GKeyFile) kf = NULL;
g_autoptr(DConfChangeset) changeset = NULL;
g_autoptr (DConfClient) client = NULL;
- dir = argv[0];
+ if (argv[index] != NULL && strcmp (argv[index], "-f") == 0)
+ {
+ force = TRUE;
+ index += 1;
+ }
+
+ dir = argv[index];
if (!dconf_is_dir (dir, &local_error))
return option_error_propagate (error, &local_error);
- if (argv[1] != NULL)
+ index += 1;
+
+ if (argv[index] != NULL)
return option_error_set (error, "too many arguments");
kf = keyfile_from_stdin (error);
if (kf == NULL)
return FALSE;
+ client = dconf_client_new ();
changeset = dconf_changeset_new ();
- if (!keyfile_foreach (kf, dir, changeset_set, changeset, error))
+
+ LoadContext ctx = { client, changeset, force };
+ if (!keyfile_foreach (kf, dir, changeset_set, &ctx, error))
return FALSE;
- client = dconf_client_new ();
return dconf_client_change_sync (client, changeset, NULL, NULL, error);
}
@@ -1024,8 +1051,8 @@ static const Command commands[] = {
},
{
"load", dconf_load,
- "Populate a subpath from stdin",
- " DIR "
+ "Populate a subpath from stdin. -f ignore locked keys.",
+ " [-f] DIR "
},
{
"blame", dconf_blame,
diff --git a/docs/dconf-tool.xml b/docs/dconf-tool.xml
index 7093da6..e5f8c24 100644
--- a/docs/dconf-tool.xml
+++ b/docs/dconf-tool.xml
@@ -77,6 +77,7 @@
<cmdsynopsis>
<command>dconf</command>
<arg choice="plain">load</arg>
+ <arg choice="opt">-f</arg>
<arg choice="plain"><replaceable>DIR</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
@@ -180,7 +181,13 @@
<varlistentry>
<term><option>load</option></term>
- <listitem><para>Populate a subpath from stdin. The expected format is the same as produced by
<option>dump</option>.</para></listitem>
+ <listitem>
+ <para>
+ Populate a subpath from stdin. The expected format is the same as produced by
<option>dump</option>.
+ Attempting to change non-writable keys cancels the load command.
+ To ignore changes to non-writable keys instead, use <option>-f</option>.
+ </para>
+ </listitem>
</varlistentry>
<varlistentry>
diff --git a/tests/test-dconf.py b/tests/test-dconf.py
index 1e143e2..cf9bb14 100755
--- a/tests/test-dconf.py
+++ b/tests/test-dconf.py
@@ -62,8 +62,8 @@ def dconf(*args, **kwargs):
return subprocess.run(argv, **kwargs)
-def dconf_read(key):
- return dconf('read', key).stdout.rstrip('\n')
+def dconf_read(key, **kwargs):
+ return dconf('read', key, **kwargs).stdout.rstrip('\n')
def dconf_write(key, value):
@@ -684,6 +684,7 @@ class DBusTest(unittest.TestCase):
- Update configures locks based on files found in "locks" subdirectory.
- Locks can be listed with list-locks command.
- Locks are enforced during write.
+ - Load can ignore changes to locked keys using -f option.
"""
db = os.path.join(self.temporary_dir.name, 'db')
@@ -755,6 +756,26 @@ class DBusTest(unittest.TestCase):
env=env, stderr=subprocess.PIPE)
self.assertRegex(cm.exception.stderr, 'non-writable keys')
+ keyfile = dedent('''\
+ [system/proxy/http]
+ enabled=false
+ [org/gnome/desktop]
+ background='Winter.png'
+ ''')
+
+ # Load fails to apply changes if some key is locked ...
+ with self.assertRaises(subprocess.CalledProcessError) as cm:
+ dconf('load', '/', input=keyfile, env=env, stderr=subprocess.PIPE)
+ self.assertRegex(cm.exception.stderr, 'non-writable keys')
+ self.assertEqual('true', dconf_read('/system/proxy/http/enabled', env=env))
+ self.assertEqual("'ColdWarm.jpg'", dconf_read('/org/gnome/desktop/background', env=env))
+
+ # ..., unless invoked with -f option, then it changes unlocked keys.
+ stderr = dconf('load', '-f', '/', input=keyfile, env=env, stderr=subprocess.PIPE).stderr
+ self.assertRegex(stderr, 'ignored non-writable key')
+ self.assertEqual('true', dconf_read('/system/proxy/http/enabled', env=env))
+ self.assertEqual("'Winter.png'", dconf_read('/org/gnome/desktop/background', env=env))
+
def test_dconf_blame(self):
"""Blame returns recorded information about write operations.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]