mercurial/dirstateutils/v2.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Tue, 19 Oct 2021 18:18:05 +0200
changeset 48264 bb240915f69f
parent 48263 83d0bd45b662
child 48392 434de12918fd
child 48741 46d12f7762e4
permissions -rw-r--r--
dirstate-v2: adjust the meaning of directory flags Tracking directory "explicitly" give use the opportunity to distinct between entry that are untracked because they are part of the directory structure and entry that are ignored/unknown files on the files system. The help is adjusted to the new semantic and the code now comply to it for both read and write. Differential Revision: https://phab.mercurial-scm.org/D11694
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     1
# v2.py - Pure-Python implementation of the dirstate-v2 file format
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     2
#
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     3
# Copyright Mercurial Contributors
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     4
#
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     7
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     8
from __future__ import absolute_import
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     9
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    10
import struct
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    11
48222
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
    12
from ..thirdparty import attr
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
    13
from .. import error, policy
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    14
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    15
parsers = policy.importmod('parsers')
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    16
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    17
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    18
# Must match the constant of the same name in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    19
# `rust/hg-core/src/dirstate_tree/on_disk.rs`
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    20
TREE_METADATA_SIZE = 44
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48228
diff changeset
    21
NODE_SIZE = 44
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    22
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    23
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    24
# Must match the `TreeMetadata` Rust struct in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    25
# `rust/hg-core/src/dirstate_tree/on_disk.rs`. See doc-comments there.
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    26
#
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    27
# * 4 bytes: start offset of root nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    28
# * 4 bytes: number of root nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    29
# * 4 bytes: total number of nodes in the tree that have an entry
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    30
# * 4 bytes: total number of nodes in the tree that have a copy source
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    31
# * 4 bytes: number of bytes in the data file that are not used anymore
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    32
# * 4 bytes: unused
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    33
# * 20 bytes: SHA-1 hash of ignore patterns
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    34
TREE_METADATA = struct.Struct('>LLLLL4s20s')
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    35
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    36
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    37
# Must match the `Node` Rust struct in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    38
# `rust/hg-core/src/dirstate_tree/on_disk.rs`. See doc-comments there.
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    39
#
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    40
# * 4 bytes: start offset of full path
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    41
# * 2 bytes: length of the full path
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    42
# * 2 bytes: length within the full path before its "base name"
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    43
# * 4 bytes: start offset of the copy source if any, or zero for no copy source
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    44
# * 2 bytes: length of the copy source if any, or unused
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    45
# * 4 bytes: start offset of child nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    46
# * 4 bytes: number of child nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    47
# * 4 bytes: number of descendant nodes that have an entry
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    48
# * 4 bytes: number of descendant nodes that have a "tracked" state
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    49
# * 1 byte: flags
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    50
# * 4 bytes: expected size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    51
# * 4 bytes: mtime seconds
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    52
# * 4 bytes: mtime nanoseconds
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48228
diff changeset
    53
NODE = struct.Struct('>LHHLHLLLLHlll')
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    54
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    55
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    56
assert TREE_METADATA_SIZE == TREE_METADATA.size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    57
assert NODE_SIZE == NODE.size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    58
48264
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
    59
# match constant in mercurial/pure/parsers.py
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
    60
