Skip to content

Commit

Permalink
dconf: Check for changes properly despite style of quotes used by user
Browse files Browse the repository at this point in the history
GVariant strings can use either single or double quotes, and therefore
the user can use either single or double quotes when specifying a
string value in their task, and what they choose to use may not match
what is output by the dconf command, so for accurate comparison we
need to strip the quotes and just compare what's inside them.
  • Loading branch information
Jonathan Kamens authored and jikamens committed Feb 23, 2023
1 parent c168f9c commit 224b734
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion plugins/modules/dconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,48 @@ def __init__(self, module, check_mode=False):
# Check if dconf binary exists
self.dconf_bin = self.module.get_bin_path('dconf', required=True)

# GVariant strings can use either single or double quotes, and therefore
# the user can use either single or double quotes when specifying a string
# value in their task, and what they choose to use may not match what is
# output by the dconf command, so for accurate comparison we need to strip
# the quotes and just compare what's inside them.
#
# This doesn't give us 100% accurate GVariant string interpretation, but
# it solves many of the common use cases and makes us much more accurate
# than if we just compare the two strings directly.
@staticmethod
def gvariant_maybe_string(value):
"""
Partially canonicalization value to avoid quotation mark inconsistencies
:returns: a massaged value of the same type as its input
"""
if not isinstance(value, str):
return value
if len(value) < 2:
return value
if value[0] in ('"', "'") and value[-1] == value[0]:
# Whichever quotation mark the user has chosen to use will
# definitely need to be backslash-quoted in the string, so to
# improve our likelihood of getting this check right, remove those
# backslashes.
chars = list(value[1:-1])
i = 0
while i < len(chars) - 1:
if chars[i] == '\\':
if chars[i+1] == value[0]:
chars[i] = ''
else:
# Otherwise we'll mishandle a \ quoted with a \
i += 1
i += 1
return ''.join(chars)
return value

def gvariant_equal(self, value1, value2):
return (self.gvariant_maybe_string(value1) ==
self.gvariant_maybe_string(value2))

def read(self, key):
"""
Retrieves current value associated with the dconf key.
Expand Down Expand Up @@ -298,7 +340,7 @@ def write(self, key, value):
"""
# If no change is needed (or won't be done due to check_mode), notify
# caller straight away.
if value == self.read(key):
if self.gvariant_equal(value, self.read(key)):
return False
elif self.check_mode:
return True
Expand Down

0 comments on commit 224b734

Please sign in to comment.