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