##// END OF EJS Templates
revlogv2: track pending write in the docket and expose it to hooks...
revlogv2: track pending write in the docket and expose it to hooks The docket is now able to write pending data. We could have used a distinct intermediate files, however keeping everything in the same file will make it simpler to keep track of the various involved files if necessary. However it might prove more complicated for streaming clone. This will be dealt with later. Note that we lifted the stderr redirection in the test since we no longer suffer from "unkown working directory parent" message. Differential Revision: https://phab.mercurial-scm.org/D10631

File last commit:

r48015:2219853a default
r48015:2219853a default
Show More
docket.py
138 lines | 4.3 KiB | text/x-python | PythonLexer
revlogv2: introduce a very basic docket file...
r48008 # 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
revlogv2: track pending write in the docket and expose it to hooks...
r48015 from .. import (
error,
)
revlogv2: introduce a very basic docket file...
r48008 from . import (
constants,
)
# Docket format
#
# * 4 bytes: revlog version
# | This is mandatory as docket must be compatible with the previous
# | revlog index header.
revlogv2: track current index size in the docket...
r48012 # * 8 bytes: size of index data
revlogv2: track pending write in the docket and expose it to hooks...
r48015 # * 8 bytes: pending size of index data
S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'LL')
revlogv2: introduce a very basic docket file...
r48008
class RevlogDocket(object):
"""metadata associated with revlog"""
revlogv2: track pending write in the docket and expose it to hooks...
r48015 def __init__(
self,
revlog,
use_pending=False,
version_header=None,
index_end=0,
pending_index_end=0,
):
revlogv2: introduce a very basic docket file...
r48008 self._version_header = version_header
revlogv2: track pending write in the docket and expose it to hooks...
r48015 self._read_only = bool(use_pending)
revlogv2: introduce a very basic docket file...
r48008 self._dirty = False
self._radix = revlog.radix
self._path = revlog._docket_file
self._opener = revlog.opener
revlogv2: track pending write in the docket and expose it to hooks...
r48015 # this assert should be True as long as we have a single index filename
assert index_end <= pending_index_end
self._initial_index_end = index_end
self._pending_index_end = pending_index_end
if use_pending:
self._index_end = self._pending_index_end
else:
self._index_end = self._initial_index_end
revlogv2: introduce a very basic docket file...
r48008
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
revlogv2: track current index size in the docket...
r48012 @property
def index_end(self):
return self._index_end
@index_end.setter
def index_end(self, new_size):
if new_size != self._index_end:
self._index_end = new_size
self._dirty = True
revlogv2: track pending write in the docket and expose it to hooks...
r48015 def write(self, transaction, pending=False, stripping=False):
revlogv2: introduce a very basic docket file...
r48008 """write the modification of disk if any
This make the new content visible to all process"""
revlogv2: track pending write in the docket and expose it to hooks...
r48015 if not self._dirty:
return False
else:
if self._read_only:
msg = b'writing read-only docket: %s'
msg %= self._path
raise error.ProgrammingError(msg)
revlogv2: track current index size in the docket...
r48012 if not stripping:
# XXX we could, leverage the docket while stripping. However it
# is not powerfull enough at the time of this comment
transaction.addbackup(self._path, location=b'store')
revlogv2: introduce a very basic docket file...
r48008 with self._opener(self._path, mode=b'w', atomictemp=True) as f:
revlogv2: track pending write in the docket and expose it to hooks...
r48015 f.write(self._serialize(pending=pending))
# if pending we still need to the write final data eventually
self._dirty = pending
return True
revlogv2: introduce a very basic docket file...
r48008
revlogv2: track pending write in the docket and expose it to hooks...
r48015 def _serialize(self, pending=False):
if pending:
official_index_end = self._initial_index_end
else:
official_index_end = self._index_end
# this assert should be True as long as we have a single index filename
assert official_index_end <= self._index_end
revlogv2: track current index size in the docket...
r48012 data = (
self._version_header,
revlogv2: track pending write in the docket and expose it to hooks...
r48015 official_index_end,
revlogv2: track current index size in the docket...
r48012 self._index_end,
)
return S_HEADER.pack(*data)
revlogv2: introduce a very basic docket file...
r48008
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
revlogv2: track pending write in the docket and expose it to hooks...
r48015 def parse_docket(revlog, data, use_pending=False):
revlogv2: introduce a very basic docket file...
r48008 """given some docket data return a docket object for the given revlog"""
header = S_HEADER.unpack(data[: S_HEADER.size])
revlogv2: track pending write in the docket and expose it to hooks...
r48015 version_header, index_size, pending_index_size = header
revlogv2: introduce a very basic docket file...
r48008 docket = RevlogDocket(
revlog,
revlogv2: track pending write in the docket and expose it to hooks...
r48015 use_pending=use_pending,
revlogv2: introduce a very basic docket file...
r48008 version_header=version_header,
revlogv2: track current index size in the docket...
r48012 index_end=index_size,
revlogv2: track pending write in the docket and expose it to hooks...
r48015 pending_index_end=pending_index_size,
revlogv2: introduce a very basic docket file...
r48008 )
return docket