Mercurial > hg
comparison mercurial/scmutil.py @ 31553:56acc4250900
scmutil: add a simple key-value file helper
The purpose of the added class is to serve purposes like save files of shelve
or state files of shelve, rebase and histedit. Keys of these files can be
alphanumeric and start with letters, while values must not contain newlines.
In light of Mercurial's reluctancy to use Python's json module, this tries
to provide a reasonable alternative for a non-nested named data.
Comparing to current approach of storing state in plain text files, where
semantic meaning of lines of text is only determined by their oreder,
simple key-value file allows for reordering lines and thus helps handle
optional values.
Initial use-case I see for this is obs-shelve's shelve files. Later we
can possibly migrate state files to this approach.
The test is in a new file beause I did not figure out where to put it
within existing test suite. If you give me a better idea, I will gladly
follow it.
author | Kostia Balytskyi <ikostia@fb.com> |
---|---|
date | Fri, 10 Mar 2017 14:33:42 -0800 |
parents | 1fc3d1f02865 |
children | 0f8ba0bc1154 |
comparison
equal
deleted
inserted
replaced
31552:d0b9e9803caf | 31553:56acc4250900 |
---|---|
963 def gddeltaconfig(ui): | 963 def gddeltaconfig(ui): |
964 """helper function to know if incoming delta should be optimised | 964 """helper function to know if incoming delta should be optimised |
965 """ | 965 """ |
966 # experimental config: format.generaldelta | 966 # experimental config: format.generaldelta |
967 return ui.configbool('format', 'generaldelta', False) | 967 return ui.configbool('format', 'generaldelta', False) |
968 | |
969 class simplekeyvaluefile(object): | |
970 """A simple file with key=value lines | |
971 | |
972 Keys must be alphanumerics and start with a letter, values must not | |
973 contain '\n' characters""" | |
974 | |
975 def __init__(self, vfs, path, keys=None): | |
976 self.vfs = vfs | |
977 self.path = path | |
978 | |
979 def read(self): | |
980 lines = self.vfs.readlines(self.path) | |
981 try: | |
982 d = dict(line[:-1].split('=', 1) for line in lines if line) | |
983 except ValueError as e: | |
984 raise error.CorruptedState(str(e)) | |
985 return d | |
986 | |
987 def write(self, data): | |
988 """Write key=>value mapping to a file | |
989 data is a dict. Keys must be alphanumerical and start with a letter. | |
990 Values must not contain newline characters.""" | |
991 lines = [] | |
992 for k, v in data.items(): | |
993 if not k[0].isalpha(): | |
994 e = "keys must start with a letter in a key-value file" | |
995 raise error.ProgrammingError(e) | |
996 if not k.isalnum(): | |
997 e = "invalid key name in a simple key-value file" | |
998 raise error.ProgrammingError(e) | |
999 if '\n' in v: | |
1000 e = "invalid value in a simple key-value file" | |
1001 raise error.ProgrammingError(e) | |
1002 lines.append("%s=%s\n" % (k, v)) | |
1003 with self.vfs(self.path, mode='wb', atomictemp=True) as fp: | |
1004 fp.write(''.join(lines)) | |
1005 |