annotate mercurial/dirstateutils/v2.py @ 51788:278af66e6595

typing: induce pytype to use the standard `attr` instead of the vendored copy What was previously happening with the vendored copy was that pytype would stub out all(?) classes that were decorated with `@attr.s` as `Any`. After this, we get a ton of classes defined, and numerous fields and methods now have proper types.
author Matt Harbison <matt_harbison@yahoo.com>
date Tue, 23 Jul 2024 19:20:22 -0400
parents fc719967efd0
children f4733654f144
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
48233
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
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
9 import struct
51788
278af66e6595 typing: induce pytype to use the standard `attr` instead of the vendored copy
Matt Harbison <matt_harbison@yahoo.com>
parents: 49542
diff changeset
10 import typing
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
11
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
12 from ..thirdparty import attr
51788
278af66e6595 typing: induce pytype to use the standard `attr` instead of the vendored copy
Matt Harbison <matt_harbison@yahoo.com>
parents: 49542
diff changeset
13
278af66e6595 typing: induce pytype to use the standard `attr` instead of the vendored copy
Matt Harbison <matt_harbison@yahoo.com>
parents: 49542
diff changeset
14 # Force pytype to use the non-vendored package
278af66e6595 typing: induce pytype to use the standard `attr` instead of the vendored copy
Matt Harbison <matt_harbison@yahoo.com>
parents: 49542
diff changeset
15 if typing.TYPE_CHECKING:
278af66e6595 typing: induce pytype to use the standard `attr` instead of the vendored copy
Matt Harbison <matt_harbison@yahoo.com>
parents: 49542
diff changeset
16 # noinspection PyPackageRequirements
278af66e6595 typing: induce pytype to use the standard `attr` instead of the vendored copy
Matt Harbison <matt_harbison@yahoo.com>
parents: 49542
diff changeset
17 import attr
278af66e6595 typing: induce pytype to use the standard `attr` instead of the vendored copy
Matt Harbison <matt_harbison@yahoo.com>
parents: 49542
diff changeset
18
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
19 from .. import error, policy
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
20
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
21 parsers = policy.importmod('parsers')
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 constant of the same name 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`
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
26 TREE_METADATA_SIZE = 44
48243
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48240
diff changeset
27 NODE_SIZE = 44
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
28
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
29
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
30 # Must match the `TreeMetadata` Rust struct in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
31 # `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
32 #
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
33 # * 4 bytes: start offset of root nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
34 # * 4 bytes: number of root nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
35 # * 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
36 # * 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
37 # * 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
38 # * 4 bytes: unused
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
39 # * 20 bytes: SHA-1 hash of ignore patterns
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
40 TREE_METADATA = struct.Struct('>LLLLL4s20s')
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
41
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
42
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
43 # Must match the `Node` Rust struct in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
44 # `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
45 #
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
46 # * 4 bytes: start offset of full path
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
47 # * 2 bytes: length of the full path
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
48 # * 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
49 # * 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
50 # * 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
51 # * 4 bytes: start offset of child nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
52 # * 4 bytes: number of child nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
53 # * 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
54 # * 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
55 # * 1 byte: flags
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
56 # * 4 bytes: expected size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
57 # * 4 bytes: mtime seconds
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
58 # * 4 bytes: mtime nanoseconds
48243
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48240
diff changeset
59 NODE = struct.Struct('>LHHLHLLLLHlll')
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
60
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
61
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
62 assert TREE_METADATA_SIZE == TREE_METADATA.size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
63 assert NODE_SIZE == NODE.size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
64
48275
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
65 # match constant in mercurial/pure/parsers.py
49538
5743e19bb8b0 dirstate-v2: update constant that wasn't kept in sync
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49037
diff changeset
66 DIRSTATE_V2_DIRECTORY = 1 << 13
48275
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
67
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
68
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
69 def parse_dirstate(map, copy_map, data, tree_metadata):
49539
07b9ca52a378 dirstate-v2: fix typos in docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49538
diff changeset
70 """parse a full v2-dirstate from a binary data into dictionaries:
48233
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 - map: a {path: entry} mapping that will be filled
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
73 - 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
74 - data: a binary blob contains v2 nodes data
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
75 - 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
76 """
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
77 (
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
78 root_nodes_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
79 root_nodes_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
80 _nodes_with_entry_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
81 _nodes_with_copy_source_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
82 _unreachable_bytes,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
83 _unused,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
84 _ignore_patterns_hash,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
85 ) = TREE_METADATA.unpack(tree_metadata)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
86 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
87
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
88
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
89 def parse_nodes(map, copy_map, data, start, len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
90 """parse <len> nodes from <data> starting at offset <start>
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
91
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
92 This is used by parse_dirstate to recursively fill `map` and `copy_map`.
48262
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48243
diff changeset
93
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48243
diff changeset
94 All directory specific information is ignored and do not need any
48275
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
95 processing (DIRECTORY, ALL_UNKNOWN_RECORDED, ALL_IGNORED_RECORDED)
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
96 """
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
97 for i in range(len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
98 node_start = start + NODE_SIZE * i
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
99 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
100 (
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
101 path_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
102 path_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
103 _basename_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
104 copy_source_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
105 copy_source_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
106 children_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
107 children_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
108 _descendants_with_entry_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
109 _tracked_descendants_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
110 flags,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
111 size,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
112 mtime_s,
48274
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48271
diff changeset
113 mtime_ns,
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
114 ) = NODE.unpack(node_bytes)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
115
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
116 # Parse child nodes of this node recursively
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
117 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
118
48271
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
119 item = parsers.DirstateItem.from_v2_data(flags, size, mtime_s, mtime_ns)
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
120 if not item.any_tracked:
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
121 continue
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
122 path = slice_with_len(data, path_start, path_len)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
123 map[path] = item
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
124 if copy_source_start:
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
125 copy_map[path] = slice_with_len(
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
126 data, copy_source_start, copy_source_len
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
127 )
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
128
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
129
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
130 def slice_with_len(data, start, len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
131 return data[start : start + len]
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
132
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
133
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
134 @attr.s
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
135 class Node:
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
136 path = attr.ib()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
137 entry = attr.ib()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
138 parent = attr.ib(default=None)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
139 children_count = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
140 children_offset = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
141 descendants_with_entry = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
142 tracked_descendants = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
143
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
144 def pack(self, copy_map, paths_offset):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
145 path = self.path
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
146 copy = copy_map.get(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
147 entry = self.entry
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
148
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
149 path_start = paths_offset
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
150 path_len = len(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
151 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: 48233
diff changeset
152 if copy is not None:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
153 copy_source_start = paths_offset + len(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
154 copy_source_len = len(copy)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
155 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
156 copy_source_start = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
157 copy_source_len = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
158 if entry is not None:
48271
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
159 flags, size, mtime_s, mtime_ns = entry.v2_data()
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
160 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
161 # There are no mtime-cached directories in the Python implementation
48275
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
162 flags = DIRSTATE_V2_DIRECTORY
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
163 size = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
164 mtime_s = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
165 mtime_ns = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
166 return NODE.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
167 path_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
168 path_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
169 basename_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
170 copy_source_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
171 copy_source_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
172 self.children_offset,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
173 self.children_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
174 self.descendants_with_entry,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
175 self.tracked_descendants,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
176 flags,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
177 size,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
178 mtime_s,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
179 mtime_ns,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
180 )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
181
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
182
48440
434de12918fd dirstate: remove need_delay logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48275
diff changeset
183 def pack_dirstate(map, copy_map):
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
184 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
185 Pack `map` and `copy_map` into the dirstate v2 binary format and return
49540
318bdd289cf2 dirstate-v2: correct documented return values of `pack_dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49539
diff changeset
186 the tuple of (data, metadata) bytearrays.
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
187
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
188 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: 48233
diff changeset
189 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: 48233
diff changeset
190 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: 48233
diff changeset
191 format in `mercurial/helptext/internals/dirstate-v2`.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
192
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
193 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: 48233
diff changeset
194 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: 48233
diff changeset
195 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: 48233
diff changeset
196 format.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
197
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
198 # Algorithm explanation
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
199
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
200 This explanation does not talk about the different counters for tracked
49539
07b9ca52a378 dirstate-v2: fix typos in docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49538
diff changeset
201 descendants and storing the copies, but that work is pretty simple once this
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
202 algorithm is in place.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
203
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
204 ## Building a subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
205
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
206 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: 48233
diff changeset
207 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: 48233
diff changeset
208 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: 48233
diff changeset
209 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: 48233
diff changeset
210 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: 48233
diff changeset
211 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: 48233
diff changeset
212 of the tree lazily.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
213 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: 48233
diff changeset
214 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: 48233
diff changeset
215 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: 48233
diff changeset
216 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: 48233
diff changeset
217 `Node["a"]`. These nodes are kept around in a stack.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
218 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: 48233
diff changeset
219 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: 48233
diff changeset
220 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: 48233
diff changeset
221 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: 48233
diff changeset
222 the subtree we're in is complete.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
223
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
224 ## Writing the subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
225
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
226 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: 48233
diff changeset
227 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: 48233
diff changeset
228 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: 48233
diff changeset
229 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: 48233
diff changeset
230 we hit the "other" subtree.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
231
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
232 An example:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
233 a
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
234 dir1/b
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
235 dir1/c
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
236 dir2/dir3/d
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
237 dir2/dir3/e
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
238 dir2/f
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
239
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
240 Would have us:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
241 - add to the stack until "dir2/dir3/e"
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
242 - realize that "dir2/f" is in a different subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
243 - 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: 48233
diff changeset
244 pack them since the next entry is "dir2/dir3"
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
245 - go back up to "dir2"
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
246 - add "dir2/f" to the stack
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
247 - realize we're done with the map
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
248 - 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: 48233
diff changeset
249 - 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: 48233
diff changeset
250 that order
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
251
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
252 ## Special case for the root node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
253
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
254 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: 48233
diff changeset
255 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: 48233
diff changeset
256 `mercurial/helptext/internals/dirstate-v2`.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
257 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
258 data = bytearray()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
259 root_nodes_start = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
260 root_nodes_len = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
261 nodes_with_entry_count = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
262 nodes_with_copy_source_count = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
263 # 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: 48233
diff changeset
264 # to disk
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
265 unreachable_bytes = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
266 unused = b'\x00' * 4
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
267 # 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: 48233
diff changeset
268 ignore_patterns_hash = b'\x00' * 20
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
269
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
270 if len(map) == 0:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
271 tree_metadata = TREE_METADATA.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
272 root_nodes_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
273 root_nodes_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
274 nodes_with_entry_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
275 nodes_with_copy_source_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
276 unreachable_bytes,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
277 unused,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
278 ignore_patterns_hash,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
279 )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
280 return data, tree_metadata
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
281
49542
fc719967efd0 dirstate-v2: fix edge case where entries aren't sorted
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49540
diff changeset
282 sorted_map = sorted(map.items(), key=lambda x: x[0].split(b"/"))
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
283
49539
07b9ca52a378 dirstate-v2: fix typos in docstrings
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49538
diff changeset
284 # Use a stack to have to only remember the nodes we currently need
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
285 # instead of building the entire tree in memory
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
286 stack = []
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
287 current_node = Node(b"", None)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
288 stack.append(current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
289
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
290 for index, (path, entry) in enumerate(sorted_map, 1):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
291 nodes_with_entry_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
292 if path in copy_map:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
293 nodes_with_copy_source_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
294 current_folder = get_folder(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
295 current_node = move_to_correct_node_in_tree(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
296 current_folder, current_node, stack
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
297 )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
298
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
299 current_node.children_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
300 # Entries from `map` are never `None`
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
301 if entry.tracked:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
302 current_node.tracked_descendants += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
303 current_node.descendants_with_entry += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
304 stack.append(Node(path, entry, current_node))
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
305
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
306 should_pack = True
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
307 next_path = None
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
308 if index < len(sorted_map):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
309 # 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: 48233
diff changeset
310 # pack yet
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
311 next_path = sorted_map[index][0]
48373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
312 should_pack = not is_ancestor(next_path, current_folder)
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
313 if should_pack:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
314 pack_directory_children(current_node, copy_map, data, stack)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
315 while stack and current_node.path != b"":
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
316 # 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: 48233
diff changeset
317 # entry (if any, otherwise the root)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
318 parent = current_node.parent
48373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
319 in_ancestor_of_next_path = next_path is not None and (
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
320 is_ancestor(next_path, get_folder(stack[-1].path))
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
321 )
48373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
322 if parent is None or in_ancestor_of_next_path:
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
323 break
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
324 pack_directory_children(parent, copy_map, data, stack)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
325 current_node = parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
326
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
327 # 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: 48233
diff changeset
328 # children to the docket
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
329 current_node = stack.pop()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
330 assert current_node.path == b"", current_node.path
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
331 assert len(stack) == 0, len(stack)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
332
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
333 tree_metadata = TREE_METADATA.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
334 current_node.children_offset,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
335 current_node.children_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
336 nodes_with_entry_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
337 nodes_with_copy_source_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
338 unreachable_bytes,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
339 unused,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
340 ignore_patterns_hash,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
341 )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
342
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
343 return data, tree_metadata
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
344
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
345
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
346 def get_folder(path):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
347 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
348 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: 48233
diff changeset
349 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
350 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: 48233
diff changeset
351
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
352
48373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
353 def is_ancestor(path, maybe_ancestor):
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
354 """Returns whether `maybe_ancestor` is an ancestor of `path`.
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
355
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
356 >>> is_ancestor(b"a", b"")
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
357 True
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
358 >>> is_ancestor(b"a/b/c", b"a/b/c")
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
359 False
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
360 >>> is_ancestor(b"hgext3rd/__init__.py", b"hgext")
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
361 False
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
362 >>> is_ancestor(b"hgext3rd/__init__.py", b"hgext3rd")
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
363 True
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
364 """
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
365 if maybe_ancestor == b"":
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
366 return True
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
367 if path <= maybe_ancestor:
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
368 return False
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
369 path_components = path.split(b"/")
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
370 ancestor_components = maybe_ancestor.split(b"/")
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
371 return all(c == o for c, o in zip(path_components, ancestor_components))
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
372
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
373
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
374 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: 48233
diff changeset
375 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
376 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: 48233
diff changeset
377 `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: 48233
diff changeset
378 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
379 while target_folder != current_node.path:
48373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48275
diff changeset
380 if is_ancestor(target_folder, current_node.path):
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
381 # We need to go down a folder
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
382 prefix = target_folder[len(current_node.path) :].lstrip(b'/')
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
383 subfolder_name = prefix.split(b'/', 1)[0]
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
384 if current_node.path:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
385 subfolder_path = current_node.path + b'/' + subfolder_name
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
386 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
387 subfolder_path = subfolder_name
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
388 next_node = stack[-1]
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
389 if next_node.path == target_folder:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
390 # 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: 48233
diff changeset
391 # merge with the last node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
392 current_node = next_node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
393 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
394 current_node.children_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
395 current_node = Node(subfolder_path, None, current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
396 stack.append(current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
397 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
398 # We need to go up a folder
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
399 current_node = current_node.parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
400 return current_node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
401
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
402
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
403 def pack_directory_children(node, copy_map, data, stack):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
404 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
405 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: 48233
diff changeset
406 `data`
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
407 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
408 direct_children = []
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
409
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
410 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: 48233
diff changeset
411 direct_children.append(stack.pop())
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
412 if not direct_children:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
413 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: 48233
diff changeset
414
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
415 # Reverse the stack to get the correct sorted order
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
416 direct_children.reverse()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
417 packed_children = bytearray()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
418 # 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: 48233
diff changeset
419 for child in direct_children:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
420 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: 48233
diff changeset
421 packed_children.extend(packed)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
422 data.extend(child.path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
423 data.extend(copy_map.get(child.path, b""))
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
424 node.tracked_descendants += child.tracked_descendants
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
425 node.descendants_with_entry += child.descendants_with_entry
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
426 # Write the fixed-size child nodes all together
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
427 node.children_offset = len(data)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48233
diff changeset
428 data.extend(packed_children)