Show More
@@ -0,0 +1,175 b'' | |||||
|
1 | use crate::dirstate::owning::OwningDirstateMap; | |||
|
2 | use hg::dirstate::parsers::Timestamp; | |||
|
3 | use hg::dirstate_tree::dispatch::DirstateMapMethods; | |||
|
4 | use hg::matchers::Matcher; | |||
|
5 | use hg::utils::hg_path::{HgPath, HgPathBuf}; | |||
|
6 | use hg::CopyMapIter; | |||
|
7 | use hg::DirstateEntry; | |||
|
8 | use hg::DirstateError; | |||
|
9 | use hg::DirstateMapError; | |||
|
10 | use hg::DirstateParents; | |||
|
11 | use hg::DirstateStatus; | |||
|
12 | use hg::EntryState; | |||
|
13 | use hg::PatternFileWarning; | |||
|
14 | use hg::StateMapIter; | |||
|
15 | use hg::StatusError; | |||
|
16 | use hg::StatusOptions; | |||
|
17 | use std::path::PathBuf; | |||
|
18 | ||||
|
19 | impl DirstateMapMethods for OwningDirstateMap { | |||
|
20 | fn clear(&mut self) { | |||
|
21 | self.get_mut().clear() | |||
|
22 | } | |||
|
23 | ||||
|
24 | fn add_file( | |||
|
25 | &mut self, | |||
|
26 | filename: &HgPath, | |||
|
27 | old_state: EntryState, | |||
|
28 | entry: DirstateEntry, | |||
|
29 | ) -> Result<(), DirstateMapError> { | |||
|
30 | self.get_mut().add_file(filename, old_state, entry) | |||
|
31 | } | |||
|
32 | ||||
|
33 | fn remove_file( | |||
|
34 | &mut self, | |||
|
35 | filename: &HgPath, | |||
|
36 | old_state: EntryState, | |||
|
37 | size: i32, | |||
|
38 | ) -> Result<(), DirstateMapError> { | |||
|
39 | self.get_mut().remove_file(filename, old_state, size) | |||
|
40 | } | |||
|
41 | ||||
|
42 | fn drop_file( | |||
|
43 | &mut self, | |||
|
44 | filename: &HgPath, | |||
|
45 | old_state: EntryState, | |||
|
46 | ) -> Result<bool, DirstateMapError> { | |||
|
47 | self.get_mut().drop_file(filename, old_state) | |||
|
48 | } | |||
|
49 | ||||
|
50 | fn clear_ambiguous_times(&mut self, filenames: Vec<HgPathBuf>, now: i32) { | |||
|
51 | self.get_mut().clear_ambiguous_times(filenames, now) | |||
|
52 | } | |||
|
53 | ||||
|
54 | fn non_normal_entries_contains(&mut self, key: &HgPath) -> bool { | |||
|
55 | self.get_mut().non_normal_entries_contains(key) | |||
|
56 | } | |||
|
57 | ||||
|
58 | fn non_normal_entries_remove(&mut self, key: &HgPath) { | |||
|
59 | self.get_mut().non_normal_entries_remove(key) | |||
|
60 | } | |||
|
61 | ||||
|
62 | fn non_normal_or_other_parent_paths( | |||
|
63 | &mut self, | |||
|
64 | ) -> Box<dyn Iterator<Item = &HgPathBuf> + '_> { | |||
|
65 | self.get_mut().non_normal_or_other_parent_paths() | |||
|
66 | } | |||
|
67 | ||||
|
68 | fn set_non_normal_other_parent_entries(&mut self, force: bool) { | |||
|
69 | self.get_mut().set_non_normal_other_parent_entries(force) | |||
|
70 | } | |||
|
71 | ||||
|
72 | fn iter_non_normal_paths( | |||
|
73 | &mut self, | |||
|
74 | ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> { | |||
|
75 | self.get_mut().iter_non_normal_paths() | |||
|
76 | } | |||
|
77 | ||||
|
78 | fn iter_non_normal_paths_panic( | |||
|
79 | &self, | |||
|
80 | ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> { | |||
|
81 | self.get().iter_non_normal_paths_panic() | |||
|
82 | } | |||
|
83 | ||||
|
84 | fn iter_other_parent_paths( | |||
|
85 | &mut self, | |||
|
86 | ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> { | |||
|
87 | self.get_mut().iter_other_parent_paths() | |||
|
88 | } | |||
|
89 | ||||
|
90 | fn has_tracked_dir( | |||
|
91 | &mut self, | |||
|
92 | directory: &HgPath, | |||
|
93 | ) -> Result<bool, DirstateMapError> { | |||
|
94 | self.get_mut().has_tracked_dir(directory) | |||
|
95 | } | |||
|
96 | ||||
|
97 | fn has_dir( | |||
|
98 | &mut self, | |||
|
99 | directory: &HgPath, | |||
|
100 | ) -> Result<bool, DirstateMapError> { | |||
|
101 | self.get_mut().has_dir(directory) | |||
|
102 | } | |||
|
103 | ||||
|
104 | fn pack( | |||
|
105 | &mut self, | |||
|
106 | parents: DirstateParents, | |||
|
107 | now: Timestamp, | |||
|
108 | ) -> Result<Vec<u8>, DirstateError> { | |||
|
109 | self.get_mut().pack(parents, now) | |||
|
110 | } | |||
|
111 | ||||
|
112 | fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> { | |||
|
113 | self.get_mut().set_all_dirs() | |||
|
114 | } | |||
|
115 | ||||
|
116 | fn set_dirs(&mut self) -> Result<(), DirstateMapError> { | |||
|
117 | self.get_mut().set_dirs() | |||
|
118 | } | |||
|
119 | ||||
|
120 | fn status<'a>( | |||
|
121 | &'a mut self, | |||
|
122 | matcher: &'a (dyn Matcher + Sync), | |||
|
123 | root_dir: PathBuf, | |||
|
124 | ignore_files: Vec<PathBuf>, | |||
|
125 | options: StatusOptions, | |||
|
126 | ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError> | |||
|
127 | { | |||
|
128 | self.get_mut() | |||
|
129 | .status(matcher, root_dir, ignore_files, options) | |||
|
130 | } | |||
|
131 | ||||
|
132 | fn copy_map_len(&self) -> usize { | |||
|
133 | self.get().copy_map_len() | |||
|
134 | } | |||
|
135 | ||||
|
136 | fn copy_map_iter(&self) -> CopyMapIter<'_> { | |||
|
137 | self.get().copy_map_iter() | |||
|
138 | } | |||
|
139 | ||||
|
140 | fn copy_map_contains_key(&self, key: &HgPath) -> bool { | |||
|
141 | self.get().copy_map_contains_key(key) | |||
|
142 | } | |||
|
143 | ||||
|
144 | fn copy_map_get(&self, key: &HgPath) -> Option<&HgPathBuf> { | |||
|
145 | self.get().copy_map_get(key) | |||
|
146 | } | |||
|
147 | ||||
|
148 | fn copy_map_remove(&mut self, key: &HgPath) -> Option<HgPathBuf> { | |||
|
149 | self.get_mut().copy_map_remove(key) | |||
|
150 | } | |||
|
151 | ||||
|
152 | fn copy_map_insert( | |||
|
153 | &mut self, | |||
|
154 | key: HgPathBuf, | |||
|
155 | value: HgPathBuf, | |||
|
156 | ) -> Option<HgPathBuf> { | |||
|
157 | self.get_mut().copy_map_insert(key, value) | |||
|
158 | } | |||
|
159 | ||||
|
160 | fn len(&self) -> usize { | |||
|
161 | self.get().len() | |||
|
162 | } | |||
|
163 | ||||
|
164 | fn contains_key(&self, key: &HgPath) -> bool { | |||
|
165 | self.get().contains_key(key) | |||
|
166 | } | |||
|
167 | ||||
|
168 | fn get(&self, key: &HgPath) -> Option<&DirstateEntry> { | |||
|
169 | self.get().get(key) | |||
|
170 | } | |||
|
171 | ||||
|
172 | fn iter(&self) -> StateMapIter<'_> { | |||
|
173 | self.get().iter() | |||
|
174 | } | |||
|
175 | } |
@@ -0,0 +1,97 b'' | |||||
|
1 | use cpython::PyBytes; | |||
|
2 | use cpython::Python; | |||
|
3 | use hg::dirstate_tree::dirstate_map::DirstateMap; | |||
|
4 | use hg::DirstateError; | |||
|
5 | use hg::DirstateParents; | |||
|
6 | ||||
|
7 | /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it | |||
|
8 | /// borrows. This is similar to the owning-ref crate. | |||
|
9 | /// | |||
|
10 | /// This is similar to [`OwningRef`] which is more limited because it | |||
|
11 | /// represents exactly one `&T` reference next to the value it borrows, as | |||
|
12 | /// opposed to a struct that may contain an arbitrary number of references in | |||
|
13 | /// arbitrarily-nested data structures. | |||
|
14 | /// | |||
|
15 | /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html | |||
|
16 | pub(super) struct OwningDirstateMap { | |||
|
17 | /// Owned handle to a bytes buffer with a stable address. | |||
|
18 | /// | |||
|
19 | /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>. | |||
|
20 | on_disk: PyBytes, | |||
|
21 | ||||
|
22 | /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the | |||
|
23 | /// language cannot represent a lifetime referencing a sibling field. | |||
|
24 | /// This is not quite a self-referencial struct (moving this struct is not | |||
|
25 | /// a problem as it doesn’t change the address of the bytes buffer owned | |||
|
26 | /// by `PyBytes`) but touches similar borrow-checker limitations. | |||
|
27 | ptr: *mut (), | |||
|
28 | } | |||
|
29 | ||||
|
30 | impl OwningDirstateMap { | |||
|
31 | pub fn new( | |||
|
32 | py: Python, | |||
|
33 | on_disk: PyBytes, | |||
|
34 | ) -> Result<(Self, Option<DirstateParents>), DirstateError> { | |||
|
35 | let bytes: &'_ [u8] = on_disk.data(py); | |||
|
36 | let (map, parents) = DirstateMap::new(bytes)?; | |||
|
37 | ||||
|
38 | // Like in `bytes` above, this `'_` lifetime parameter borrows from | |||
|
39 | // the bytes buffer owned by `on_disk`. | |||
|
40 | let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map)); | |||
|
41 | ||||
|
42 | // Erase the pointed type entirely in order to erase the lifetime. | |||
|
43 | let ptr: *mut () = ptr.cast(); | |||
|
44 | ||||
|
45 | Ok((Self { on_disk, ptr }, parents)) | |||
|
46 | } | |||
|
47 | ||||
|
48 | pub fn get_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> { | |||
|
49 | // SAFETY: We cast the type-erased pointer back to the same type it had | |||
|
50 | // in `new`, except with a different lifetime parameter. This time we | |||
|
51 | // connect the lifetime to that of `self`. This cast is valid because | |||
|
52 | // `self` owns the same `PyBytes` whose buffer `DirstateMap` | |||
|
53 | // references. That buffer has a stable memory address because the byte | |||
|
54 | // string value of a `PyBytes` is immutable. | |||
|
55 | let ptr: *mut DirstateMap<'a> = self.ptr.cast(); | |||
|
56 | // SAFETY: we dereference that pointer, connecting the lifetime of the | |||
|
57 | // new `&mut` to that of `self`. This is valid because the | |||
|
58 | // raw pointer is to a boxed value, and `self` owns that box. | |||
|
59 | unsafe { &mut *ptr } | |||
|
60 | } | |||
|
61 | ||||
|
62 | pub fn get<'a>(&'a self) -> &'a DirstateMap<'a> { | |||
|
63 | // SAFETY: same reasoning as in `get_mut` above. | |||
|
64 | let ptr: *mut DirstateMap<'a> = self.ptr.cast(); | |||
|
65 | unsafe { &*ptr } | |||
|
66 | } | |||
|
67 | } | |||
|
68 | ||||
|
69 | impl Drop for OwningDirstateMap { | |||
|
70 | fn drop(&mut self) { | |||
|
71 | // Silence a "field is never read" warning, and demonstrate that this | |||
|
72 | // value is still alive. | |||
|
73 | let _ = &self.on_disk; | |||
|
74 | // SAFETY: this cast is the same as in `get_mut`, and is valid for the | |||
|
75 | // same reason. `self.on_disk` still exists at this point, drop glue | |||
|
76 | // will drop it implicitly after this `drop` method returns. | |||
|
77 | let ptr: *mut DirstateMap<'_> = self.ptr.cast(); | |||
|
78 | // SAFETY: `Box::from_raw` takes ownership of the box away from `self`. | |||
|
79 | // This is fine because drop glue does nothig for `*mut ()` and we’re | |||
|
80 | // in `drop`, so `get` and `get_mut` cannot be called again. | |||
|
81 | unsafe { drop(Box::from_raw(ptr)) } | |||
|
82 | } | |||
|
83 | } | |||
|
84 | ||||
|
85 | fn _static_assert_is_send<T: Send>() {} | |||
|
86 | ||||
|
87 | fn _static_assert_fields_are_send() { | |||
|
88 | _static_assert_is_send::<PyBytes>(); | |||
|
89 | _static_assert_is_send::<Box<DirstateMap<'_>>>(); | |||
|
90 | } | |||
|
91 | ||||
|
92 | // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because | |||
|
93 | // thread-safety of raw pointers is unknown in the general case. However this | |||
|
94 | // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we | |||
|
95 | // own. Since that `Box` and `PyBytes` are both `Send` as shown in above, it | |||
|
96 | // is sound to mark this struct as `Send` too. | |||
|
97 | unsafe impl Send for OwningDirstateMap {} |
@@ -284,10 +284,10 b' impl DirstateMap {' | |||||
284 | } |
|
284 | } | |
285 |
|
285 | |||
286 | #[timed] |
|
286 | #[timed] | |
287 |
pub fn read |
|
287 | pub fn read( | |
288 | &mut self, |
|
288 | &mut self, | |
289 |
file_contents: & |
|
289 | file_contents: &[u8], | |
290 |
) -> Result<Option< |
|
290 | ) -> Result<Option<DirstateParents>, DirstateError> { | |
291 | if file_contents.is_empty() { |
|
291 | if file_contents.is_empty() { | |
292 | return Ok(None); |
|
292 | return Ok(None); | |
293 | } |
|
293 | } | |
@@ -303,7 +303,7 b' impl DirstateMap {' | |||||
303 | .into_iter() |
|
303 | .into_iter() | |
304 | .map(|(path, copy)| (path.to_owned(), copy.to_owned())), |
|
304 | .map(|(path, copy)| (path.to_owned(), copy.to_owned())), | |
305 | ); |
|
305 | ); | |
306 | Ok(Some(parents)) |
|
306 | Ok(Some(parents.clone())) | |
307 | } |
|
307 | } | |
308 |
|
308 | |||
309 | pub fn pack( |
|
309 | pub fn pack( |
@@ -24,7 +24,10 b' use crate::StateMapIter;' | |||||
24 | use crate::StatusError; |
|
24 | use crate::StatusError; | |
25 | use crate::StatusOptions; |
|
25 | use crate::StatusOptions; | |
26 |
|
26 | |||
27 | pub struct DirstateMap { |
|
27 | pub struct DirstateMap<'on_disk> { | |
|
28 | /// Contents of the `.hg/dirstate` file | |||
|
29 | on_disk: &'on_disk [u8], | |||
|
30 | ||||
28 | pub(super) root: ChildNodes, |
|
31 | pub(super) root: ChildNodes, | |
29 |
|
32 | |||
30 | /// Number of nodes anywhere in the tree that have `.entry.is_some()`. |
|
33 | /// Number of nodes anywhere in the tree that have `.entry.is_some()`. | |
@@ -69,13 +72,58 b" type NodeDataMut<'a> = (" | |||||
69 | &'a mut Option<HgPathBuf>, |
|
72 | &'a mut Option<HgPathBuf>, | |
70 | ); |
|
73 | ); | |
71 |
|
74 | |||
72 | impl DirstateMap { |
|
75 | impl<'on_disk> DirstateMap<'on_disk> { | |
73 |
pub fn new( |
|
76 | pub fn new( | |
74 | Self { |
|
77 | on_disk: &'on_disk [u8], | |
|
78 | ) -> Result<(Self, Option<DirstateParents>), DirstateError> { | |||
|
79 | let mut map = Self { | |||
|
80 | on_disk, | |||
75 | root: ChildNodes::default(), |
|
81 | root: ChildNodes::default(), | |
76 | nodes_with_entry_count: 0, |
|
82 | nodes_with_entry_count: 0, | |
77 | nodes_with_copy_source_count: 0, |
|
83 | nodes_with_copy_source_count: 0, | |
|
84 | }; | |||
|
85 | let parents = map.read()?; | |||
|
86 | Ok((map, parents)) | |||
|
87 | } | |||
|
88 | ||||
|
89 | /// Should only be called in `new` | |||
|
90 | #[timed] | |||
|
91 | fn read(&mut self) -> Result<Option<DirstateParents>, DirstateError> { | |||
|
92 | if self.on_disk.is_empty() { | |||
|
93 | return Ok(None); | |||
78 | } |
|
94 | } | |
|
95 | ||||
|
96 | let parents = parse_dirstate_entries( | |||
|
97 | self.on_disk, | |||
|
98 | |path, entry, copy_source| { | |||
|
99 | let tracked = entry.state.is_tracked(); | |||
|
100 | let node = Self::get_or_insert_node_tracing_ancestors( | |||
|
101 | &mut self.root, | |||
|
102 | path, | |||
|
103 | |ancestor| { | |||
|
104 | if tracked { | |||
|
105 | ancestor.tracked_descendants_count += 1 | |||
|
106 | } | |||
|
107 | }, | |||
|
108 | ); | |||
|
109 | assert!( | |||
|
110 | node.entry.is_none(), | |||
|
111 | "duplicate dirstate entry in read" | |||
|
112 | ); | |||
|
113 | assert!( | |||
|
114 | node.copy_source.is_none(), | |||
|
115 | "duplicate dirstate entry in read" | |||
|
116 | ); | |||
|
117 | node.entry = Some(*entry); | |||
|
118 | node.copy_source = copy_source.map(HgPath::to_owned); | |||
|
119 | self.nodes_with_entry_count += 1; | |||
|
120 | if copy_source.is_some() { | |||
|
121 | self.nodes_with_copy_source_count += 1 | |||
|
122 | } | |||
|
123 | }, | |||
|
124 | )?; | |||
|
125 | ||||
|
126 | Ok(Some(parents.clone())) | |||
79 | } |
|
127 | } | |
80 |
|
128 | |||
81 | fn get_node(&self, path: &HgPath) -> Option<&Node> { |
|
129 | fn get_node(&self, path: &HgPath) -> Option<&Node> { | |
@@ -280,7 +328,7 b' impl DirstateMap {' | |||||
280 | } |
|
328 | } | |
281 | } |
|
329 | } | |
282 |
|
330 | |||
283 | impl super::dispatch::DirstateMapMethods for DirstateMap { |
|
331 | impl<'on_disk> super::dispatch::DirstateMapMethods for DirstateMap<'on_disk> { | |
284 | fn clear(&mut self) { |
|
332 | fn clear(&mut self) { | |
285 | self.root.clear(); |
|
333 | self.root.clear(); | |
286 | self.nodes_with_entry_count = 0; |
|
334 | self.nodes_with_entry_count = 0; | |
@@ -443,48 +491,6 b' impl super::dispatch::DirstateMapMethods' | |||||
443 | } |
|
491 | } | |
444 | } |
|
492 | } | |
445 |
|
493 | |||
446 | #[timed] |
|
|||
447 | fn read<'a>( |
|
|||
448 | &mut self, |
|
|||
449 | file_contents: &'a [u8], |
|
|||
450 | ) -> Result<Option<&'a DirstateParents>, DirstateError> { |
|
|||
451 | if file_contents.is_empty() { |
|
|||
452 | return Ok(None); |
|
|||
453 | } |
|
|||
454 |
|
||||
455 | let parents = parse_dirstate_entries( |
|
|||
456 | file_contents, |
|
|||
457 | |path, entry, copy_source| { |
|
|||
458 | let tracked = entry.state.is_tracked(); |
|
|||
459 | let node = Self::get_or_insert_node_tracing_ancestors( |
|
|||
460 | &mut self.root, |
|
|||
461 | path, |
|
|||
462 | |ancestor| { |
|
|||
463 | if tracked { |
|
|||
464 | ancestor.tracked_descendants_count += 1 |
|
|||
465 | } |
|
|||
466 | }, |
|
|||
467 | ); |
|
|||
468 | assert!( |
|
|||
469 | node.entry.is_none(), |
|
|||
470 | "duplicate dirstate entry in read" |
|
|||
471 | ); |
|
|||
472 | assert!( |
|
|||
473 | node.copy_source.is_none(), |
|
|||
474 | "duplicate dirstate entry in read" |
|
|||
475 | ); |
|
|||
476 | node.entry = Some(*entry); |
|
|||
477 | node.copy_source = copy_source.map(HgPath::to_owned); |
|
|||
478 | self.nodes_with_entry_count += 1; |
|
|||
479 | if copy_source.is_some() { |
|
|||
480 | self.nodes_with_copy_source_count += 1 |
|
|||
481 | } |
|
|||
482 | }, |
|
|||
483 | )?; |
|
|||
484 |
|
||||
485 | Ok(Some(parents)) |
|
|||
486 | } |
|
|||
487 |
|
||||
488 | fn pack( |
|
494 | fn pack( | |
489 | &mut self, |
|
495 | &mut self, | |
490 | parents: DirstateParents, |
|
496 | parents: DirstateParents, |
@@ -73,11 +73,6 b' pub trait DirstateMapMethods {' | |||||
73 | directory: &HgPath, |
|
73 | directory: &HgPath, | |
74 | ) -> Result<bool, DirstateMapError>; |
|
74 | ) -> Result<bool, DirstateMapError>; | |
75 |
|
75 | |||
76 | fn read<'a>( |
|
|||
77 | &mut self, |
|
|||
78 | file_contents: &'a [u8], |
|
|||
79 | ) -> Result<Option<&'a DirstateParents>, DirstateError>; |
|
|||
80 |
|
||||
81 | fn pack( |
|
76 | fn pack( | |
82 | &mut self, |
|
77 | &mut self, | |
83 | parents: DirstateParents, |
|
78 | parents: DirstateParents, | |
@@ -216,13 +211,6 b' impl DirstateMapMethods for DirstateMap ' | |||||
216 | self.has_dir(directory) |
|
211 | self.has_dir(directory) | |
217 | } |
|
212 | } | |
218 |
|
213 | |||
219 | fn read<'a>( |
|
|||
220 | &mut self, |
|
|||
221 | file_contents: &'a [u8], |
|
|||
222 | ) -> Result<Option<&'a DirstateParents>, DirstateError> { |
|
|||
223 | self.read(file_contents) |
|
|||
224 | } |
|
|||
225 |
|
||||
226 | fn pack( |
|
214 | fn pack( | |
227 | &mut self, |
|
215 | &mut self, | |
228 | parents: DirstateParents, |
|
216 | parents: DirstateParents, |
@@ -12,7 +12,9 b'' | |||||
12 | mod copymap; |
|
12 | mod copymap; | |
13 | mod dirs_multiset; |
|
13 | mod dirs_multiset; | |
14 | mod dirstate_map; |
|
14 | mod dirstate_map; | |
|
15 | mod dispatch; | |||
15 | mod non_normal_entries; |
|
16 | mod non_normal_entries; | |
|
17 | mod owning; | |||
16 | mod status; |
|
18 | mod status; | |
17 | use crate::{ |
|
19 | use crate::{ | |
18 | dirstate::{ |
|
20 | dirstate::{ |
@@ -22,6 +22,7 b' use crate::{' | |||||
22 | dirstate::non_normal_entries::{ |
|
22 | dirstate::non_normal_entries::{ | |
23 | NonNormalEntries, NonNormalEntriesIterator, |
|
23 | NonNormalEntries, NonNormalEntriesIterator, | |
24 | }, |
|
24 | }, | |
|
25 | dirstate::owning::OwningDirstateMap, | |||
25 | dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, |
|
26 | dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, | |
26 | parsers::dirstate_parents_to_pytuple, |
|
27 | parsers::dirstate_parents_to_pytuple, | |
27 | }; |
|
28 | }; | |
@@ -58,12 +59,13 b' py_class!(pub class DirstateMap |py| {' | |||||
58 | let dirstate_error = |_: DirstateError| { |
|
59 | let dirstate_error = |_: DirstateError| { | |
59 | PyErr::new::<exc::OSError, _>(py, "Dirstate error".to_string()) |
|
60 | PyErr::new::<exc::OSError, _>(py, "Dirstate error".to_string()) | |
60 | }; |
|
61 | }; | |
61 | let bytes = on_disk.data(py); |
|
|||
62 | let (inner, parents) = if use_dirstate_tree { |
|
62 | let (inner, parents) = if use_dirstate_tree { | |
63 | let mut map = hg::dirstate_tree::dirstate_map::DirstateMap::new(); |
|
63 | let (map, parents) = | |
64 | let parents = map.read(bytes).map_err(dirstate_error)?; |
|
64 | OwningDirstateMap::new(py, on_disk) | |
|
65 | .map_err(dirstate_error)?; | |||
65 | (Box::new(map) as _, parents) |
|
66 | (Box::new(map) as _, parents) | |
66 | } else { |
|
67 | } else { | |
|
68 | let bytes = on_disk.data(py); | |||
67 | let mut map = RustDirstateMap::default(); |
|
69 | let mut map = RustDirstateMap::default(); | |
68 | let parents = map.read(bytes).map_err(dirstate_error)?; |
|
70 | let parents = map.read(bytes).map_err(dirstate_error)?; | |
69 | (Box::new(map) as _, parents) |
|
71 | (Box::new(map) as _, parents) |
General Comments 0
You need to be logged in to leave comments.
Login now