DIRSTATE_V2_DIRECTORY = 1 << 5
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
    61
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    62
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    63
def parse_dirstate(map, copy_map, data, tree_metadata):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    64
    """parse a full v2-dirstate from a binary data into dictionnaries:
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    65
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    66
    - map: a {path: entry} mapping that will be filled
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    67
    - copy_map: a {path: copy-source} mapping that will be filled
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    68
    - data: a binary blob contains v2 nodes data
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    69
    - tree_metadata:: a binary blob of the top level node (from the docket)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    70
    """
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    71
    (
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    72
        root_nodes_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    73
        root_nodes_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    74
        _nodes_with_entry_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    75
        _nodes_with_copy_source_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    76
        _unreachable_bytes,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    77
        _unused,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    78
        _ignore_patterns_hash,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    79
    ) = TREE_METADATA.unpack(tree_metadata)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    80
    parse_nodes(map, copy_map, data, root_nodes_start, root_nodes_len)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    81
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    82
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    83
def parse_nodes(map, copy_map, data, start, len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    84
    """parse <len> nodes from <data> starting at offset <start>
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    85
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    86
    This is used by parse_dirstate to recursively fill `map` and `copy_map`.
48251
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48231
diff changeset
    87
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48231
diff changeset
    88
    All directory specific information is ignored and do not need any
48264
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
    89
    processing (DIRECTORY, ALL_UNKNOWN_RECORDED, ALL_IGNORED_RECORDED)
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    90
    """
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    91
    for i in range(len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    92
        node_start = start + NODE_SIZE * i
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    93
        node_bytes = slice_with_len(data, node_start, NODE_SIZE)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    94
        (
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    95
            path_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    96
            path_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    97
            _basename_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    98
            copy_source_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    99
            copy_source_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   100
            children_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   101
            children_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   102
            _descendants_with_entry_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   103
            _tracked_descendants_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   104
            flags,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   105
            size,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   106
            mtime_s,
48263
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
   107
            mtime_ns,
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   108
        ) = NODE.unpack(node_bytes)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   109
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   110
        # Parse child nodes of this node recursively
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   111
        parse_nodes(map, copy_map, data, children_start, children_count)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   112
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48251
diff changeset
   113
        item = parsers.DirstateItem.from_v2_data(flags, size, mtime_s, mtime_ns)
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   114
        if not item.any_tracked:
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   115
            continue
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   116
        path = slice_with_len(data, path_start, path_len)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   117
        map[path] = item
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   118
        if copy_source_start:
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   119
            copy_map[path] = slice_with_len(
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   120
                data, copy_source_start, copy_source_len
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   121
            )
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   122
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   123
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   124
def slice_with_len(data, start, len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   125
    return data[start : start + len]
48222
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   126
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   127
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   128
@attr.s
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   129
class Node(object):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   130
    path = attr.ib()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   131
    entry = attr.ib()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   132
    parent = attr.ib(default=None)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   133
    children_count = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   134
    children_offset = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   135
    descendants_with_entry = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   136
    tracked_descendants = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   137
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   138
    def pack(self, copy_map, paths_offset):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   139
        path = self.path
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   140
        copy = copy_map.get(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   141
        entry = self.entry
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   142
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   143
        path_start = paths_offset
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   144
        path_len = len(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   145
        basename_start = path.rfind(b'/') + 1  # 0 if rfind returns -1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   146
        if copy is not None:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   147
            copy_source_start = paths_offset + len(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   148
            copy_source_len = len(copy)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   149
        else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   150
            copy_source_start = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   151
            copy_source_len = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   152
        if entry is not None:
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48251
diff changeset
   153
            flags, size, mtime_s, mtime_ns = entry.v2_data()
48222
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   154
        else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   155
            # There are no mtime-cached directories in the Python implementation
48264
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
   156
            flags = DIRSTATE_V2_DIRECTORY
48222
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   157
            size = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   158
            mtime_s = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   159
            mtime_ns = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   160
        return NODE.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   161
            path_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   162
            path_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   163
            basename_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   164
            copy_source_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   165
            copy_source_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   166
            self.children_offset,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   167
            self.children_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   168
            self.descendants_with_entry,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   169
            self.tracked_descendants,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   170
            flags,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   171
            size,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   172
            mtime_s,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   173
            mtime_ns,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   174
        )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   175
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   176
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   177
def pack_dirstate(map, copy_map, now):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   178
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   179
    Pack `map` and `copy_map` into the dirstate v2 binary format and return
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   180
    the bytearray.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   181
    `now` is a timestamp of the current filesystem time used to detect race
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   182
    conditions in writing the dirstate to disk, see inline comment.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   183
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   184
    The on-disk format expects a tree-like structure where the leaves are
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   185
    written first (and sorted per-directory), going up levels until the root
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   186
    node and writing that one to the docket. See more details on the on-disk
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   187
    format in `mercurial/helptext/internals/dirstate-v2`.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   188
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   189
    Since both `map` and `copy_map` are flat dicts we need to figure out the
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   190
    hierarchy. This algorithm does so without having to build the entire tree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   191
    in-memory: it only keeps the minimum number of nodes around to satisfy the
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   192
    format.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   193
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   194
    # Algorithm explanation
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   195
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   196
    This explanation does not talk about the different counters for tracked
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   197
    descendents and storing the copies, but that work is pretty simple once this
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   198
    algorithm is in place.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   199
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   200
    ## Building a subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   201
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   202
    First, sort `map`: this makes it so the leaves of the tree are contiguous
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   203
    per directory (i.e. a/b/c and a/b/d will be next to each other in the list),
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   204
    and enables us to use the ordering of folders to have a "cursor" of the
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   205
    current folder we're in without ever going twice in the same branch of the
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   206
    tree. The cursor is a node that remembers its parent and any information
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   207
    relevant to the format (see the `Node` class), building the relevant part
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   208
    of the tree lazily.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   209
    Then, for each file in `map`, move the cursor into the tree to the
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   210
    corresponding folder of the file: for example, if the very first file
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   211
    is "a/b/c", we start from `Node[""]`, create `Node["a"]` which points to
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   212
    its parent `Node[""]`, then create `Node["a/b"]`, which points to its parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   213
    `Node["a"]`. These nodes are kept around in a stack.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   214
    If the next file in `map` is in the same subtree ("a/b/d" or "a/b/e/f"), we
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   215
    add it to the stack and keep looping with the same logic of creating the
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   216
    tree nodes as needed. If however the next file in `map` is *not* in the same
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   217
    subtree ("a/other", if we're still in the "a/b" folder), then we know that
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   218
    the subtree we're in is complete.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   219
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   220
    ## Writing the subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   221
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   222
    We have the entire subtree in the stack, so we start writing it to disk
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   223
    folder by folder. The way we write a folder is to pop the stack into a list
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   224
    until the folder changes, revert this list of direct children (to satisfy
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   225
    the format requirement that children be sorted). This process repeats until
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   226
    we hit the "other" subtree.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   227
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   228
    An example:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   229
        a
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   230
        dir1/b
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   231
        dir1/c
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   232
        dir2/dir3/d
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   233
        dir2/dir3/e
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   234
        dir2/f
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   235
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   236
    Would have us:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   237
        - add to the stack until "dir2/dir3/e"
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   238
        - realize that "dir2/f" is in a different subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   239
        - pop "dir2/dir3/e", "dir2/dir3/d", reverse them so they're sorted and
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   240
          pack them since the next entry is "dir2/dir3"
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   241
        - go back up to "dir2"
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   242
        - add "dir2/f" to the stack
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   243
        - realize we're done with the map
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   244
        - pop "dir2/f", "dir2/dir3" from the stack, reverse and pack them
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   245
        - go up to the root node, do the same to write "a", "dir1" and "dir2" in
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   246
          that order
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   247
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   248
    ## Special case for the root node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   249
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   250
    The root node is not serialized in the format, but its information is
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   251
    written to the docket. Again, see more details on the on-disk format in
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   252
    `mercurial/helptext/internals/dirstate-v2`.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   253
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   254
    data = bytearray()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   255
    root_nodes_start = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   256
    root_nodes_len = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   257
    nodes_with_entry_count = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   258
    nodes_with_copy_source_count = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   259
    # Will always be 0 since this implementation always re-writes everything
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   260
    # to disk
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   261
    unreachable_bytes = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   262
    unused = b'\x00' * 4
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   263
    # This is an optimization that's only useful for the Rust implementation
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   264
    ignore_patterns_hash = b'\x00' * 20
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   265
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   266
    if len(map) == 0:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   267
        tree_metadata = TREE_METADATA.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   268
            root_nodes_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   269
            root_nodes_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   270
            nodes_with_entry_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   271
            nodes_with_copy_source_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   272
            unreachable_bytes,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   273
            unused,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   274
            ignore_patterns_hash,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   275
        )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   276
        return data, tree_metadata
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   277
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   278
    sorted_map = sorted(map.items(), key=lambda x: x[0])
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   279
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   280
    # Use a stack to not have to only remember the nodes we currently need
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   281
    # instead of building the entire tree in memory
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   282
    stack = []
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   283
    current_node = Node(b"", None)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   284
    stack.append(current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   285
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   286
    for index, (path, entry) in enumerate(sorted_map, 1):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   287
        if entry.need_delay(now):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   288
            # The file was last modified "simultaneously" with the current
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   289
            # write to dirstate (i.e. within the same second for file-
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   290
            # systems with a granularity of 1 sec). This commonly happens
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   291
            # for at least a couple of files on 'update'.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   292
            # The user could change the file without changing its size
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   293
            # within the same second. Invalidate the file's mtime in
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   294
            # dirstate, forcing future 'status' calls to compare the
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   295
            # contents of the file if the size is the same. This prevents
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   296
            # mistakenly treating such files as clean.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   297
            entry.set_possibly_dirty()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   298
        nodes_with_entry_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   299
        if path in copy_map:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   300
            nodes_with_copy_source_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   301
        current_folder = get_folder(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   302
        current_node = move_to_correct_node_in_tree(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   303
            current_folder, current_node, stack
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   304
        )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   305
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   306
        current_node.children_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   307
        # Entries from `map` are never `None`
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   308
        if entry.tracked:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   309
            current_node.tracked_descendants += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   310
        current_node.descendants_with_entry += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   311
        stack.append(Node(path, entry, current_node))
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   312
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   313
        should_pack = True
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   314
        next_path = None
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   315
        if index < len(sorted_map):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   316
            # Determine if the next entry is in the same sub-tree, if so don't
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   317
            # pack yet
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   318
            next_path = sorted_map[index][0]
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   319
            should_pack = not get_folder(next_path).startswith(current_folder)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   320
        if should_pack:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   321
            pack_directory_children(current_node, copy_map, data, stack)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   322
            while stack and current_node.path != b"":
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   323
                # Go up the tree and write until we reach the folder of the next
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   324
                # entry (if any, otherwise the root)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   325
                parent = current_node.parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   326
                in_parent_folder_of_next_entry = next_path is not None and (
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   327
                    get_folder(next_path).startswith(get_folder(stack[-1].path))
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   328
                )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   329
                if parent is None or in_parent_folder_of_next_entry:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   330
                    break
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   331
                pack_directory_children(parent, copy_map, data, stack)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   332
                current_node = parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   333
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   334
    # Special case for the root node since we don't write it to disk, only its
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   335
    # children to the docket
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   336
    current_node = stack.pop()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   337
    assert current_node.path == b"", current_node.path
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   338
    assert len(stack) == 0, len(stack)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   339
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   340
    tree_metadata = TREE_METADATA.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   341
        current_node.children_offset,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   342
        current_node.children_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   343
        nodes_with_entry_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   344
        nodes_with_copy_source_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   345
        unreachable_bytes,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   346
        unused,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   347
        ignore_patterns_hash,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   348
    )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   349
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   350
    return data, tree_metadata
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   351
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   352
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   353
def get_folder(path):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   354
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   355
    Return the folder of the path that's given, an empty string for root paths.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   356
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   357
    return path.rsplit(b'/', 1)[0] if b'/' in path else b''
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   358
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   359
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   360
def move_to_correct_node_in_tree(target_folder, current_node, stack):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   361
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   362
    Move inside the dirstate node tree to the node corresponding to
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   363
    `target_folder`, creating the missing nodes along the way if needed.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   364
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   365
    while target_folder != current_node.path:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   366
        if target_folder.startswith(current_node.path):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   367
            # We need to go down a folder
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   368
            prefix = target_folder[len(current_node.path) :].lstrip(b'/')
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   369
            subfolder_name = prefix.split(b'/', 1)[0]
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   370
            if current_node.path:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   371
                subfolder_path = current_node.path + b'/' + subfolder_name
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   372
            else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   373
                subfolder_path = subfolder_name
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   374
            next_node = stack[-1]
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   375
            if next_node.path == target_folder:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   376
                # This folder is now a file and only contains removed entries
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   377
                # merge with the last node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   378
                current_node = next_node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   379
            else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   380
                current_node.children_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   381
                current_node = Node(subfolder_path, None, current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   382
                stack.append(current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   383
        else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   384
            # We need to go up a folder
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   385
            current_node = current_node.parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   386
    return current_node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   387
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   388
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   389
def pack_directory_children(node, copy_map, data, stack):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   390
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   391
    Write the binary representation of the direct sorted children of `node` to
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   392
    `data`
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   393
    """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   394
    direct_children = []
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   395
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   396
    while stack[-1].path != b"" and get_folder(stack[-1].path) == node.path:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   397
        direct_children.append(stack.pop())
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   398
    if not direct_children:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   399
        raise error.ProgrammingError(b"no direct children for %r" % node.path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   400
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   401
    # Reverse the stack to get the correct sorted order
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   402
    direct_children.reverse()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   403
    packed_children = bytearray()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   404
    # Write the paths to `data`. Pack child nodes but don't write them yet
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   405
    for child in direct_children:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   406
        packed = child.pack(copy_map=copy_map, paths_offset=len(data))
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   407
        packed_children.extend(packed)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   408
        data.extend(child.path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   409
        data.extend(copy_map.get(child.path, b""))
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   410
        node.tracked_descendants += child.tracked_descendants
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   411
        node.descendants_with_entry += child.descendants_with_entry
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   412
    # Write the fixed-size child nodes all together
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   413
    node.children_offset = len(data)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48221
diff changeset
   414
    data.extend(packed_children)