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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }