summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Playfair Cal <daniel.playfair.cal@gmail.com>2019-02-12 22:15:56 +0000
committerDaniel Playfair Cal <daniel.playfair.cal@gmail.com>2019-02-12 22:15:56 +0000
commit0740fd9c28f5cb2cfab634ebdd3c6f4893e2d296 (patch)
tree1444a893b63574b768194dce7b5a9b7cc37cc05c
parentf0bb97ded21f8d2fb50065e7cfefade66a70333e (diff)
parentc963f9eec8d72d6e17099d456330cd988294c0af (diff)
downloaddconf-0740fd9c28f5cb2cfab634ebdd3c6f4893e2d296.tar.gz
Merge branch 'ignore-non-writable' into 'master'
bin: Add an option to ignore changes to locked keys during load Closes #1 See merge request GNOME/dconf!43
-rw-r--r--bin/dconf.c43
-rw-r--r--docs/dconf-tool.xml9
-rwxr-xr-xtests/test-dconf.py34
3 files changed, 70 insertions, 16 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 51e522b..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')
@@ -714,8 +715,8 @@ class DBusTest(unittest.TestCase):
host='172.16.0.1'
enabled=true
- [org/gnome/desktop/background]
- picture-uri='file:///usr/local/rupert-corp/company-wallpaper.jpeg'
+ [org/gnome/desktop]
+ background='company-wallpaper.jpeg'
'''))
# Lock proxy settings.
@@ -746,9 +747,8 @@ class DBusTest(unittest.TestCase):
dconf_locks('/org/gnome/', env=env))
# Changing unlocked defaults is fine.
- dconf('write', '/org/gnome/desktop/background/picture-uri',
- '"file:///usr/share/backgrounds/gnome/ColdWarm.jpg"',
- env=env)
+ dconf('write', '/org/gnome/desktop/background',
+ '"ColdWarm.jpg"', env=env)
# It is an error to change locked keys.
with self.assertRaises(subprocess.CalledProcessError) as cm:
@@ -756,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.