Mercurial > public > mercurial-scm > hg-stable
comparison rust/hg-core/src/dirstate_tree/dispatch.rs @ 47107:787ff5d21bcd
dirstate-tree: Make Rust DirstateMap bindings go through a trait object
This changeset starts a series that adds an experiment to make status faster
by changing the dirstate (first only in memory and later also on disk) to
be shaped as a tree matching the directory structure, instead of the current
flat collection of entries. The status algorithm can then traverse this tree
dirstate at the same time as it traverses the filesystem.
We (Octobus) have made prototypes that show promising results but are prone
to bitrot. We would like to start upstreaming some experimental Rust code that
goes in this direction, but to avoid disrupting users it should only be
enabled by some run-time opt-in while keeping the existing dirstate structure
and status algorithm as-is.
The `DirstateMap` type and `status` function look like the appropriate
boundary. This adds a new trait that abstracts everything Python bindings need
and makes those bindings go through a `dyn` trait object. Later we?ll have two
implementations of this trait, and the same bindings can use either.
Differential Revision: https://phab.mercurial-scm.org/D10362
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Tue, 30 Mar 2021 14:15:23 +0200 |
parents | |
children | e061a1df32a8 |
comparison
equal
deleted
inserted
replaced
47106:102a50746bc5 | 47107:787ff5d21bcd |
---|---|
1 use std::collections::HashSet; | |
2 use std::path::PathBuf; | |
3 use std::time::Duration; | |
4 | |
5 use crate::matchers::Matcher; | |
6 use crate::utils::hg_path::{HgPath, HgPathBuf}; | |
7 use crate::CopyMapIter; | |
8 use crate::DirstateEntry; | |
9 use crate::DirstateError; | |
10 use crate::DirstateMap; | |
11 use crate::DirstateMapError; | |
12 use crate::DirstateParents; | |
13 use crate::DirstateStatus; | |
14 use crate::EntryState; | |
15 use crate::FastHashMap; | |
16 use crate::HgPathCow; | |
17 use crate::PatternFileWarning; | |
18 use crate::StateMapIter; | |
19 use crate::StatusError; | |
20 use crate::StatusOptions; | |
21 | |
22 pub trait DirstateMapMethods { | |
23 fn clear(&mut self); | |
24 | |
25 fn add_file( | |
26 &mut self, | |
27 filename: &HgPath, | |
28 old_state: EntryState, | |
29 entry: DirstateEntry, | |
30 ) -> Result<(), DirstateMapError>; | |
31 | |
32 fn remove_file( | |
33 &mut self, | |
34 filename: &HgPath, | |
35 old_state: EntryState, | |
36 size: i32, | |
37 ) -> Result<(), DirstateMapError>; | |
38 | |
39 fn drop_file( | |
40 &mut self, | |
41 filename: &HgPath, | |
42 old_state: EntryState, | |
43 ) -> Result<bool, DirstateMapError>; | |
44 | |
45 fn clear_ambiguous_times(&mut self, filenames: Vec<HgPathBuf>, now: i32); | |
46 | |
47 fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool; | |
48 | |
49 fn non_normal_entries_union( | |
50 &mut self, | |
51 other: HashSet<HgPathBuf>, | |
52 ) -> Vec<HgPathBuf>; | |
53 | |
54 fn set_non_normal_other_parent_entries(&mut self, force: bool); | |
55 | |
56 fn get_non_normal_other_parent_entries_panic( | |
57 &self, | |
58 ) -> (&HashSet<HgPathBuf>, &HashSet<HgPathBuf>); | |
59 | |
60 fn get_non_normal_other_parent_entries( | |
61 &mut self, | |
62 ) -> (&mut HashSet<HgPathBuf>, &mut HashSet<HgPathBuf>); | |
63 | |
64 fn has_tracked_dir( | |
65 &mut self, | |
66 directory: &HgPath, | |
67 ) -> Result<bool, DirstateMapError>; | |
68 | |
69 fn has_dir( | |
70 &mut self, | |
71 directory: &HgPath, | |
72 ) -> Result<bool, DirstateMapError>; | |
73 | |
74 fn parents( | |
75 &mut self, | |
76 file_contents: &[u8], | |
77 ) -> Result<&DirstateParents, DirstateError>; | |
78 | |
79 fn set_parents(&mut self, parents: &DirstateParents); | |
80 | |
81 fn read<'a>( | |
82 &mut self, | |
83 file_contents: &'a [u8], | |
84 ) -> Result<Option<&'a DirstateParents>, DirstateError>; | |
85 | |
86 fn pack( | |
87 &mut self, | |
88 parents: DirstateParents, | |
89 now: Duration, | |
90 ) -> Result<Vec<u8>, DirstateError>; | |
91 | |
92 fn build_file_fold_map(&mut self) -> &FastHashMap<HgPathBuf, HgPathBuf>; | |
93 | |
94 fn set_all_dirs(&mut self) -> Result<(), DirstateMapError>; | |
95 | |
96 fn set_dirs(&mut self) -> Result<(), DirstateMapError>; | |
97 | |
98 fn status<'a>( | |
99 &'a self, | |
100 matcher: &'a (dyn Matcher + Sync), | |
101 root_dir: PathBuf, | |
102 ignore_files: Vec<PathBuf>, | |
103 options: StatusOptions, | |
104 ) -> Result< | |
105 ( | |
106 (Vec<HgPathCow<'a>>, DirstateStatus<'a>), | |
107 Vec<PatternFileWarning>, | |
108 ), | |
109 StatusError, | |
110 >; | |
111 | |
112 fn copy_map_len(&self) -> usize; | |
113 | |
114 fn copy_map_iter(&self) -> CopyMapIter<'_>; | |
115 | |
116 fn copy_map_contains_key(&self, key: &HgPath) -> bool; | |
117 | |
118 fn copy_map_get(&self, key: &HgPath) -> Option<&HgPathBuf>; | |
119 | |
120 fn copy_map_remove(&mut self, key: &HgPath) -> Option<HgPathBuf>; | |
121 | |
122 fn copy_map_insert( | |
123 &mut self, | |
124 key: HgPathBuf, | |
125 value: HgPathBuf, | |
126 ) -> Option<HgPathBuf>; | |
127 | |
128 fn len(&self) -> usize; | |
129 | |
130 fn contains_key(&self, key: &HgPath) -> bool; | |
131 | |
132 fn get(&self, key: &HgPath) -> Option<&DirstateEntry>; | |
133 | |
134 fn iter(&self) -> StateMapIter<'_>; | |
135 } | |
136 | |
137 impl DirstateMapMethods for DirstateMap { | |
138 fn clear(&mut self) { | |
139 self.clear() | |
140 } | |
141 | |
142 fn add_file( | |
143 &mut self, | |
144 filename: &HgPath, | |
145 old_state: EntryState, | |
146 entry: DirstateEntry, | |
147 ) -> Result<(), DirstateMapError> { | |
148 self.add_file(filename, old_state, entry) | |
149 } | |
150 | |
151 fn remove_file( | |
152 &mut self, | |
153 filename: &HgPath, | |
154 old_state: EntryState, | |
155 size: i32, | |
156 ) -> Result<(), DirstateMapError> { | |
157 self.remove_file(filename, old_state, size) | |
158 } | |
159 | |
160 fn drop_file( | |
161 &mut self, | |
162 filename: &HgPath, | |
163 old_state: EntryState, | |
164 ) -> Result<bool, DirstateMapError> { | |
165 self.drop_file(filename, old_state) | |
166 } | |
167 | |
168 fn clear_ambiguous_times(&mut self, filenames: Vec<HgPathBuf>, now: i32) { | |
169 self.clear_ambiguous_times(filenames, now) | |
170 } | |
171 | |
172 fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool { | |
173 self.non_normal_entries_remove(key) | |
174 } | |
175 | |
176 fn non_normal_entries_union( | |
177 &mut self, | |
178 other: HashSet<HgPathBuf>, | |
179 ) -> Vec<HgPathBuf> { | |
180 self.non_normal_entries_union(other) | |
181 } | |
182 | |
183 fn set_non_normal_other_parent_entries(&mut self, force: bool) { | |
184 self.set_non_normal_other_parent_entries(force) | |
185 } | |
186 | |
187 fn get_non_normal_other_parent_entries_panic( | |
188 &self, | |
189 ) -> (&HashSet<HgPathBuf>, &HashSet<HgPathBuf>) { | |
190 self.get_non_normal_other_parent_entries_panic() | |
191 } | |
192 | |
193 fn get_non_normal_other_parent_entries( | |
194 &mut self, | |
195 ) -> (&mut HashSet<HgPathBuf>, &mut HashSet<HgPathBuf>) { | |
196 self.get_non_normal_other_parent_entries() | |
197 } | |
198 | |
199 fn has_tracked_dir( | |
200 &mut self, | |
201 directory: &HgPath, | |
202 ) -> Result<bool, DirstateMapError> { | |
203 self.has_tracked_dir(directory) | |
204 } | |
205 | |
206 fn has_dir( | |
207 &mut self, | |
208 directory: &HgPath, | |
209 ) -> Result<bool, DirstateMapError> { | |
210 self.has_dir(directory) | |
211 } | |
212 | |
213 fn parents( | |
214 &mut self, | |
215 file_contents: &[u8], | |
216 ) -> Result<&DirstateParents, DirstateError> { | |
217 self.parents(file_contents) | |
218 } | |
219 | |
220 fn set_parents(&mut self, parents: &DirstateParents) { | |
221 self.set_parents(parents) | |
222 } | |
223 | |
224 fn read<'a>( | |
225 &mut self, | |
226 file_contents: &'a [u8], | |
227 ) -> Result<Option<&'a DirstateParents>, DirstateError> { | |
228 self.read(file_contents) | |
229 } | |
230 | |
231 fn pack( | |
232 &mut self, | |
233 parents: DirstateParents, | |
234 now: Duration, | |
235 ) -> Result<Vec<u8>, DirstateError> { | |
236 self.pack(parents, now) | |
237 } | |
238 | |
239 fn build_file_fold_map(&mut self) -> &FastHashMap<HgPathBuf, HgPathBuf> { | |
240 self.build_file_fold_map() | |
241 } | |
242 | |
243 fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> { | |
244 self.set_all_dirs() | |
245 } | |
246 | |
247 fn set_dirs(&mut self) -> Result<(), DirstateMapError> { | |
248 self.set_dirs() | |
249 } | |
250 | |
251 fn status<'a>( | |
252 &'a self, | |
253 matcher: &'a (dyn Matcher + Sync), | |
254 root_dir: PathBuf, | |
255 ignore_files: Vec<PathBuf>, | |
256 options: StatusOptions, | |
257 ) -> Result< | |
258 ( | |
259 (Vec<HgPathCow<'a>>, DirstateStatus<'a>), | |
260 Vec<PatternFileWarning>, | |
261 ), | |
262 StatusError, | |
263 > { | |
264 crate::status(self, matcher, root_dir, ignore_files, options) | |
265 } | |
266 | |
267 fn copy_map_len(&self) -> usize { | |
268 self.copy_map.len() | |
269 } | |
270 | |
271 fn copy_map_iter(&self) -> CopyMapIter<'_> { | |
272 Box::new(self.copy_map.iter()) | |
273 } | |
274 | |
275 fn copy_map_contains_key(&self, key: &HgPath) -> bool { | |
276 self.copy_map.contains_key(key) | |
277 } | |
278 | |
279 fn copy_map_get(&self, key: &HgPath) -> Option<&HgPathBuf> { | |
280 self.copy_map.get(key) | |
281 } | |
282 | |
283 fn copy_map_remove(&mut self, key: &HgPath) -> Option<HgPathBuf> { | |
284 self.copy_map.remove(key) | |
285 } | |
286 | |
287 fn copy_map_insert( | |
288 &mut self, | |
289 key: HgPathBuf, | |
290 value: HgPathBuf, | |
291 ) -> Option<HgPathBuf> { | |
292 self.copy_map.insert(key, value) | |
293 } | |
294 | |
295 fn len(&self) -> usize { | |
296 (&**self).len() | |
297 } | |
298 | |
299 fn contains_key(&self, key: &HgPath) -> bool { | |
300 (&**self).contains_key(key) | |
301 } | |
302 | |
303 fn get(&self, key: &HgPath) -> Option<&DirstateEntry> { | |
304 (&**self).get(key) | |
305 } | |
306 | |
307 fn iter(&self) -> StateMapIter<'_> { | |
308 Box::new((&**self).iter()) | |
309 } | |
310 } |