annotate mercurial/dirstateutils/v2.py @ 51901:f4733654f144

typing: add `from __future__ import annotations` to most files Now that py36 is no longer supported, we can postpone annotation evaluation. This means that the quoting is usually optional (for things imported under the guard of `if typing.TYPE_CHECKING:` to avoid circular imports), and there's less overhead on startup[1]. There may be some missing here. I backed out 6000f5b25c9b (which removed the `from __future__ import ...` that was supporting py2), reverted the changes in `contrib/`, `doc/`, and `tests/`, and then ran: $ hg status -n --change . | \ xargs sed -i -e 's/from __future__ import .*$/from __future__ import annotations/' There were some minor tweaks needed when reviewing (mostly making the spacing around the import consistent, and `mercurial/testing/__init__.py` had a multiline import that wasn't fully rewritten. [1] https://docs.python.org/3/whatsnew/3.7.html#pep-563-postponed-evaluation-of-annotations
author Matt Harbison <matt_harbison@yahoo.com>
date Mon, 16 Sep 2024 15:36:44 +0200
parents 278af66e6595
children
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
51901
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 51788
diff changeset
8 from __future__ import annotations
48233
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
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
11 import typing
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
12
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
13 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
14
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 # 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
16 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
17 # 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
18 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
19
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
20 from .. import error, policy
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
21
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
22 parsers = policy.importmod('parsers')
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
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
25 # Must match the constant of the same name in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
26 # `rust/hg-core/src/dirstate_tree/on_disk.rs`
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
27 TREE_METADATA_SIZE = 44
48243
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48240
diff changeset
28 NODE_SIZE = 44
48233
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
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
31 # Must match the `TreeMetadata` Rust struct in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
32 # `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
33 #
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
34 # * 4 bytes: start offset of root nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
35 # * 4 bytes: number of root nodes
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 an entry
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
37 # * 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
38 # * 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
39 # * 4 bytes: unused
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
40 # * 20 bytes: SHA-1 hash of ignore patterns
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
41 TREE_METADATA = struct.Struct('>LLLLL4s20s')
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
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
44 # Must match the `Node` Rust struct in
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
45 # `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
46 #
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
47 # * 4 bytes: start offset of full path
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
48 # * 2 bytes: length of the full path
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
49 # * 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
50 # * 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
51 # * 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
52 # * 4 bytes: start offset of child nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
53 # * 4 bytes: number of child nodes
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
54 # * 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
55 # * 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
56 # * 1 byte: flags
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
57 # * 4 bytes: expected size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
58 # * 4 bytes: mtime seconds
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
59 # * 4 bytes: mtime nanoseconds
48243
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48240
diff changeset
60 NODE = struct.Struct('>LHHLHLLLLHlll')
48233
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
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
63 assert TREE_METADATA_SIZE == TREE_METADATA.size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
64 assert NODE_SIZE == NODE.size
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
65
48275
bb240915f69f dirstate-v2: adjust the meaning of directory flags
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
66 # 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
67 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
68
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
69
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
70 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
71 """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
72
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
73 - map: a {path: entry} mapping that will be filled
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
74 - 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
75 - data: a binary blob contains v2 nodes data
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
76 - 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
77 """
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
78 (
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
79 root_nodes_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
80 root_nodes_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
81 _nodes_with_entry_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
82 _nodes_with_copy_source_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
83 _unreachable_bytes,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
84 _unused,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
85 _ignore_patterns_hash,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
86 ) = TREE_METADATA.unpack(tree_metadata)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
87 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
88
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
89
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
90 def parse_nodes(map, copy_map, data, start, len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
91 """parse <len> nodes from <data> starting at offset <start>
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
92
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
93 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
94
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
95 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
96 processing (DIRECTORY, ALL_UNKNOWN_RECORDED, ALL_IGNORED_RECORDED)
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
97 """
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
98 for i in range(len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
99 node_start = start + NODE_SIZE * i
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
100 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
101 (
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
102 path_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
103 path_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
104 _basename_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
105 copy_source_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
106 copy_source_len,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
107 children_start,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
108 children_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
109 _descendants_with_entry_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
110 _tracked_descendants_count,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
111 flags,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
112 size,
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
113 mtime_s,
48274
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48271
diff changeset
114 mtime_ns,
48233
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
115 ) = NODE.unpack(node_bytes)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
116
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
117 # Parse child nodes of this node recursively
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
118 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
119
48271
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
120 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
121 if not item.any_tracked:
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
122 continue
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
123 path = slice_with_len(data, path_start, path_len)
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
124 map[path] = item
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
125 if copy_source_start:
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
126 copy_map[path] = slice_with_len(
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
127 data, copy_source_start, copy_source_len
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
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
131 def slice_with_len(data, start, len):
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
132 return data[start : start + len]
48234
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
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
135 @attr.s
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
136 class Node:
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
137 path = attr.ib()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
138 entry = attr.ib()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
139 parent = attr.ib(default=None)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
140 children_count = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
141 children_offset = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
142 descendants_with_entry = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
143 tracked_descendants = attr.ib(default=0)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
144
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
145 def pack(self, copy_map, paths_offset):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
146 path = self.path
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
147 copy = copy_map.get(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
148 entry = self.entry
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
149
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
150 path_start = paths_offset
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
151 path_len = len(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
152 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
153 if copy is not None:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
154 copy_source_start = paths_offset + len(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
155 copy_source_len = len(copy)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
156 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
157 copy_source_start = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
158 copy_source_len = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
159 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
160 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
161 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
162 # 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
163 flags = DIRSTATE_V2_DIRECTORY
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
164 size = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
165 mtime_s = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
166 mtime_ns = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
167 return NODE.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
168 path_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
169 path_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
170 basename_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
171 copy_source_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
172 copy_source_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
173 self.children_offset,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
174 self.children_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
175 self.descendants_with_entry,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
176 self.tracked_descendants,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
177 flags,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
178 size,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
179 mtime_s,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
180 mtime_ns,
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
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
183
48440
434de12918fd dirstate: remove need_delay logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48275
diff changeset
184 def pack_dirstate(map, copy_map):
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
185 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
186 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
187 the tuple of (data, metadata) bytearrays.
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
188
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
189 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
190 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
191 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
192 format in `mercurial/helptext/internals/dirstate-v2`.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
193
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
194 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
195 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
196 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
197 format.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
198
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
199 # Algorithm explanation
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
200
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
201 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
202 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
203 algorithm is in place.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
204
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
205 ## Building a subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
206
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
207 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
208 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
209 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
210 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
211 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
212 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
213 of the tree lazily.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
214 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
215 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
216 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
217 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
218 `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
219 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
220 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
221 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
222 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
223 the subtree we're in is complete.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
224
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
225 ## Writing the subtree
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
226
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
227 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
228 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
229 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
230 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
231 we hit the "other" subtree.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
232
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
233 An example:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
234 a
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
235 dir1/b
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
236 dir1/c
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
237 dir2/dir3/d
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
238 dir2/dir3/e
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
239 dir2/f
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
240
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
241 Would have us:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
242 - 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
243 - 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
244 - 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
245 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
246 - go back up to "dir2"
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
247 - add "dir2/f" to the stack
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
248 - realize we're done with the map
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
249 - 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
250 - 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
251 that order
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
252
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
253 ## Special case for the root node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
254
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
255 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
256 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
257 `mercurial/helptext/internals/dirstate-v2`.
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
258 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
259 data = bytearray()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
260 root_nodes_start = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
261 root_nodes_len = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
262 nodes_with_entry_count = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
263 nodes_with_copy_source_count = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
264 # 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
265 # to disk
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
266 unreachable_bytes = 0
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
267 unused = b'\x00' * 4
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
268 # 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
269 ignore_patterns_hash = b'\x00' * 20
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
270
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
271 if len(map) == 0:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
272 tree_metadata = TREE_METADATA.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
273 root_nodes_start,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
274 root_nodes_len,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
275 nodes_with_entry_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
276 nodes_with_copy_source_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
277 unreachable_bytes,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
278 unused,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
279 ignore_patterns_hash,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
280 )
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
281 return data, tree_metadata
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
282
49542
fc719967efd0 dirstate-v2: fix edge case where entries aren't sorted
Raphaël Gomès <rgomes@octobus.net>
parents: 49540
diff changeset
283 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
284
49539
07b9ca52a378 dirstate-v2: fix typos in docstrings
Raphaël Gomès <rgomes@octobus.net>
parents: 49538
diff changeset
285 # 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
286 # 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
287 stack = []
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
288 current_node = Node(b"", None)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
289 stack.append(current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
290
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
291 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
292 nodes_with_entry_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
293 if path in copy_map:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
294 nodes_with_copy_source_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
295 current_folder = get_folder(path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
296 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
297 current_folder, current_node, stack
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
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
300 current_node.children_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
301 # Entries from `map` are never `None`
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
302 if entry.tracked:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
303 current_node.tracked_descendants += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
304 current_node.descendants_with_entry += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
305 stack.append(Node(path, entry, current_node))
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
306
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
307 should_pack = True
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
308 next_path = None
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
309 if index < len(sorted_map):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
310 # 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
311 # pack yet
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
312 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
313 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
314 if should_pack:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
315 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
316 while stack and current_node.path != b"":
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
317 # 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
318 # entry (if any, otherwise the root)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
319 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
320 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
321 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
322 )
48373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
323 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
324 break
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
325 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
326 current_node = parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
327
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
328 # 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
329 # children to the docket
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
330 current_node = stack.pop()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
331 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
332 assert len(stack) == 0, len(stack)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
333
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
334 tree_metadata = TREE_METADATA.pack(
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
335 current_node.children_offset,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
336 current_node.children_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
337 nodes_with_entry_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
338 nodes_with_copy_source_count,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
339 unreachable_bytes,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
340 unused,
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
341 ignore_patterns_hash,
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
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
344 return data, tree_metadata
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
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
347 def get_folder(path):
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
348 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
349 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
350 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
351 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
352
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
353
48373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
354 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
355 """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
356
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
357 >>> 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
358 True
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
359 >>> 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
360 False
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
361 >>> 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
362 False
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
363 >>> 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
364 True
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
365 """
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
366 if maybe_ancestor == b"":
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
367 return True
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
368 if path <= maybe_ancestor:
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
369 return False
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
370 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
371 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
372 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
373
46d12f7762e4 dirstate-v2: fix infinite loop in pure packer
Raphaël Gomès <rgomes@octobus.net>
parents: 48275
diff changeset
374
48234
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
375 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
376 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
377 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
378 `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
379 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
380 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
381 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
382 # We need to go down a folder
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
383 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
384 subfolder_name = prefix.split(b'/', 1)[0]
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
385 if current_node.path:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
386 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
387 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
388 subfolder_path = subfolder_name
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
389 next_node = stack[-1]
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
390 if next_node.path == target_folder:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
391 # 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
392 # merge with the last node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
393 current_node = next_node
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
394 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
395 current_node.children_count += 1
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
396 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
397 stack.append(current_node)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
398 else:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
399 # We need to go up a folder
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
400 current_node = current_node.parent
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
401 return current_node
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
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
404 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
405 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
406 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
407 `data`
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
408 """
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
409 direct_children = []
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
410
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
411 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
412 direct_children.append(stack.pop())
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
413 if not direct_children:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
414 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
415
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
416 # 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
417 direct_children.reverse()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
418 packed_children = bytearray()
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
419 # 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
420 for child in direct_children:
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
421 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
422 packed_children.extend(packed)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
423 data.extend(child.path)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
424 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
425 node.tracked_descendants += child.tracked_descendants
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
426 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
427 # 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
428 node.children_offset = len(data)
7e78c72ee3ea dirstate-v2: Initial Python serializer
Raphaël Gomès <rgomes@octobus.net>
parents: 48233
diff changeset
429 data.extend(packed_children)