Mercurial > public > mercurial-scm > hg
diff mercurial/revlogutils/docket.py @ 47234:616b8f412676
revlogv2: introduce a very basic docket file
This is the first stone toward using a docket file in revlogv2. Right now the
docket is very basic and only store the version number (which is -also- stored
into the index file?) and the other files have fixed name. This new
implementation break transactionally? but they are no test checking
transactionally for revlogv2? So I take this as an opportunity to start small.
They are no usage of revlogv2 outside of tests anyway.
The docket keeps the `.i` naming used by previous version index to preserve a
unique entry point. We could decide to use a different name and look it up
first, or to fully rework this in a future "store" version. However that does
not seems necessary right now.
We will re-introduces transactionality (and associated testing?) in a later
changesets.
A long list of TODOs have been added to the relevant comment.
Differential Revision: https://phab.mercurial-scm.org/D10624
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 03 May 2021 12:34:11 +0200 |
parents | |
children | 6597255a4f94 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/revlogutils/docket.py Mon May 03 12:34:11 2021 +0200 @@ -0,0 +1,80 @@ +# docket - code related to revlog "docket" +# +# Copyright 2021 Pierre-Yves David <pierre-yves.david@octobus.net> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +### Revlog docket file +# +# The revlog is stored on disk using multiple files: +# +# * a small docket file, containing metadata and a pointer, +# +# * an index file, containing fixed width information about revisions, +# +# * a data file, containing variable width data for these revisions, + +from __future__ import absolute_import + +import struct + +from . import ( + constants, +) + +# Docket format +# +# * 4 bytes: revlog version +# | This is mandatory as docket must be compatible with the previous +# | revlog index header. +S_HEADER = struct.Struct(constants.INDEX_HEADER.format) + + +class RevlogDocket(object): + """metadata associated with revlog""" + + def __init__(self, revlog, version_header=None): + self._version_header = version_header + self._dirty = False + self._radix = revlog.radix + self._path = revlog._docket_file + self._opener = revlog.opener + + def index_filepath(self): + """file path to the current index file associated to this docket""" + # very simplistic version at first + return b"%s.idx" % self._radix + + def write(self, transaction): + """write the modification of disk if any + + This make the new content visible to all process""" + if self._dirty: + transaction.addbackup(self._path, location=b'store') + with self._opener(self._path, mode=b'w', atomictemp=True) as f: + f.write(self._serialize()) + self._dirty = False + + def _serialize(self): + return S_HEADER.pack(self._version_header) + + +def default_docket(revlog, version_header): + """given a revlog version a new docket object for the given revlog""" + if (version_header & 0xFFFF) != constants.REVLOGV2: + return None + docket = RevlogDocket(revlog, version_header=version_header) + docket._dirty = True + return docket + + +def parse_docket(revlog, data): + """given some docket data return a docket object for the given revlog""" + header = S_HEADER.unpack(data[: S_HEADER.size]) + (version_header,) = header + docket = RevlogDocket( + revlog, + version_header=version_header, + ) + return docket