annotate mercurial/dirstateutils/v2.py @ 48264:bb240915f69f

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
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 19 Oct 2021 18:18:05 +0200
parents 83d0bd45b662
children 434de12918fd 46d12f7762e4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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)