[PATCH 2 of 4 shelve-ext v4] scmutil: make simplekeyvaluefile able to have a non-key-value first line
Yuya Nishihara
yuya at tcha.org
Thu May 11 09:30:47 EDT 2017
On Sun, 7 May 2017 06:07:04 -0700, Kostia Balytskyi wrote:
> # HG changeset patch
> # User Kostia Balytskyi <ikostia at fb.com>
> # Date 1494158131 25200
> # Sun May 07 04:55:31 2017 -0700
> # Node ID d78507e5b31ac9d5dbf3b8ab45c0c94b01491a0b
> # Parent e9b77b6f16c04efced06169735a813d5db82dddf
> scmutil: make simplekeyvaluefile able to have a non-key-value first line
>
> To ease migration from files with version numbers in their first lines,
> we want simplekeyvaluefile to support a non-key-value first line. In this
> way, old versions of Mercurial will read such files, discover a newer version
> than the one they know how to handle and fail gracefully, rather than with
> exception. Shelve's shelvestate file is an example.
>
> diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
> --- a/mercurial/scmutil.py
> +++ b/mercurial/scmutil.py
> @@ -917,28 +917,50 @@ class simplekeyvaluefile(object):
>
> Keys must be alphanumerics and start with a letter, values must not
> contain '\n' characters"""
> + firstlinekey = '__firstline'
>
> def __init__(self, vfs, path, keys=None):
> self.vfs = vfs
> self.path = path
>
> - def read(self):
> + def read(self, firstlinenonkeyval=False):
> + """Read the contents of a simple key-value file
> +
> + 'firstlinenonkeyval' indicates whether the first line of file should
> + be treated as a key-value pair or reuturned fully under the
> + __firstline key."""
> lines = self.vfs.readlines(self.path)
> + d = {}
> + if firstlinenonkeyval:
> + # we don't want to include '\n' in the __firstline
> + d[self.firstlinekey] = lines[0][:-1]
> + del lines[0]
lines may be an empty list. In which case, CorruptedState should be raised.
> try:
> # the 'if line.strip()' part prevents us from failing on empty
> # lines which only contain '\n' therefore are not skipped
> # by 'if line'
> - d = dict(line[:-1].split('=', 1) for line in lines if line.strip())
> + d.update(dict(line[:-1].split('=', 1) for line in lines
> + if line.strip()))
Perhaps '__firstline=' should be rejected as CorruptedState for consistency
with write() ?
> except ValueError as e:
> raise error.CorruptedState(str(e))
> return d
>
> - def write(self, data):
> + def write(self, data, firstline=None):
> """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."""
> + Values must not contain newline characters.
> +
> + If 'firstline' is not None, it is written to file before
> + everything else, as it is, not in a key=value form"""
> lines = []
> + if firstline is not None:
> + lines.append('%s\n' % firstline)
> +
> for k, v in data.items():
> + if k == self.firstlinekey:
> + e = "key name '%s' is reserved" % self.firstlinekey
> + raise error.ProgrammingError(e)
> if not k[0].isalpha():
> e = "keys must start with a letter in a key-value file"
> raise error.ProgrammingError(e)
More information about the Mercurial-devel
mailing list