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 }