Mercurial > hg
view mercurial/state.py @ 39814:d059cb669632
wireprotov2: allow multiple fields to follow revision maps
The *data wire protocol commands emit a series of CBOR values.
Because revision/delta data may be large, their data is emitted
outside the map as a top-level bytestring value.
Before this commit, we'd emit a single optional bytestring
value after the revision descriptor map. This got the job done.
But it was limiting in that we could only send a single field.
And, it required the consumer to know that the presence of a
key in the map implied the existence of a following bytestring
value.
This commit changes the encoding strategy so top-level bytestring
values in the stream are explicitly denoted in a "fieldsfollowing"
key. This key contains an array defining what fields that follow
and the expected size of each field.
By defining things this way, we can easily send N bytestring
values without any ambiguity about their order. In addition,
clients only need to know how to parse ``fieldsfollowing`` to
know if extra values are present.
Because this breaks backwards compatibility, we've bumped the version
number of the wire protocol version 2 API endpoint.
Differential Revision: https://phab.mercurial-scm.org/D4620
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Thu, 20 Sep 2018 12:57:23 -0700 |
parents | 5bfab9400daf |
children | 050ea8eb42a5 |
line wrap: on
line source
# state.py - writing and reading state files in Mercurial # # Copyright 2018 Pulkit Goyal <pulkitmgoyal@gmail.com> # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. """ This file contains class to wrap the state for commands and other related logic. All the data related to the command state is stored as dictionary in the object. The class has methods using which the data can be stored to disk in a file under .hg/ directory. We store the data on disk in cbor, for which we use the third party cbor library to serialize and deserialize data. """ from __future__ import absolute_import from . import ( error, util, ) from .utils import ( cborutil, ) class cmdstate(object): """a wrapper class to store the state of commands like `rebase`, `graft`, `histedit`, `shelve` etc. Extensions can also use this to write state files. All the data for the state is stored in the form of key-value pairs in a dictionary. The class object can write all the data to a file in .hg/ directory and can populate the object data reading that file. Uses cbor to serialize and deserialize data while writing and reading from disk. """ def __init__(self, repo, fname): """ repo is the repo object fname is the file name in which data should be stored in .hg directory """ self._repo = repo self.fname = fname def read(self): """read the existing state file and return a dict of data stored""" return self._read() def save(self, version, data): """write all the state data stored to .hg/<filename> file we use third-party library cbor to serialize data to write in the file. """ if not isinstance(version, int): raise error.ProgrammingError("version of state file should be" " an integer") with self._repo.vfs(self.fname, 'wb', atomictemp=True) as fp: fp.write('%d\n' % version) for chunk in cborutil.streamencode(data): fp.write(chunk) def _read(self): """reads the state file and returns a dictionary which contain data in the same format as it was before storing""" with self._repo.vfs(self.fname, 'rb') as fp: try: int(fp.readline()) except ValueError: raise error.CorruptedState("unknown version of state file" " found") return cborutil.decodeall(fp.read())[0] def delete(self): """drop the state file if exists""" util.unlinkpath(self._repo.vfs.join(self.fname), ignoremissing=True) def exists(self): """check whether the state file exists or not""" return self._repo.vfs.exists(self.fname)