diff -r d0b9e9803caf -r 56acc4250900 mercurial/scmutil.py --- a/mercurial/scmutil.py Mon Mar 20 11:50:55 2017 +0900 +++ b/mercurial/scmutil.py Fri Mar 10 14:33:42 2017 -0800 @@ -965,3 +965,41 @@ """ # experimental config: format.generaldelta return ui.configbool('format', 'generaldelta', False) + +class simplekeyvaluefile(object): + """A simple file with key=value lines + + Keys must be alphanumerics and start with a letter, values must not + contain '\n' characters""" + + def __init__(self, vfs, path, keys=None): + self.vfs = vfs + self.path = path + + def read(self): + lines = self.vfs.readlines(self.path) + try: + d = dict(line[:-1].split('=', 1) for line in lines if line) + except ValueError as e: + raise error.CorruptedState(str(e)) + return d + + def write(self, data): + """Write key=>value mapping to a file + data is a dict. Keys must be alphanumerical and start with a letter. + Values must not contain newline characters.""" + lines = [] + for k, v in data.items(): + if not k[0].isalpha(): + e = "keys must start with a letter in a key-value file" + raise error.ProgrammingError(e) + if not k.isalnum(): + e = "invalid key name in a simple key-value file" + raise error.ProgrammingError(e) + if '\n' in v: + e = "invalid value in a simple key-value file" + raise error.ProgrammingError(e) + lines.append("%s=%s\n" % (k, v)) + with self.vfs(self.path, mode='wb', atomictemp=True) as fp: + fp.write(''.join(lines)) +