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