Mercurial > hg
comparison rust/hg-core/src/dirstate_tree/on_disk.rs @ 47409:0ef8231e413f
dirstate-v2: Store a hash of ignore patterns (.hgignore)
Later, this help extend `read_dir` caching to directories that contain ignored
files (but no unknown files). Such cache must be invalidated when ignore patterns
change since a formerly-ignored file might become unknown.
This helps the default configuration of `hg status` where unknown files must
be listed, but ignored files are not.
Differential Revision: https://phab.mercurial-scm.org/D10836
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Wed, 02 Jun 2021 11:25:18 +0200 |
parents | bd88b6bfd8da |
children | 94e38822d395 |
comparison
equal
deleted
inserted
replaced
47408:7954ee2d7cf7 | 47409:0ef8231e413f |
---|---|
26 /// Added at the start of `.hg/dirstate` when the "v2" format is used. | 26 /// Added at the start of `.hg/dirstate` when the "v2" format is used. |
27 /// This a redundant sanity check more than an actual "magic number" since | 27 /// This a redundant sanity check more than an actual "magic number" since |
28 /// `.hg/requires` already governs which format should be used. | 28 /// `.hg/requires` already governs which format should be used. |
29 pub const V2_FORMAT_MARKER: &[u8; 12] = b"dirstate-v2\n"; | 29 pub const V2_FORMAT_MARKER: &[u8; 12] = b"dirstate-v2\n"; |
30 | 30 |
31 pub(super) const IGNORE_PATTERNS_HASH_LEN: usize = 20; | |
32 pub(super) type IgnorePatternsHash = [u8; IGNORE_PATTERNS_HASH_LEN]; | |
33 | |
31 #[derive(BytesCast)] | 34 #[derive(BytesCast)] |
32 #[repr(C)] | 35 #[repr(C)] |
33 struct Header { | 36 struct Header { |
34 marker: [u8; V2_FORMAT_MARKER.len()], | 37 marker: [u8; V2_FORMAT_MARKER.len()], |
35 | 38 |
38 parents: DirstateParents, | 41 parents: DirstateParents, |
39 | 42 |
40 root: ChildNodes, | 43 root: ChildNodes, |
41 nodes_with_entry_count: Size, | 44 nodes_with_entry_count: Size, |
42 nodes_with_copy_source_count: Size, | 45 nodes_with_copy_source_count: Size, |
46 | |
47 /// If non-zero, a hash of ignore files that were used for some previous | |
48 /// run of the `status` algorithm. | |
49 /// | |
50 /// We define: | |
51 /// | |
52 /// * "Root" ignore files are `.hgignore` at the root of the repository if | |
53 /// it exists, and files from `ui.ignore.*` config. This set of files is | |
54 /// then sorted by the string representation of their path. | |
55 /// * The "expanded contents" of an ignore files is the byte string made | |
56 /// by concatenating its contents with the "expanded contents" of other | |
57 /// files included with `include:` or `subinclude:` files, in inclusion | |
58 /// order. This definition is recursive, as included files can | |
59 /// themselves include more files. | |
60 /// | |
61 /// This hash is defined as the SHA-1 of the concatenation (in sorted | |
62 /// order) of the "expanded contents" of each "root" ignore file. | |
63 /// (Note that computing this does not require actually concatenating byte | |
64 /// strings into contiguous memory, instead SHA-1 hashing can be done | |
65 /// incrementally.) | |
66 ignore_patterns_hash: IgnorePatternsHash, | |
43 } | 67 } |
44 | 68 |
45 #[derive(BytesCast)] | 69 #[derive(BytesCast)] |
46 #[repr(C)] | 70 #[repr(C)] |
47 pub(super) struct Node { | 71 pub(super) struct Node { |
143 /// Either nothing if `start == 0`, or a `HgPath` of `len` bytes | 167 /// Either nothing if `start == 0`, or a `HgPath` of `len` bytes |
144 type OptPathSlice = Slice; | 168 type OptPathSlice = Slice; |
145 | 169 |
146 /// Make sure that size-affecting changes are made knowingly | 170 /// Make sure that size-affecting changes are made knowingly |
147 fn _static_assert_size_of() { | 171 fn _static_assert_size_of() { |
148 let _ = std::mem::transmute::<Header, [u8; 72]>; | 172 let _ = std::mem::transmute::<Header, [u8; 92]>; |
149 let _ = std::mem::transmute::<Node, [u8; 57]>; | 173 let _ = std::mem::transmute::<Node, [u8; 57]>; |
150 } | 174 } |
151 | 175 |
152 /// Unexpected file format found in `.hg/dirstate` with the "v2" format. | 176 /// Unexpected file format found in `.hg/dirstate` with the "v2" format. |
153 /// | 177 /// |
195 )?), | 219 )?), |
196 nodes_with_entry_count: header.nodes_with_entry_count.get(), | 220 nodes_with_entry_count: header.nodes_with_entry_count.get(), |
197 nodes_with_copy_source_count: header | 221 nodes_with_copy_source_count: header |
198 .nodes_with_copy_source_count | 222 .nodes_with_copy_source_count |
199 .get(), | 223 .get(), |
224 ignore_patterns_hash: header.ignore_patterns_hash, | |
200 }; | 225 }; |
201 let parents = Some(header.parents.clone()); | 226 let parents = Some(header.parents.clone()); |
202 Ok((dirstate_map, parents)) | 227 Ok((dirstate_map, parents)) |
203 } | 228 } |
204 | 229 |
471 root, | 496 root, |
472 nodes_with_entry_count: dirstate_map.nodes_with_entry_count.into(), | 497 nodes_with_entry_count: dirstate_map.nodes_with_entry_count.into(), |
473 nodes_with_copy_source_count: dirstate_map | 498 nodes_with_copy_source_count: dirstate_map |
474 .nodes_with_copy_source_count | 499 .nodes_with_copy_source_count |
475 .into(), | 500 .into(), |
501 ignore_patterns_hash: dirstate_map.ignore_patterns_hash, | |
476 }; | 502 }; |
477 out[..header_len].copy_from_slice(header.as_bytes()); | 503 out[..header_len].copy_from_slice(header.as_bytes()); |
478 Ok(out) | 504 Ok(out) |
479 } | 505 } |
480 | 506 |