Show More
@@ -30,7 +30,7 b' impl DirsMultiset {' | |||||
30 | pub fn from_dirstate( |
|
30 | pub fn from_dirstate( | |
31 | dirstate: &FastHashMap<HgPathBuf, DirstateEntry>, |
|
31 | dirstate: &FastHashMap<HgPathBuf, DirstateEntry>, | |
32 | skip_state: Option<EntryState>, |
|
32 | skip_state: Option<EntryState>, | |
33 | ) -> Self { |
|
33 | ) -> Result<Self, DirstateMapError> { | |
34 | let mut multiset = DirsMultiset { |
|
34 | let mut multiset = DirsMultiset { | |
35 | inner: FastHashMap::default(), |
|
35 | inner: FastHashMap::default(), | |
36 | }; |
|
36 | }; | |
@@ -39,27 +39,29 b' impl DirsMultiset {' | |||||
39 | // This `if` is optimized out of the loop |
|
39 | // This `if` is optimized out of the loop | |
40 | if let Some(skip) = skip_state { |
|
40 | if let Some(skip) = skip_state { | |
41 | if skip != *state { |
|
41 | if skip != *state { | |
42 | multiset.add_path(filename); |
|
42 | multiset.add_path(filename)?; | |
43 | } |
|
43 | } | |
44 | } else { |
|
44 | } else { | |
45 | multiset.add_path(filename); |
|
45 | multiset.add_path(filename)?; | |
46 | } |
|
46 | } | |
47 | } |
|
47 | } | |
48 |
|
48 | |||
49 | multiset |
|
49 | Ok(multiset) | |
50 | } |
|
50 | } | |
51 |
|
51 | |||
52 | /// Initializes the multiset from a manifest. |
|
52 | /// Initializes the multiset from a manifest. | |
53 | pub fn from_manifest(manifest: &[impl AsRef<HgPath>]) -> Self { |
|
53 | pub fn from_manifest( | |
|
54 | manifest: &[impl AsRef<HgPath>], | |||
|
55 | ) -> Result<Self, DirstateMapError> { | |||
54 | let mut multiset = DirsMultiset { |
|
56 | let mut multiset = DirsMultiset { | |
55 | inner: FastHashMap::default(), |
|
57 | inner: FastHashMap::default(), | |
56 | }; |
|
58 | }; | |
57 |
|
59 | |||
58 | for filename in manifest { |
|
60 | for filename in manifest { | |
59 | multiset.add_path(filename.as_ref()); |
|
61 | multiset.add_path(filename.as_ref())?; | |
60 | } |
|
62 | } | |
61 |
|
63 | |||
62 | multiset |
|
64 | Ok(multiset) | |
63 | } |
|
65 | } | |
64 |
|
66 | |||
65 | /// Increases the count of deepest directory contained in the path. |
|
67 | /// Increases the count of deepest directory contained in the path. | |
@@ -134,7 +136,7 b' mod tests {' | |||||
134 | #[test] |
|
136 | #[test] | |
135 | fn test_delete_path_path_not_found() { |
|
137 | fn test_delete_path_path_not_found() { | |
136 | let manifest: Vec<HgPathBuf> = vec![]; |
|
138 | let manifest: Vec<HgPathBuf> = vec![]; | |
137 | let mut map = DirsMultiset::from_manifest(&manifest); |
|
139 | let mut map = DirsMultiset::from_manifest(&manifest).unwrap(); | |
138 | let path = HgPathBuf::from_bytes(b"doesnotexist/"); |
|
140 | let path = HgPathBuf::from_bytes(b"doesnotexist/"); | |
139 | assert_eq!( |
|
141 | assert_eq!( | |
140 | Err(DirstateMapError::PathNotFound(path.to_owned())), |
|
142 | Err(DirstateMapError::PathNotFound(path.to_owned())), | |
@@ -144,7 +146,8 b' mod tests {' | |||||
144 |
|
146 | |||
145 | #[test] |
|
147 | #[test] | |
146 | fn test_delete_path_empty_path() { |
|
148 | fn test_delete_path_empty_path() { | |
147 | let mut map = DirsMultiset::from_manifest(&vec![HgPathBuf::new()]); |
|
149 | let mut map = | |
|
150 | DirsMultiset::from_manifest(&vec![HgPathBuf::new()]).unwrap(); | |||
148 | let path = HgPath::new(b""); |
|
151 | let path = HgPath::new(b""); | |
149 | assert_eq!(Ok(()), map.delete_path(path)); |
|
152 | assert_eq!(Ok(()), map.delete_path(path)); | |
150 | assert_eq!( |
|
153 | assert_eq!( | |
@@ -191,7 +194,7 b' mod tests {' | |||||
191 | #[test] |
|
194 | #[test] | |
192 | fn test_add_path_empty_path() { |
|
195 | fn test_add_path_empty_path() { | |
193 | let manifest: Vec<HgPathBuf> = vec![]; |
|
196 | let manifest: Vec<HgPathBuf> = vec![]; | |
194 | let mut map = DirsMultiset::from_manifest(&manifest); |
|
197 | let mut map = DirsMultiset::from_manifest(&manifest).unwrap(); | |
195 | let path = HgPath::new(b""); |
|
198 | let path = HgPath::new(b""); | |
196 | map.add_path(path); |
|
199 | map.add_path(path); | |
197 |
|
200 | |||
@@ -201,7 +204,7 b' mod tests {' | |||||
201 | #[test] |
|
204 | #[test] | |
202 | fn test_add_path_successful() { |
|
205 | fn test_add_path_successful() { | |
203 | let manifest: Vec<HgPathBuf> = vec![]; |
|
206 | let manifest: Vec<HgPathBuf> = vec![]; | |
204 | let mut map = DirsMultiset::from_manifest(&manifest); |
|
207 | let mut map = DirsMultiset::from_manifest(&manifest).unwrap(); | |
205 |
|
208 | |||
206 | map.add_path(HgPath::new(b"a/")); |
|
209 | map.add_path(HgPath::new(b"a/")); | |
207 | assert_eq!(1, *map.inner.get(HgPath::new(b"a")).unwrap()); |
|
210 | assert_eq!(1, *map.inner.get(HgPath::new(b"a")).unwrap()); | |
@@ -247,13 +250,14 b' mod tests {' | |||||
247 | #[test] |
|
250 | #[test] | |
248 | fn test_dirsmultiset_new_empty() { |
|
251 | fn test_dirsmultiset_new_empty() { | |
249 | let manifest: Vec<HgPathBuf> = vec![]; |
|
252 | let manifest: Vec<HgPathBuf> = vec![]; | |
250 | let new = DirsMultiset::from_manifest(&manifest); |
|
253 | let new = DirsMultiset::from_manifest(&manifest).unwrap(); | |
251 | let expected = DirsMultiset { |
|
254 | let expected = DirsMultiset { | |
252 | inner: FastHashMap::default(), |
|
255 | inner: FastHashMap::default(), | |
253 | }; |
|
256 | }; | |
254 | assert_eq!(expected, new); |
|
257 | assert_eq!(expected, new); | |
255 |
|
258 | |||
256 |
let new = DirsMultiset::from_dirstate(&FastHashMap::default(), None) |
|
259 | let new = DirsMultiset::from_dirstate(&FastHashMap::default(), None) | |
|
260 | .unwrap(); | |||
257 | let expected = DirsMultiset { |
|
261 | let expected = DirsMultiset { | |
258 | inner: FastHashMap::default(), |
|
262 | inner: FastHashMap::default(), | |
259 | }; |
|
263 | }; | |
@@ -271,7 +275,7 b' mod tests {' | |||||
271 | .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v)) |
|
275 | .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v)) | |
272 | .collect(); |
|
276 | .collect(); | |
273 |
|
277 | |||
274 | let new = DirsMultiset::from_manifest(&input_vec); |
|
278 | let new = DirsMultiset::from_manifest(&input_vec).unwrap(); | |
275 | let expected = DirsMultiset { |
|
279 | let expected = DirsMultiset { | |
276 | inner: expected_inner, |
|
280 | inner: expected_inner, | |
277 | }; |
|
281 | }; | |
@@ -296,7 +300,7 b' mod tests {' | |||||
296 | .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v)) |
|
300 | .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v)) | |
297 | .collect(); |
|
301 | .collect(); | |
298 |
|
302 | |||
299 | let new = DirsMultiset::from_dirstate(&input_map, None); |
|
303 | let new = DirsMultiset::from_dirstate(&input_map, None).unwrap(); | |
300 | let expected = DirsMultiset { |
|
304 | let expected = DirsMultiset { | |
301 | inner: expected_inner, |
|
305 | inner: expected_inner, | |
302 | }; |
|
306 | }; | |
@@ -332,7 +336,8 b' mod tests {' | |||||
332 | .collect(); |
|
336 | .collect(); | |
333 |
|
337 | |||
334 | let new = |
|
338 | let new = | |
335 |
DirsMultiset::from_dirstate(&input_map, Some(EntryState::Normal)) |
|
339 | DirsMultiset::from_dirstate(&input_map, Some(EntryState::Normal)) | |
|
340 | .unwrap(); | |||
336 | let expected = DirsMultiset { |
|
341 | let expected = DirsMultiset { | |
337 | inner: expected_inner, |
|
342 | inner: expected_inner, | |
338 | }; |
|
343 | }; |
@@ -126,7 +126,7 b' impl DirstateMap {' | |||||
126 | } |
|
126 | } | |
127 | if old_state == EntryState::Unknown { |
|
127 | if old_state == EntryState::Unknown { | |
128 | if let Some(ref mut all_dirs) = self.all_dirs { |
|
128 | if let Some(ref mut all_dirs) = self.all_dirs { | |
129 | all_dirs.add_path(filename); |
|
129 | all_dirs.add_path(filename)?; | |
130 | } |
|
130 | } | |
131 | } |
|
131 | } | |
132 |
|
132 | |||
@@ -227,30 +227,38 b' impl DirstateMap {' | |||||
227 | /// emulate a Python lazy property, but it is ugly and unidiomatic. |
|
227 | /// emulate a Python lazy property, but it is ugly and unidiomatic. | |
228 | /// TODO One day, rewriting this struct using the typestate might be a |
|
228 | /// TODO One day, rewriting this struct using the typestate might be a | |
229 | /// good idea. |
|
229 | /// good idea. | |
230 | pub fn set_all_dirs(&mut self) { |
|
230 | pub fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> { | |
231 | if self.all_dirs.is_none() { |
|
231 | if self.all_dirs.is_none() { | |
232 | self.all_dirs = |
|
232 | self.all_dirs = | |
233 | Some(DirsMultiset::from_dirstate(&self.state_map, None)); |
|
233 | Some(DirsMultiset::from_dirstate(&self.state_map, None)?); | |
234 | } |
|
234 | } | |
|
235 | Ok(()) | |||
235 | } |
|
236 | } | |
236 |
|
237 | |||
237 | pub fn set_dirs(&mut self) { |
|
238 | pub fn set_dirs(&mut self) -> Result<(), DirstateMapError> { | |
238 | if self.dirs.is_none() { |
|
239 | if self.dirs.is_none() { | |
239 | self.dirs = Some(DirsMultiset::from_dirstate( |
|
240 | self.dirs = Some(DirsMultiset::from_dirstate( | |
240 | &self.state_map, |
|
241 | &self.state_map, | |
241 | Some(EntryState::Removed), |
|
242 | Some(EntryState::Removed), | |
242 | )); |
|
243 | )?); | |
243 | } |
|
244 | } | |
|
245 | Ok(()) | |||
244 | } |
|
246 | } | |
245 |
|
247 | |||
246 | pub fn has_tracked_dir(&mut self, directory: &HgPath) -> bool { |
|
248 | pub fn has_tracked_dir( | |
247 | self.set_dirs(); |
|
249 | &mut self, | |
248 | self.dirs.as_ref().unwrap().contains(directory) |
|
250 | directory: &HgPath, | |
|
251 | ) -> Result<bool, DirstateMapError> { | |||
|
252 | self.set_dirs()?; | |||
|
253 | Ok(self.dirs.as_ref().unwrap().contains(directory)) | |||
249 | } |
|
254 | } | |
250 |
|
255 | |||
251 | pub fn has_dir(&mut self, directory: &HgPath) -> bool { |
|
256 | pub fn has_dir( | |
252 | self.set_all_dirs(); |
|
257 | &mut self, | |
253 | self.all_dirs.as_ref().unwrap().contains(directory) |
|
258 | directory: &HgPath, | |
|
259 | ) -> Result<bool, DirstateMapError> { | |||
|
260 | self.set_all_dirs()?; | |||
|
261 | Ok(self.all_dirs.as_ref().unwrap().contains(directory)) | |||
254 | } |
|
262 | } | |
255 |
|
263 | |||
256 | pub fn parents( |
|
264 | pub fn parents( | |
@@ -350,11 +358,11 b' mod tests {' | |||||
350 | assert!(map.dirs.is_none()); |
|
358 | assert!(map.dirs.is_none()); | |
351 | assert!(map.all_dirs.is_none()); |
|
359 | assert!(map.all_dirs.is_none()); | |
352 |
|
360 | |||
353 |
assert_eq!( |
|
361 | assert_eq!(map.has_dir(HgPath::new(b"nope")).unwrap(), false); | |
354 | assert!(map.all_dirs.is_some()); |
|
362 | assert!(map.all_dirs.is_some()); | |
355 | assert!(map.dirs.is_none()); |
|
363 | assert!(map.dirs.is_none()); | |
356 |
|
364 | |||
357 |
assert_eq!( |
|
365 | assert_eq!(map.has_tracked_dir(HgPath::new(b"nope")).unwrap(), false); | |
358 | assert!(map.dirs.is_some()); |
|
366 | assert!(map.dirs.is_some()); | |
359 | } |
|
367 | } | |
360 |
|
368 |
@@ -7,7 +7,7 b'' | |||||
7 |
|
7 | |||
8 | //! Structs and types for matching files and directories. |
|
8 | //! Structs and types for matching files and directories. | |
9 |
|
9 | |||
10 |
use crate::utils::hg_path:: |
|
10 | use crate::utils::hg_path::HgPath; | |
11 | use std::collections::HashSet; |
|
11 | use std::collections::HashSet; | |
12 |
|
12 | |||
13 | pub enum VisitChildrenSet<'a> { |
|
13 | pub enum VisitChildrenSet<'a> { |
@@ -47,6 +47,9 b' py_class!(pub class Dirs |py| {' | |||||
47 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { |
|
47 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { | |
48 | let dirstate = extract_dirstate(py, &map)?; |
|
48 | let dirstate = extract_dirstate(py, &map)?; | |
49 | DirsMultiset::from_dirstate(&dirstate, skip_state) |
|
49 | DirsMultiset::from_dirstate(&dirstate, skip_state) | |
|
50 | .map_err(|e| { | |||
|
51 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
52 | })? | |||
50 | } else { |
|
53 | } else { | |
51 | let map: Result<Vec<HgPathBuf>, PyErr> = map |
|
54 | let map: Result<Vec<HgPathBuf>, PyErr> = map | |
52 | .iter(py)? |
|
55 | .iter(py)? | |
@@ -57,6 +60,9 b' py_class!(pub class Dirs |py| {' | |||||
57 | }) |
|
60 | }) | |
58 | .collect(); |
|
61 | .collect(); | |
59 | DirsMultiset::from_manifest(&map?) |
|
62 | DirsMultiset::from_manifest(&map?) | |
|
63 | .map_err(|e| { | |||
|
64 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
65 | })? | |||
60 | }; |
|
66 | }; | |
61 |
|
67 | |||
62 | Self::create_instance( |
|
68 | Self::create_instance( |
@@ -200,6 +200,9 b' py_class!(pub class DirstateMap |py| {' | |||||
200 | let d = d.extract::<PyBytes>(py)?; |
|
200 | let d = d.extract::<PyBytes>(py)?; | |
201 | Ok(self.inner_shared(py).borrow_mut()? |
|
201 | Ok(self.inner_shared(py).borrow_mut()? | |
202 | .has_tracked_dir(HgPath::new(d.data(py))) |
|
202 | .has_tracked_dir(HgPath::new(d.data(py))) | |
|
203 | .map_err(|e| { | |||
|
204 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
205 | })? | |||
203 | .to_py_object(py)) |
|
206 | .to_py_object(py)) | |
204 | } |
|
207 | } | |
205 |
|
208 | |||
@@ -207,6 +210,9 b' py_class!(pub class DirstateMap |py| {' | |||||
207 | let d = d.extract::<PyBytes>(py)?; |
|
210 | let d = d.extract::<PyBytes>(py)?; | |
208 | Ok(self.inner_shared(py).borrow_mut()? |
|
211 | Ok(self.inner_shared(py).borrow_mut()? | |
209 | .has_dir(HgPath::new(d.data(py))) |
|
212 | .has_dir(HgPath::new(d.data(py))) | |
|
213 | .map_err(|e| { | |||
|
214 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
215 | })? | |||
210 | .to_py_object(py)) |
|
216 | .to_py_object(py)) | |
211 | } |
|
217 | } | |
212 |
|
218 | |||
@@ -330,24 +336,35 b' py_class!(pub class DirstateMap |py| {' | |||||
330 |
|
336 | |||
331 | def getdirs(&self) -> PyResult<Dirs> { |
|
337 | def getdirs(&self) -> PyResult<Dirs> { | |
332 | // TODO don't copy, share the reference |
|
338 | // TODO don't copy, share the reference | |
333 |
self.inner_shared(py).borrow_mut()?.set_dirs() |
|
339 | self.inner_shared(py).borrow_mut()?.set_dirs() | |
|
340 | .map_err(|e| { | |||
|
341 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
342 | })?; | |||
334 | Dirs::from_inner( |
|
343 | Dirs::from_inner( | |
335 | py, |
|
344 | py, | |
336 | DirsMultiset::from_dirstate( |
|
345 | DirsMultiset::from_dirstate( | |
337 | &self.inner_shared(py).borrow(), |
|
346 | &self.inner_shared(py).borrow(), | |
338 | Some(EntryState::Removed), |
|
347 | Some(EntryState::Removed), | |
339 |
) |
|
348 | ) | |
|
349 | .map_err(|e| { | |||
|
350 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
351 | })?, | |||
340 | ) |
|
352 | ) | |
341 | } |
|
353 | } | |
342 | def getalldirs(&self) -> PyResult<Dirs> { |
|
354 | def getalldirs(&self) -> PyResult<Dirs> { | |
343 | // TODO don't copy, share the reference |
|
355 | // TODO don't copy, share the reference | |
344 |
self.inner_shared(py).borrow_mut()?.set_all_dirs() |
|
356 | self.inner_shared(py).borrow_mut()?.set_all_dirs() | |
|
357 | .map_err(|e| { | |||
|
358 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
359 | })?; | |||
345 | Dirs::from_inner( |
|
360 | Dirs::from_inner( | |
346 | py, |
|
361 | py, | |
347 | DirsMultiset::from_dirstate( |
|
362 | DirsMultiset::from_dirstate( | |
348 | &self.inner_shared(py).borrow(), |
|
363 | &self.inner_shared(py).borrow(), | |
349 | None, |
|
364 | None, | |
350 |
) |
|
365 | ).map_err(|e| { | |
|
366 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
367 | })?, | |||
351 | ) |
|
368 | ) | |
352 | } |
|
369 | } | |
353 |
|
370 |
General Comments 0
You need to be logged in to leave comments.
Login now