Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/examples/nodemap/index.rs @ 47385:f6bb181c75f8
rust: Parse "subinclude"d files along the way, not later
When parsing a `.hgignore` file and encountering an `include:` line,
the included file is parsed recursively right then in a depth-first fashion.
With `subinclude:` however included files were parsed (recursively) much later.
This changes it to be expanded during parsing, like `.hgignore`.
The motivation for this is an upcoming changeset that needs to detect changes
in which files are ignored or not. The plan is to hash all ignore files while
they are being read, and store that hash in the dirstate (in v2 format).
In order to allow a potential alternative implementations to read that format,
the algorithm to compute that hash must be documented. Having a well-defined
depth-first ordering for the tree of (sub-)included files makes that easier.
Differential Revision: https://phab.mercurial-scm.org/D10834
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Wed, 02 Jun 2021 18:03:43 +0200 |
parents | 8f7c6656ac79 |
children | e834b79def74 |
rev | line source |
---|---|
44417
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
1 // Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net> |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
2 // |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
3 // This software may be used and distributed according to the terms of the |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
4 // GNU General Public License version 2 or any later version. |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
5 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
6 //! Minimal `RevlogIndex`, readable from standard Mercurial file format |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
7 use hg::*; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
8 use memmap::*; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
9 use std::fs::File; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
10 use std::ops::Deref; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
11 use std::path::Path; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
12 use std::slice; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
13 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
14 pub struct Index { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
15 data: Box<dyn Deref<Target = [IndexEntry]> + Send>, |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
16 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
17 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
18 /// A fixed sized index entry. All numbers are big endian |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
19 #[repr(C)] |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
20 pub struct IndexEntry { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
21 not_used_yet: [u8; 24], |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
22 p1: Revision, |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
23 p2: Revision, |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
24 node: Node, |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
25 unused_node: [u8; 12], |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
26 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
27 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
28 pub const INDEX_ENTRY_SIZE: usize = 64; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
29 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
30 impl IndexEntry { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
31 fn parents(&self) -> [Revision; 2] { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
32 [Revision::from_be(self.p1), Revision::from_be(self.p1)] |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
33 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
34 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
35 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
36 impl RevlogIndex for Index { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
37 fn len(&self) -> usize { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
38 self.data.len() |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
39 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
40 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
41 fn node(&self, rev: Revision) -> Option<&Node> { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
42 if rev == NULL_REVISION { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
43 return None; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
44 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
45 let i = rev as usize; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
46 if i >= self.len() { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
47 None |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
48 } else { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
49 Some(&self.data[i].node) |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
50 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
51 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
52 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
53 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
54 impl Graph for &Index { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
55 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
56 let [p1, p2] = (*self).data[rev as usize].parents(); |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
57 let len = (*self).len(); |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
58 if p1 < NULL_REVISION |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
59 || p2 < NULL_REVISION |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
60 || p1 as usize >= len |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
61 || p2 as usize >= len |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
62 { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
63 return Err(GraphError::ParentOutOfRange(rev)); |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
64 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
65 Ok([p1, p2]) |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
66 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
67 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
68 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
69 struct IndexMmap(Mmap); |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
70 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
71 impl Deref for IndexMmap { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
72 type Target = [IndexEntry]; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
73 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
74 fn deref(&self) -> &[IndexEntry] { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
75 let ptr = self.0.as_ptr() as *const IndexEntry; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
76 // Any misaligned data will be ignored. |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
77 debug_assert_eq!( |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
78 self.0.len() % std::mem::align_of::<IndexEntry>(), |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
79 0, |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
80 "Misaligned data in mmap" |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
81 ); |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
82 unsafe { slice::from_raw_parts(ptr, self.0.len() / INDEX_ENTRY_SIZE) } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
83 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
84 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
85 |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
86 impl Index { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
87 pub fn load_mmap(path: impl AsRef<Path>) -> Self { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
88 let file = File::open(path).unwrap(); |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
89 let msg = "Index file is missing, or missing permission"; |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
90 let mmap = unsafe { MmapOptions::new().map(&file) }.expect(msg); |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
91 Self { |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
92 data: Box::new(IndexMmap(mmap)), |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
93 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
94 } |
8f7c6656ac79
rust-nodemap: pure Rust example
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
95 } |