##// END OF EJS Templates
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate `dirstatemap.dirfoldmap` was recently changed to re-use a Rust iterator that was added for the `hg debugdirstate` command. That iterator was based on all nodes in the tree dirstate without an entry only existing to hold child nodes, and therefore being directories. However to optimize status further we may want to store additional nodes for unknown or ignored files and directories. At that point the two users of this iterator will want different things, so let’s make two iterators instead. See doc-comments in `dispatch.rs`. Differential Revision: https://phab.mercurial-scm.org/D11099

File last commit:

r48482:78f7f0d4 default
r48483:284a2026 default
Show More
docket.py
75 lines | 2.4 KiB | text/x-python | PythonLexer
# dirstatedocket.py - docket file for dirstate-v2
#
# Copyright Mercurial Contributors
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import struct
from ..revlogutils import docket as docket_mod
V2_FORMAT_MARKER = b"dirstate-v2\n"
# Must match the constant of the same name in
# `rust/hg-core/src/dirstate_tree/on_disk.rs`
TREE_METADATA_SIZE = 40
# * 12 bytes: format marker
# * 32 bytes: node ID of the working directory's first parent
# * 32 bytes: node ID of the working directory's second parent
# * 4 bytes: big-endian used size of the data file
# * {TREE_METADATA_SIZE} bytes: tree metadata, parsed separately
# * 1 byte: length of the data file's UUID
# * variable: data file's UUID
#
# Node IDs are null-padded if shorter than 32 bytes.
# A data file shorter than the specified used size is corrupted (truncated)
HEADER = struct.Struct(
">{}s32s32sL{}sB".format(len(V2_FORMAT_MARKER), TREE_METADATA_SIZE)
)
class DirstateDocket(object):
data_filename_pattern = b'dirstate.%s.d'
def __init__(self, parents, data_size, tree_metadata, uuid):
self.parents = parents
self.data_size = data_size
self.tree_metadata = tree_metadata
self.uuid = uuid
@classmethod
def with_new_uuid(cls, parents, data_size, tree_metadata):
return cls(parents, data_size, tree_metadata, docket_mod.make_uid())
@classmethod
def parse(cls, data, nodeconstants):
if not data:
parents = (nodeconstants.nullid, nodeconstants.nullid)
return cls(parents, 0, b'', None)
marker, p1, p2, data_size, meta, uuid_size = HEADER.unpack_from(data)
if marker != V2_FORMAT_MARKER:
raise ValueError("expected dirstate-v2 marker")
uuid = data[HEADER.size : HEADER.size + uuid_size]
p1 = p1[: nodeconstants.nodelen]
p2 = p2[: nodeconstants.nodelen]
return cls((p1, p2), data_size, meta, uuid)
def serialize(self):
p1, p2 = self.parents
header = HEADER.pack(
V2_FORMAT_MARKER,
p1,
p2,
self.data_size,
self.tree_metadata,
len(self.uuid),
)
return header + self.uuid
def data_filename(self):
return self.data_filename_pattern % self.uuid