##// END OF EJS Templates
dirstate-tree: Maintain a counter of DirstateEntry’s and copy sources...
Simon Sapin -
r47873:214ae40e default
parent child Browse files
Show More
@@ -1,448 +1,495 b''
1 use bytes_cast::BytesCast;
1 use bytes_cast::BytesCast;
2 use std::path::PathBuf;
2 use std::path::PathBuf;
3 use std::{collections::BTreeMap, convert::TryInto};
3 use std::{collections::BTreeMap, convert::TryInto};
4
4
5 use super::path_with_basename::WithBasename;
5 use super::path_with_basename::WithBasename;
6 use crate::dirstate::parsers::clear_ambiguous_mtime;
6 use crate::dirstate::parsers::clear_ambiguous_mtime;
7 use crate::dirstate::parsers::pack_entry;
7 use crate::dirstate::parsers::pack_entry;
8 use crate::dirstate::parsers::packed_entry_size;
8 use crate::dirstate::parsers::packed_entry_size;
9 use crate::dirstate::parsers::parse_dirstate_entries;
9 use crate::dirstate::parsers::parse_dirstate_entries;
10 use crate::dirstate::parsers::parse_dirstate_parents;
10 use crate::dirstate::parsers::parse_dirstate_parents;
11 use crate::dirstate::parsers::Timestamp;
11 use crate::dirstate::parsers::Timestamp;
12 use crate::matchers::Matcher;
12 use crate::matchers::Matcher;
13 use crate::revlog::node::NULL_NODE;
13 use crate::revlog::node::NULL_NODE;
14 use crate::utils::hg_path::{HgPath, HgPathBuf};
14 use crate::utils::hg_path::{HgPath, HgPathBuf};
15 use crate::CopyMapIter;
15 use crate::CopyMapIter;
16 use crate::DirstateEntry;
16 use crate::DirstateEntry;
17 use crate::DirstateError;
17 use crate::DirstateError;
18 use crate::DirstateMapError;
18 use crate::DirstateMapError;
19 use crate::DirstateParents;
19 use crate::DirstateParents;
20 use crate::DirstateStatus;
20 use crate::DirstateStatus;
21 use crate::EntryState;
21 use crate::EntryState;
22 use crate::FastHashMap;
22 use crate::FastHashMap;
23 use crate::HgPathCow;
23 use crate::HgPathCow;
24 use crate::PatternFileWarning;
24 use crate::PatternFileWarning;
25 use crate::StateMapIter;
25 use crate::StateMapIter;
26 use crate::StatusError;
26 use crate::StatusError;
27 use crate::StatusOptions;
27 use crate::StatusOptions;
28
28
29 pub struct DirstateMap {
29 pub struct DirstateMap {
30 parents: Option<DirstateParents>,
30 parents: Option<DirstateParents>,
31 dirty_parents: bool,
31 dirty_parents: bool,
32 root: ChildNodes,
32 root: ChildNodes,
33
34 /// Number of nodes anywhere in the tree that have `.entry.is_some()`.
35 nodes_with_entry_count: usize,
36
37 /// Number of nodes anywhere in the tree that have
38 /// `.copy_source.is_some()`.
39 nodes_with_copy_source_count: usize,
33 }
40 }
34
41
35 /// Using a plain `HgPathBuf` of the full path from the repository root as a
42 /// Using a plain `HgPathBuf` of the full path from the repository root as a
36 /// map key would also work: all paths in a given map have the same parent
43 /// map key would also work: all paths in a given map have the same parent
37 /// path, so comparing full paths gives the same result as comparing base
44 /// path, so comparing full paths gives the same result as comparing base
38 /// names. However `BTreeMap` would waste time always re-comparing the same
45 /// names. However `BTreeMap` would waste time always re-comparing the same
39 /// string prefix.
46 /// string prefix.
40 type ChildNodes = BTreeMap<WithBasename<HgPathBuf>, Node>;
47 type ChildNodes = BTreeMap<WithBasename<HgPathBuf>, Node>;
41
48
42 #[derive(Default)]
49 #[derive(Default)]
43 struct Node {
50 struct Node {
44 entry: Option<DirstateEntry>,
51 entry: Option<DirstateEntry>,
45 copy_source: Option<HgPathBuf>,
52 copy_source: Option<HgPathBuf>,
46 children: ChildNodes,
53 children: ChildNodes,
47 }
54 }
48
55
49 /// `(full_path, entry, copy_source)`
56 /// `(full_path, entry, copy_source)`
50 type NodeDataMut<'a> = (
57 type NodeDataMut<'a> = (
51 &'a WithBasename<HgPathBuf>,
58 &'a WithBasename<HgPathBuf>,
52 &'a mut Option<DirstateEntry>,
59 &'a mut Option<DirstateEntry>,
53 &'a mut Option<HgPathBuf>,
60 &'a mut Option<HgPathBuf>,
54 );
61 );
55
62
56 impl DirstateMap {
63 impl DirstateMap {
57 pub fn new() -> Self {
64 pub fn new() -> Self {
58 Self {
65 Self {
59 parents: None,
66 parents: None,
60 dirty_parents: false,
67 dirty_parents: false,
61 root: ChildNodes::new(),
68 root: ChildNodes::new(),
69 nodes_with_entry_count: 0,
70 nodes_with_copy_source_count: 0,
62 }
71 }
63 }
72 }
64
73
65 fn get_node(&self, path: &HgPath) -> Option<&Node> {
74 fn get_node(&self, path: &HgPath) -> Option<&Node> {
66 let mut children = &self.root;
75 let mut children = &self.root;
67 let mut components = path.components();
76 let mut components = path.components();
68 let mut component =
77 let mut component =
69 components.next().expect("expected at least one components");
78 components.next().expect("expected at least one components");
70 loop {
79 loop {
71 let child = children.get(component)?;
80 let child = children.get(component)?;
72 if let Some(next_component) = components.next() {
81 if let Some(next_component) = components.next() {
73 component = next_component;
82 component = next_component;
74 children = &child.children;
83 children = &child.children;
75 } else {
84 } else {
76 return Some(child);
85 return Some(child);
77 }
86 }
78 }
87 }
79 }
88 }
80
89
81 fn get_or_insert_node(&mut self, path: &HgPath) -> &mut Node {
90 /// This takes `root` instead of `&mut self` so that callers can mutate
82 let mut child_nodes = &mut self.root;
91 /// other fields while the returned borrow is still valid
92 fn get_or_insert_node<'tree>(
93 root: &'tree mut ChildNodes,
94 path: &HgPath,
95 ) -> &'tree mut Node {
96 let mut child_nodes = root;
83 let mut inclusive_ancestor_paths =
97 let mut inclusive_ancestor_paths =
84 WithBasename::inclusive_ancestors_of(path);
98 WithBasename::inclusive_ancestors_of(path);
85 let mut ancestor_path = inclusive_ancestor_paths
99 let mut ancestor_path = inclusive_ancestor_paths
86 .next()
100 .next()
87 .expect("expected at least one inclusive ancestor");
101 .expect("expected at least one inclusive ancestor");
88 loop {
102 loop {
89 // TODO: can we avoid double lookup in all cases without allocating
103 // TODO: can we avoid double lookup in all cases without allocating
90 // an owned key in cases where the map already contains that key?
104 // an owned key in cases where the map already contains that key?
91 let child_node =
105 let child_node =
92 if child_nodes.contains_key(ancestor_path.base_name()) {
106 if child_nodes.contains_key(ancestor_path.base_name()) {
93 child_nodes.get_mut(ancestor_path.base_name()).unwrap()
107 child_nodes.get_mut(ancestor_path.base_name()).unwrap()
94 } else {
108 } else {
95 // This is always a vacant entry, using `.entry()` lets us
109 // This is always a vacant entry, using `.entry()` lets us
96 // return a `&mut Node` of the newly-inserted node without
110 // return a `&mut Node` of the newly-inserted node without
97 // yet another lookup. `BTreeMap::insert` doesn’t do this.
111 // yet another lookup. `BTreeMap::insert` doesn’t do this.
98 child_nodes.entry(ancestor_path.to_owned()).or_default()
112 child_nodes.entry(ancestor_path.to_owned()).or_default()
99 };
113 };
100 if let Some(next) = inclusive_ancestor_paths.next() {
114 if let Some(next) = inclusive_ancestor_paths.next() {
101 ancestor_path = next;
115 ancestor_path = next;
102 child_nodes = &mut child_node.children;
116 child_nodes = &mut child_node.children;
103 } else {
117 } else {
104 return child_node;
118 return child_node;
105 }
119 }
106 }
120 }
107 }
121 }
108
122
123 /// The meaning of `new_copy_source` is:
124 ///
125 /// * `Some(Some(x))`: set `Node::copy_source` to `Some(x)`
126 /// * `Some(None)`: set `Node::copy_source` to `None`
127 /// * `None`: leave `Node::copy_source` unchanged
128 fn add_file_node(
129 &mut self,
130 path: &HgPath,
131 new_entry: DirstateEntry,
132 new_copy_source: Option<Option<HgPathBuf>>,
133 ) {
134 let node = Self::get_or_insert_node(&mut self.root, path);
135 if node.entry.is_none() {
136 self.nodes_with_entry_count += 1
137 }
138 if let Some(source) = &new_copy_source {
139 if node.copy_source.is_none() && source.is_some() {
140 self.nodes_with_copy_source_count += 1
141 }
142 if node.copy_source.is_some() && source.is_none() {
143 self.nodes_with_copy_source_count -= 1
144 }
145 }
146 node.entry = Some(new_entry);
147 if let Some(source) = new_copy_source {
148 node.copy_source = source
149 }
150 }
151
109 fn iter_nodes<'a>(
152 fn iter_nodes<'a>(
110 &'a self,
153 &'a self,
111 ) -> impl Iterator<Item = (&'a WithBasename<HgPathBuf>, &'a Node)> + 'a
154 ) -> impl Iterator<Item = (&'a WithBasename<HgPathBuf>, &'a Node)> + 'a
112 {
155 {
113 // Depth first tree traversal.
156 // Depth first tree traversal.
114 //
157 //
115 // If we could afford internal iteration and recursion,
158 // If we could afford internal iteration and recursion,
116 // this would look like:
159 // this would look like:
117 //
160 //
118 // ```
161 // ```
119 // fn traverse_children(
162 // fn traverse_children(
120 // children: &ChildNodes,
163 // children: &ChildNodes,
121 // each: &mut impl FnMut(&Node),
164 // each: &mut impl FnMut(&Node),
122 // ) {
165 // ) {
123 // for child in children.values() {
166 // for child in children.values() {
124 // traverse_children(&child.children, each);
167 // traverse_children(&child.children, each);
125 // each(child);
168 // each(child);
126 // }
169 // }
127 // }
170 // }
128 // ```
171 // ```
129 //
172 //
130 // However we want an external iterator and therefore can’t use the
173 // However we want an external iterator and therefore can’t use the
131 // call stack. Use an explicit stack instead:
174 // call stack. Use an explicit stack instead:
132 let mut stack = Vec::new();
175 let mut stack = Vec::new();
133 let mut iter = self.root.iter();
176 let mut iter = self.root.iter();
134 std::iter::from_fn(move || {
177 std::iter::from_fn(move || {
135 while let Some((key, child_node)) = iter.next() {
178 while let Some((key, child_node)) = iter.next() {
136 // Pseudo-recursion
179 // Pseudo-recursion
137 let new_iter = child_node.children.iter();
180 let new_iter = child_node.children.iter();
138 let old_iter = std::mem::replace(&mut iter, new_iter);
181 let old_iter = std::mem::replace(&mut iter, new_iter);
139 stack.push((key, child_node, old_iter));
182 stack.push((key, child_node, old_iter));
140 }
183 }
141 // Found the end of a `children.iter()` iterator.
184 // Found the end of a `children.iter()` iterator.
142 if let Some((key, child_node, next_iter)) = stack.pop() {
185 if let Some((key, child_node, next_iter)) = stack.pop() {
143 // "Return" from pseudo-recursion by restoring state from the
186 // "Return" from pseudo-recursion by restoring state from the
144 // explicit stack
187 // explicit stack
145 iter = next_iter;
188 iter = next_iter;
146
189
147 Some((key, child_node))
190 Some((key, child_node))
148 } else {
191 } else {
149 // Reached the bottom of the stack, we’re done
192 // Reached the bottom of the stack, we’re done
150 None
193 None
151 }
194 }
152 })
195 })
153 }
196 }
154
197
155 /// Mutable iterator for the `(entry, copy source)` of each node.
198 /// Mutable iterator for the `(entry, copy source)` of each node.
156 ///
199 ///
157 /// It would not be safe to yield mutable references to nodes themeselves
200 /// It would not be safe to yield mutable references to nodes themeselves
158 /// with `-> impl Iterator<Item = &mut Node>` since child nodes are
201 /// with `-> impl Iterator<Item = &mut Node>` since child nodes are
159 /// reachable from their ancestor nodes, potentially creating multiple
202 /// reachable from their ancestor nodes, potentially creating multiple
160 /// `&mut` references to a given node.
203 /// `&mut` references to a given node.
161 fn iter_node_data_mut<'a>(
204 fn iter_node_data_mut<'a>(
162 &'a mut self,
205 &'a mut self,
163 ) -> impl Iterator<Item = NodeDataMut<'a>> + 'a {
206 ) -> impl Iterator<Item = NodeDataMut<'a>> + 'a {
164 // Explict stack for pseudo-recursion, see `iter_nodes` above.
207 // Explict stack for pseudo-recursion, see `iter_nodes` above.
165 let mut stack = Vec::new();
208 let mut stack = Vec::new();
166 let mut iter = self.root.iter_mut();
209 let mut iter = self.root.iter_mut();
167 std::iter::from_fn(move || {
210 std::iter::from_fn(move || {
168 while let Some((key, child_node)) = iter.next() {
211 while let Some((key, child_node)) = iter.next() {
169 // Pseudo-recursion
212 // Pseudo-recursion
170 let data =
213 let data =
171 (key, &mut child_node.entry, &mut child_node.copy_source);
214 (key, &mut child_node.entry, &mut child_node.copy_source);
172 let new_iter = child_node.children.iter_mut();
215 let new_iter = child_node.children.iter_mut();
173 let old_iter = std::mem::replace(&mut iter, new_iter);
216 let old_iter = std::mem::replace(&mut iter, new_iter);
174 stack.push((data, old_iter));
217 stack.push((data, old_iter));
175 }
218 }
176 // Found the end of a `children.values_mut()` iterator.
219 // Found the end of a `children.values_mut()` iterator.
177 if let Some((data, next_iter)) = stack.pop() {
220 if let Some((data, next_iter)) = stack.pop() {
178 // "Return" from pseudo-recursion by restoring state from the
221 // "Return" from pseudo-recursion by restoring state from the
179 // explicit stack
222 // explicit stack
180 iter = next_iter;
223 iter = next_iter;
181
224
182 Some(data)
225 Some(data)
183 } else {
226 } else {
184 // Reached the bottom of the stack, we’re done
227 // Reached the bottom of the stack, we’re done
185 None
228 None
186 }
229 }
187 })
230 })
188 }
231 }
189 }
232 }
190
233
191 impl super::dispatch::DirstateMapMethods for DirstateMap {
234 impl super::dispatch::DirstateMapMethods for DirstateMap {
192 fn clear(&mut self) {
235 fn clear(&mut self) {
193 self.set_parents(&DirstateParents {
236 self.set_parents(&DirstateParents {
194 p1: NULL_NODE,
237 p1: NULL_NODE,
195 p2: NULL_NODE,
238 p2: NULL_NODE,
196 });
239 });
197 self.root.clear()
240 self.root.clear();
241 self.nodes_with_entry_count = 0;
242 self.nodes_with_copy_source_count = 0;
198 }
243 }
199
244
200 fn add_file(
245 fn add_file(
201 &mut self,
246 &mut self,
202 _filename: &HgPath,
247 _filename: &HgPath,
203 _old_state: EntryState,
248 _old_state: EntryState,
204 _entry: DirstateEntry,
249 _entry: DirstateEntry,
205 ) -> Result<(), DirstateMapError> {
250 ) -> Result<(), DirstateMapError> {
206 todo!()
251 todo!()
207 }
252 }
208
253
209 fn remove_file(
254 fn remove_file(
210 &mut self,
255 &mut self,
211 _filename: &HgPath,
256 _filename: &HgPath,
212 _old_state: EntryState,
257 _old_state: EntryState,
213 _size: i32,
258 _size: i32,
214 ) -> Result<(), DirstateMapError> {
259 ) -> Result<(), DirstateMapError> {
215 todo!()
260 todo!()
216 }
261 }
217
262
218 fn drop_file(
263 fn drop_file(
219 &mut self,
264 &mut self,
220 _filename: &HgPath,
265 _filename: &HgPath,
221 _old_state: EntryState,
266 _old_state: EntryState,
222 ) -> Result<bool, DirstateMapError> {
267 ) -> Result<bool, DirstateMapError> {
223 todo!()
268 todo!()
224 }
269 }
225
270
226 fn clear_ambiguous_times(
271 fn clear_ambiguous_times(
227 &mut self,
272 &mut self,
228 _filenames: Vec<HgPathBuf>,
273 _filenames: Vec<HgPathBuf>,
229 _now: i32,
274 _now: i32,
230 ) {
275 ) {
231 todo!()
276 todo!()
232 }
277 }
233
278
234 fn non_normal_entries_contains(&mut self, _key: &HgPath) -> bool {
279 fn non_normal_entries_contains(&mut self, _key: &HgPath) -> bool {
235 todo!()
280 todo!()
236 }
281 }
237
282
238 fn non_normal_entries_remove(&mut self, _key: &HgPath) -> bool {
283 fn non_normal_entries_remove(&mut self, _key: &HgPath) -> bool {
239 todo!()
284 todo!()
240 }
285 }
241
286
242 fn non_normal_or_other_parent_paths(
287 fn non_normal_or_other_parent_paths(
243 &mut self,
288 &mut self,
244 ) -> Box<dyn Iterator<Item = &HgPathBuf> + '_> {
289 ) -> Box<dyn Iterator<Item = &HgPathBuf> + '_> {
245 todo!()
290 todo!()
246 }
291 }
247
292
248 fn set_non_normal_other_parent_entries(&mut self, _force: bool) {
293 fn set_non_normal_other_parent_entries(&mut self, _force: bool) {
249 todo!()
294 todo!()
250 }
295 }
251
296
252 fn iter_non_normal_paths(
297 fn iter_non_normal_paths(
253 &mut self,
298 &mut self,
254 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
299 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
255 todo!()
300 todo!()
256 }
301 }
257
302
258 fn iter_non_normal_paths_panic(
303 fn iter_non_normal_paths_panic(
259 &self,
304 &self,
260 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
305 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
261 todo!()
306 todo!()
262 }
307 }
263
308
264 fn iter_other_parent_paths(
309 fn iter_other_parent_paths(
265 &mut self,
310 &mut self,
266 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
311 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
267 todo!()
312 todo!()
268 }
313 }
269
314
270 fn has_tracked_dir(
315 fn has_tracked_dir(
271 &mut self,
316 &mut self,
272 _directory: &HgPath,
317 _directory: &HgPath,
273 ) -> Result<bool, DirstateMapError> {
318 ) -> Result<bool, DirstateMapError> {
274 todo!()
319 todo!()
275 }
320 }
276
321
277 fn has_dir(
322 fn has_dir(
278 &mut self,
323 &mut self,
279 _directory: &HgPath,
324 _directory: &HgPath,
280 ) -> Result<bool, DirstateMapError> {
325 ) -> Result<bool, DirstateMapError> {
281 todo!()
326 todo!()
282 }
327 }
283
328
284 fn parents(
329 fn parents(
285 &mut self,
330 &mut self,
286 file_contents: &[u8],
331 file_contents: &[u8],
287 ) -> Result<&DirstateParents, DirstateError> {
332 ) -> Result<&DirstateParents, DirstateError> {
288 if self.parents.is_none() {
333 if self.parents.is_none() {
289 let parents = if !file_contents.is_empty() {
334 let parents = if !file_contents.is_empty() {
290 parse_dirstate_parents(file_contents)?.clone()
335 parse_dirstate_parents(file_contents)?.clone()
291 } else {
336 } else {
292 DirstateParents {
337 DirstateParents {
293 p1: NULL_NODE,
338 p1: NULL_NODE,
294 p2: NULL_NODE,
339 p2: NULL_NODE,
295 }
340 }
296 };
341 };
297 self.parents = Some(parents);
342 self.parents = Some(parents);
298 }
343 }
299 Ok(self.parents.as_ref().unwrap())
344 Ok(self.parents.as_ref().unwrap())
300 }
345 }
301
346
302 fn set_parents(&mut self, parents: &DirstateParents) {
347 fn set_parents(&mut self, parents: &DirstateParents) {
303 self.parents = Some(parents.clone());
348 self.parents = Some(parents.clone());
304 self.dirty_parents = true;
349 self.dirty_parents = true;
305 }
350 }
306
351
307 fn read<'a>(
352 fn read<'a>(
308 &mut self,
353 &mut self,
309 file_contents: &'a [u8],
354 file_contents: &'a [u8],
310 ) -> Result<Option<&'a DirstateParents>, DirstateError> {
355 ) -> Result<Option<&'a DirstateParents>, DirstateError> {
311 if file_contents.is_empty() {
356 if file_contents.is_empty() {
312 return Ok(None);
357 return Ok(None);
313 }
358 }
314
359
315 let parents = parse_dirstate_entries(
360 let parents = parse_dirstate_entries(
316 file_contents,
361 file_contents,
317 |path, entry, copy_source| {
362 |path, entry, copy_source| {
318 let node = self.get_or_insert_node(path);
363 self.add_file_node(
319 node.entry = Some(*entry);
364 path,
320 node.copy_source = copy_source.map(HgPath::to_owned);
365 *entry,
366 Some(copy_source.map(HgPath::to_owned)),
367 )
321 },
368 },
322 )?;
369 )?;
323
370
324 if !self.dirty_parents {
371 if !self.dirty_parents {
325 self.set_parents(parents);
372 self.set_parents(parents);
326 }
373 }
327
374
328 Ok(Some(parents))
375 Ok(Some(parents))
329 }
376 }
330
377
331 fn pack(
378 fn pack(
332 &mut self,
379 &mut self,
333 parents: DirstateParents,
380 parents: DirstateParents,
334 now: Timestamp,
381 now: Timestamp,
335 ) -> Result<Vec<u8>, DirstateError> {
382 ) -> Result<Vec<u8>, DirstateError> {
336 // Optizimation (to be measured?): pre-compute size to avoid `Vec`
383 // Optizimation (to be measured?): pre-compute size to avoid `Vec`
337 // reallocations
384 // reallocations
338 let mut size = parents.as_bytes().len();
385 let mut size = parents.as_bytes().len();
339 for (path, node) in self.iter_nodes() {
386 for (path, node) in self.iter_nodes() {
340 if node.entry.is_some() {
387 if node.entry.is_some() {
341 size += packed_entry_size(
388 size += packed_entry_size(
342 path.full_path(),
389 path.full_path(),
343 node.copy_source.as_ref(),
390 node.copy_source.as_ref(),
344 )
391 )
345 }
392 }
346 }
393 }
347
394
348 let mut packed = Vec::with_capacity(size);
395 let mut packed = Vec::with_capacity(size);
349 packed.extend(parents.as_bytes());
396 packed.extend(parents.as_bytes());
350
397
351 let now: i32 = now.0.try_into().expect("time overflow");
398 let now: i32 = now.0.try_into().expect("time overflow");
352 for (path, opt_entry, copy_source) in self.iter_node_data_mut() {
399 for (path, opt_entry, copy_source) in self.iter_node_data_mut() {
353 if let Some(entry) = opt_entry {
400 if let Some(entry) = opt_entry {
354 clear_ambiguous_mtime(entry, now);
401 clear_ambiguous_mtime(entry, now);
355 pack_entry(
402 pack_entry(
356 path.full_path(),
403 path.full_path(),
357 entry,
404 entry,
358 copy_source.as_ref(),
405 copy_source.as_ref(),
359 &mut packed,
406 &mut packed,
360 );
407 );
361 }
408 }
362 }
409 }
363 self.dirty_parents = false;
410 self.dirty_parents = false;
364 Ok(packed)
411 Ok(packed)
365 }
412 }
366
413
367 fn build_file_fold_map(&mut self) -> &FastHashMap<HgPathBuf, HgPathBuf> {
414 fn build_file_fold_map(&mut self) -> &FastHashMap<HgPathBuf, HgPathBuf> {
368 todo!()
415 todo!()
369 }
416 }
370
417
371 fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> {
418 fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> {
372 todo!()
419 todo!()
373 }
420 }
374
421
375 fn set_dirs(&mut self) -> Result<(), DirstateMapError> {
422 fn set_dirs(&mut self) -> Result<(), DirstateMapError> {
376 todo!()
423 todo!()
377 }
424 }
378
425
379 fn status<'a>(
426 fn status<'a>(
380 &'a self,
427 &'a self,
381 _matcher: &'a (dyn Matcher + Sync),
428 _matcher: &'a (dyn Matcher + Sync),
382 _root_dir: PathBuf,
429 _root_dir: PathBuf,
383 _ignore_files: Vec<PathBuf>,
430 _ignore_files: Vec<PathBuf>,
384 _options: StatusOptions,
431 _options: StatusOptions,
385 ) -> Result<
432 ) -> Result<
386 (
433 (
387 (Vec<HgPathCow<'a>>, DirstateStatus<'a>),
434 (Vec<HgPathCow<'a>>, DirstateStatus<'a>),
388 Vec<PatternFileWarning>,
435 Vec<PatternFileWarning>,
389 ),
436 ),
390 StatusError,
437 StatusError,
391 > {
438 > {
392 todo!()
439 todo!()
393 }
440 }
394
441
395 fn copy_map_len(&self) -> usize {
442 fn copy_map_len(&self) -> usize {
396 todo!()
443 self.nodes_with_copy_source_count
397 }
444 }
398
445
399 fn copy_map_iter(&self) -> CopyMapIter<'_> {
446 fn copy_map_iter(&self) -> CopyMapIter<'_> {
400 Box::new(self.iter_nodes().filter_map(|(path, node)| {
447 Box::new(self.iter_nodes().filter_map(|(path, node)| {
401 node.copy_source
448 node.copy_source
402 .as_ref()
449 .as_ref()
403 .map(|copy_source| (path.full_path(), copy_source))
450 .map(|copy_source| (path.full_path(), copy_source))
404 }))
451 }))
405 }
452 }
406
453
407 fn copy_map_contains_key(&self, key: &HgPath) -> bool {
454 fn copy_map_contains_key(&self, key: &HgPath) -> bool {
408 if let Some(node) = self.get_node(key) {
455 if let Some(node) = self.get_node(key) {
409 node.copy_source.is_some()
456 node.copy_source.is_some()
410 } else {
457 } else {
411 false
458 false
412 }
459 }
413 }
460 }
414
461
415 fn copy_map_get(&self, key: &HgPath) -> Option<&HgPathBuf> {
462 fn copy_map_get(&self, key: &HgPath) -> Option<&HgPathBuf> {
416 self.get_node(key)?.copy_source.as_ref()
463 self.get_node(key)?.copy_source.as_ref()
417 }
464 }
418
465
419 fn copy_map_remove(&mut self, _key: &HgPath) -> Option<HgPathBuf> {
466 fn copy_map_remove(&mut self, _key: &HgPath) -> Option<HgPathBuf> {
420 todo!()
467 todo!()
421 }
468 }
422
469
423 fn copy_map_insert(
470 fn copy_map_insert(
424 &mut self,
471 &mut self,
425 _key: HgPathBuf,
472 _key: HgPathBuf,
426 _value: HgPathBuf,
473 _value: HgPathBuf,
427 ) -> Option<HgPathBuf> {
474 ) -> Option<HgPathBuf> {
428 todo!()
475 todo!()
429 }
476 }
430
477
431 fn len(&self) -> usize {
478 fn len(&self) -> usize {
432 todo!()
479 self.nodes_with_entry_count
433 }
480 }
434
481
435 fn contains_key(&self, key: &HgPath) -> bool {
482 fn contains_key(&self, key: &HgPath) -> bool {
436 self.get(key).is_some()
483 self.get(key).is_some()
437 }
484 }
438
485
439 fn get(&self, key: &HgPath) -> Option<&DirstateEntry> {
486 fn get(&self, key: &HgPath) -> Option<&DirstateEntry> {
440 self.get_node(key)?.entry.as_ref()
487 self.get_node(key)?.entry.as_ref()
441 }
488 }
442
489
443 fn iter(&self) -> StateMapIter<'_> {
490 fn iter(&self) -> StateMapIter<'_> {
444 Box::new(self.iter_nodes().filter_map(|(path, node)| {
491 Box::new(self.iter_nodes().filter_map(|(path, node)| {
445 node.entry.as_ref().map(|entry| (path.full_path(), entry))
492 node.entry.as_ref().map(|entry| (path.full_path(), entry))
446 }))
493 }))
447 }
494 }
448 }
495 }
General Comments 0
You need to be logged in to leave comments. Login now