diff --git a/plugins/modules/dconf.py b/plugins/modules/dconf.py index 4d7ed34bf93..68ca37f3a5b 100644 --- a/plugins/modules/dconf.py +++ b/plugins/modules/dconf.py @@ -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. @@ -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