##// END OF EJS Templates
rust-dirstate: specify concrete return type of DirsMultiset::iter()...
Yuya Nishihara -
r43155:a03a2946 default
parent child Browse files
Show More
@@ -1,319 +1,322 b''
1 // dirs_multiset.rs
1 // dirs_multiset.rs
2 //
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 //! A multiset of directory names.
8 //! A multiset of directory names.
9 //!
9 //!
10 //! Used to counts the references to directories in a manifest or dirstate.
10 //! Used to counts the references to directories in a manifest or dirstate.
11 use crate::{
11 use crate::{
12 dirstate::EntryState, utils::files, DirstateEntry, DirstateMapError,
12 dirstate::EntryState, utils::files, DirstateEntry, DirstateMapError,
13 };
13 };
14 use std::collections::hash_map::Entry;
14 use std::collections::hash_map::{self, Entry};
15 use std::collections::HashMap;
15 use std::collections::HashMap;
16
16
17 // could be encapsulated if we care API stability more seriously
18 pub type DirsMultisetIter<'a> = hash_map::Keys<'a, Vec<u8>, u32>;
19
17 #[derive(PartialEq, Debug)]
20 #[derive(PartialEq, Debug)]
18 pub struct DirsMultiset {
21 pub struct DirsMultiset {
19 inner: HashMap<Vec<u8>, u32>,
22 inner: HashMap<Vec<u8>, u32>,
20 }
23 }
21
24
22 impl DirsMultiset {
25 impl DirsMultiset {
23 /// Initializes the multiset from a dirstate.
26 /// Initializes the multiset from a dirstate.
24 ///
27 ///
25 /// If `skip_state` is provided, skips dirstate entries with equal state.
28 /// If `skip_state` is provided, skips dirstate entries with equal state.
26 pub fn from_dirstate(
29 pub fn from_dirstate(
27 vec: &HashMap<Vec<u8>, DirstateEntry>,
30 vec: &HashMap<Vec<u8>, DirstateEntry>,
28 skip_state: Option<EntryState>,
31 skip_state: Option<EntryState>,
29 ) -> Self {
32 ) -> Self {
30 let mut multiset = DirsMultiset {
33 let mut multiset = DirsMultiset {
31 inner: HashMap::new(),
34 inner: HashMap::new(),
32 };
35 };
33
36
34 for (filename, DirstateEntry { state, .. }) in vec {
37 for (filename, DirstateEntry { state, .. }) in vec {
35 // This `if` is optimized out of the loop
38 // This `if` is optimized out of the loop
36 if let Some(skip) = skip_state {
39 if let Some(skip) = skip_state {
37 if skip != *state {
40 if skip != *state {
38 multiset.add_path(filename);
41 multiset.add_path(filename);
39 }
42 }
40 } else {
43 } else {
41 multiset.add_path(filename);
44 multiset.add_path(filename);
42 }
45 }
43 }
46 }
44
47
45 multiset
48 multiset
46 }
49 }
47
50
48 /// Initializes the multiset from a manifest.
51 /// Initializes the multiset from a manifest.
49 pub fn from_manifest(vec: &Vec<Vec<u8>>) -> Self {
52 pub fn from_manifest(vec: &Vec<Vec<u8>>) -> Self {
50 let mut multiset = DirsMultiset {
53 let mut multiset = DirsMultiset {
51 inner: HashMap::new(),
54 inner: HashMap::new(),
52 };
55 };
53
56
54 for filename in vec {
57 for filename in vec {
55 multiset.add_path(filename);
58 multiset.add_path(filename);
56 }
59 }
57
60
58 multiset
61 multiset
59 }
62 }
60
63
61 /// Increases the count of deepest directory contained in the path.
64 /// Increases the count of deepest directory contained in the path.
62 ///
65 ///
63 /// If the directory is not yet in the map, adds its parents.
66 /// If the directory is not yet in the map, adds its parents.
64 pub fn add_path(&mut self, path: &[u8]) {
67 pub fn add_path(&mut self, path: &[u8]) {
65 for subpath in files::find_dirs(path) {
68 for subpath in files::find_dirs(path) {
66 if let Some(val) = self.inner.get_mut(subpath) {
69 if let Some(val) = self.inner.get_mut(subpath) {
67 *val += 1;
70 *val += 1;
68 break;
71 break;
69 }
72 }
70 self.inner.insert(subpath.to_owned(), 1);
73 self.inner.insert(subpath.to_owned(), 1);
71 }
74 }
72 }
75 }
73
76
74 /// Decreases the count of deepest directory contained in the path.
77 /// Decreases the count of deepest directory contained in the path.
75 ///
78 ///
76 /// If it is the only reference, decreases all parents until one is
79 /// If it is the only reference, decreases all parents until one is
77 /// removed.
80 /// removed.
78 /// If the directory is not in the map, something horrible has happened.
81 /// If the directory is not in the map, something horrible has happened.
79 pub fn delete_path(
82 pub fn delete_path(
80 &mut self,
83 &mut self,
81 path: &[u8],
84 path: &[u8],
82 ) -> Result<(), DirstateMapError> {
85 ) -> Result<(), DirstateMapError> {
83 for subpath in files::find_dirs(path) {
86 for subpath in files::find_dirs(path) {
84 match self.inner.entry(subpath.to_owned()) {
87 match self.inner.entry(subpath.to_owned()) {
85 Entry::Occupied(mut entry) => {
88 Entry::Occupied(mut entry) => {
86 let val = entry.get().clone();
89 let val = entry.get().clone();
87 if val > 1 {
90 if val > 1 {
88 entry.insert(val - 1);
91 entry.insert(val - 1);
89 break;
92 break;
90 }
93 }
91 entry.remove();
94 entry.remove();
92 }
95 }
93 Entry::Vacant(_) => {
96 Entry::Vacant(_) => {
94 return Err(DirstateMapError::PathNotFound(
97 return Err(DirstateMapError::PathNotFound(
95 path.to_owned(),
98 path.to_owned(),
96 ))
99 ))
97 }
100 }
98 };
101 };
99 }
102 }
100
103
101 Ok(())
104 Ok(())
102 }
105 }
103
106
104 pub fn contains(&self, key: &[u8]) -> bool {
107 pub fn contains(&self, key: &[u8]) -> bool {
105 self.inner.contains_key(key)
108 self.inner.contains_key(key)
106 }
109 }
107
110
108 pub fn iter(&self) -> impl Iterator<Item = &Vec<u8>> {
111 pub fn iter(&self) -> DirsMultisetIter {
109 self.inner.keys()
112 self.inner.keys()
110 }
113 }
111
114
112 pub fn len(&self) -> usize {
115 pub fn len(&self) -> usize {
113 self.inner.len()
116 self.inner.len()
114 }
117 }
115 }
118 }
116
119
117 #[cfg(test)]
120 #[cfg(test)]
118 mod tests {
121 mod tests {
119 use super::*;
122 use super::*;
120 use std::collections::HashMap;
123 use std::collections::HashMap;
121
124
122 #[test]
125 #[test]
123 fn test_delete_path_path_not_found() {
126 fn test_delete_path_path_not_found() {
124 let mut map = DirsMultiset::from_manifest(&vec![]);
127 let mut map = DirsMultiset::from_manifest(&vec![]);
125 let path = b"doesnotexist/";
128 let path = b"doesnotexist/";
126 assert_eq!(
129 assert_eq!(
127 Err(DirstateMapError::PathNotFound(path.to_vec())),
130 Err(DirstateMapError::PathNotFound(path.to_vec())),
128 map.delete_path(path)
131 map.delete_path(path)
129 );
132 );
130 }
133 }
131
134
132 #[test]
135 #[test]
133 fn test_delete_path_empty_path() {
136 fn test_delete_path_empty_path() {
134 let mut map = DirsMultiset::from_manifest(&vec![vec![]]);
137 let mut map = DirsMultiset::from_manifest(&vec![vec![]]);
135 let path = b"";
138 let path = b"";
136 assert_eq!(Ok(()), map.delete_path(path));
139 assert_eq!(Ok(()), map.delete_path(path));
137 assert_eq!(
140 assert_eq!(
138 Err(DirstateMapError::PathNotFound(path.to_vec())),
141 Err(DirstateMapError::PathNotFound(path.to_vec())),
139 map.delete_path(path)
142 map.delete_path(path)
140 );
143 );
141 }
144 }
142
145
143 #[test]
146 #[test]
144 fn test_delete_path_successful() {
147 fn test_delete_path_successful() {
145 let mut map = DirsMultiset {
148 let mut map = DirsMultiset {
146 inner: [("", 5), ("a", 3), ("a/b", 2), ("a/c", 1)]
149 inner: [("", 5), ("a", 3), ("a/b", 2), ("a/c", 1)]
147 .iter()
150 .iter()
148 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
151 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
149 .collect(),
152 .collect(),
150 };
153 };
151
154
152 assert_eq!(Ok(()), map.delete_path(b"a/b/"));
155 assert_eq!(Ok(()), map.delete_path(b"a/b/"));
153 assert_eq!(Ok(()), map.delete_path(b"a/b/"));
156 assert_eq!(Ok(()), map.delete_path(b"a/b/"));
154 assert_eq!(
157 assert_eq!(
155 Err(DirstateMapError::PathNotFound(b"a/b/".to_vec())),
158 Err(DirstateMapError::PathNotFound(b"a/b/".to_vec())),
156 map.delete_path(b"a/b/")
159 map.delete_path(b"a/b/")
157 );
160 );
158
161
159 assert_eq!(2, *map.inner.get(&b"a".to_vec()).unwrap());
162 assert_eq!(2, *map.inner.get(&b"a".to_vec()).unwrap());
160 assert_eq!(1, *map.inner.get(&b"a/c".to_vec()).unwrap());
163 assert_eq!(1, *map.inner.get(&b"a/c".to_vec()).unwrap());
161 eprintln!("{:?}", map);
164 eprintln!("{:?}", map);
162 assert_eq!(Ok(()), map.delete_path(b"a/"));
165 assert_eq!(Ok(()), map.delete_path(b"a/"));
163 eprintln!("{:?}", map);
166 eprintln!("{:?}", map);
164
167
165 assert_eq!(Ok(()), map.delete_path(b"a/c/"));
168 assert_eq!(Ok(()), map.delete_path(b"a/c/"));
166 assert_eq!(
169 assert_eq!(
167 Err(DirstateMapError::PathNotFound(b"a/c/".to_vec())),
170 Err(DirstateMapError::PathNotFound(b"a/c/".to_vec())),
168 map.delete_path(b"a/c/")
171 map.delete_path(b"a/c/")
169 );
172 );
170 }
173 }
171
174
172 #[test]
175 #[test]
173 fn test_add_path_empty_path() {
176 fn test_add_path_empty_path() {
174 let mut map = DirsMultiset::from_manifest(&vec![]);
177 let mut map = DirsMultiset::from_manifest(&vec![]);
175 let path = b"";
178 let path = b"";
176 map.add_path(path);
179 map.add_path(path);
177
180
178 assert_eq!(1, map.len());
181 assert_eq!(1, map.len());
179 }
182 }
180
183
181 #[test]
184 #[test]
182 fn test_add_path_successful() {
185 fn test_add_path_successful() {
183 let mut map = DirsMultiset::from_manifest(&vec![]);
186 let mut map = DirsMultiset::from_manifest(&vec![]);
184
187
185 map.add_path(b"a/");
188 map.add_path(b"a/");
186 assert_eq!(1, *map.inner.get(&b"a".to_vec()).unwrap());
189 assert_eq!(1, *map.inner.get(&b"a".to_vec()).unwrap());
187 assert_eq!(1, *map.inner.get(&Vec::new()).unwrap());
190 assert_eq!(1, *map.inner.get(&Vec::new()).unwrap());
188 assert_eq!(2, map.len());
191 assert_eq!(2, map.len());
189
192
190 // Non directory should be ignored
193 // Non directory should be ignored
191 map.add_path(b"a");
194 map.add_path(b"a");
192 assert_eq!(1, *map.inner.get(&b"a".to_vec()).unwrap());
195 assert_eq!(1, *map.inner.get(&b"a".to_vec()).unwrap());
193 assert_eq!(2, map.len());
196 assert_eq!(2, map.len());
194
197
195 // Non directory will still add its base
198 // Non directory will still add its base
196 map.add_path(b"a/b");
199 map.add_path(b"a/b");
197 assert_eq!(2, *map.inner.get(&b"a".to_vec()).unwrap());
200 assert_eq!(2, *map.inner.get(&b"a".to_vec()).unwrap());
198 assert_eq!(2, map.len());
201 assert_eq!(2, map.len());
199
202
200 // Duplicate path works
203 // Duplicate path works
201 map.add_path(b"a/");
204 map.add_path(b"a/");
202 assert_eq!(3, *map.inner.get(&b"a".to_vec()).unwrap());
205 assert_eq!(3, *map.inner.get(&b"a".to_vec()).unwrap());
203
206
204 // Nested dir adds to its base
207 // Nested dir adds to its base
205 map.add_path(b"a/b/");
208 map.add_path(b"a/b/");
206 assert_eq!(4, *map.inner.get(&b"a".to_vec()).unwrap());
209 assert_eq!(4, *map.inner.get(&b"a".to_vec()).unwrap());
207 assert_eq!(1, *map.inner.get(&b"a/b".to_vec()).unwrap());
210 assert_eq!(1, *map.inner.get(&b"a/b".to_vec()).unwrap());
208
211
209 // but not its base's base, because it already existed
212 // but not its base's base, because it already existed
210 map.add_path(b"a/b/c/");
213 map.add_path(b"a/b/c/");
211 assert_eq!(4, *map.inner.get(&b"a".to_vec()).unwrap());
214 assert_eq!(4, *map.inner.get(&b"a".to_vec()).unwrap());
212 assert_eq!(2, *map.inner.get(&b"a/b".to_vec()).unwrap());
215 assert_eq!(2, *map.inner.get(&b"a/b".to_vec()).unwrap());
213
216
214 map.add_path(b"a/c/");
217 map.add_path(b"a/c/");
215 assert_eq!(1, *map.inner.get(&b"a/c".to_vec()).unwrap());
218 assert_eq!(1, *map.inner.get(&b"a/c".to_vec()).unwrap());
216
219
217 let expected = DirsMultiset {
220 let expected = DirsMultiset {
218 inner: [("", 2), ("a", 5), ("a/b", 2), ("a/b/c", 1), ("a/c", 1)]
221 inner: [("", 2), ("a", 5), ("a/b", 2), ("a/b/c", 1), ("a/c", 1)]
219 .iter()
222 .iter()
220 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
223 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
221 .collect(),
224 .collect(),
222 };
225 };
223 assert_eq!(map, expected);
226 assert_eq!(map, expected);
224 }
227 }
225
228
226 #[test]
229 #[test]
227 fn test_dirsmultiset_new_empty() {
230 fn test_dirsmultiset_new_empty() {
228 let new = DirsMultiset::from_manifest(&vec![]);
231 let new = DirsMultiset::from_manifest(&vec![]);
229 let expected = DirsMultiset {
232 let expected = DirsMultiset {
230 inner: HashMap::new(),
233 inner: HashMap::new(),
231 };
234 };
232 assert_eq!(expected, new);
235 assert_eq!(expected, new);
233
236
234 let new = DirsMultiset::from_dirstate(&HashMap::new(), None);
237 let new = DirsMultiset::from_dirstate(&HashMap::new(), None);
235 let expected = DirsMultiset {
238 let expected = DirsMultiset {
236 inner: HashMap::new(),
239 inner: HashMap::new(),
237 };
240 };
238 assert_eq!(expected, new);
241 assert_eq!(expected, new);
239 }
242 }
240
243
241 #[test]
244 #[test]
242 fn test_dirsmultiset_new_no_skip() {
245 fn test_dirsmultiset_new_no_skip() {
243 let input_vec = ["a/", "b/", "a/c", "a/d/"]
246 let input_vec = ["a/", "b/", "a/c", "a/d/"]
244 .iter()
247 .iter()
245 .map(|e| e.as_bytes().to_vec())
248 .map(|e| e.as_bytes().to_vec())
246 .collect();
249 .collect();
247 let expected_inner = [("", 2), ("a", 3), ("b", 1), ("a/d", 1)]
250 let expected_inner = [("", 2), ("a", 3), ("b", 1), ("a/d", 1)]
248 .iter()
251 .iter()
249 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
252 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
250 .collect();
253 .collect();
251
254
252 let new = DirsMultiset::from_manifest(&input_vec);
255 let new = DirsMultiset::from_manifest(&input_vec);
253 let expected = DirsMultiset {
256 let expected = DirsMultiset {
254 inner: expected_inner,
257 inner: expected_inner,
255 };
258 };
256 assert_eq!(expected, new);
259 assert_eq!(expected, new);
257
260
258 let input_map = ["a/", "b/", "a/c", "a/d/"]
261 let input_map = ["a/", "b/", "a/c", "a/d/"]
259 .iter()
262 .iter()
260 .map(|f| {
263 .map(|f| {
261 (
264 (
262 f.as_bytes().to_vec(),
265 f.as_bytes().to_vec(),
263 DirstateEntry {
266 DirstateEntry {
264 state: EntryState::Normal,
267 state: EntryState::Normal,
265 mode: 0,
268 mode: 0,
266 mtime: 0,
269 mtime: 0,
267 size: 0,
270 size: 0,
268 },
271 },
269 )
272 )
270 })
273 })
271 .collect();
274 .collect();
272 let expected_inner = [("", 2), ("a", 3), ("b", 1), ("a/d", 1)]
275 let expected_inner = [("", 2), ("a", 3), ("b", 1), ("a/d", 1)]
273 .iter()
276 .iter()
274 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
277 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
275 .collect();
278 .collect();
276
279
277 let new = DirsMultiset::from_dirstate(&input_map, None);
280 let new = DirsMultiset::from_dirstate(&input_map, None);
278 let expected = DirsMultiset {
281 let expected = DirsMultiset {
279 inner: expected_inner,
282 inner: expected_inner,
280 };
283 };
281 assert_eq!(expected, new);
284 assert_eq!(expected, new);
282 }
285 }
283
286
284 #[test]
287 #[test]
285 fn test_dirsmultiset_new_skip() {
288 fn test_dirsmultiset_new_skip() {
286 let input_map = [
289 let input_map = [
287 ("a/", EntryState::Normal),
290 ("a/", EntryState::Normal),
288 ("a/b/", EntryState::Normal),
291 ("a/b/", EntryState::Normal),
289 ("a/c", EntryState::Removed),
292 ("a/c", EntryState::Removed),
290 ("a/d/", EntryState::Merged),
293 ("a/d/", EntryState::Merged),
291 ]
294 ]
292 .iter()
295 .iter()
293 .map(|(f, state)| {
296 .map(|(f, state)| {
294 (
297 (
295 f.as_bytes().to_vec(),
298 f.as_bytes().to_vec(),
296 DirstateEntry {
299 DirstateEntry {
297 state: *state,
300 state: *state,
298 mode: 0,
301 mode: 0,
299 mtime: 0,
302 mtime: 0,
300 size: 0,
303 size: 0,
301 },
304 },
302 )
305 )
303 })
306 })
304 .collect();
307 .collect();
305
308
306 // "a" incremented with "a/c" and "a/d/"
309 // "a" incremented with "a/c" and "a/d/"
307 let expected_inner = [("", 1), ("a", 2), ("a/d", 1)]
310 let expected_inner = [("", 1), ("a", 2), ("a/d", 1)]
308 .iter()
311 .iter()
309 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
312 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
310 .collect();
313 .collect();
311
314
312 let new =
315 let new =
313 DirsMultiset::from_dirstate(&input_map, Some(EntryState::Normal));
316 DirsMultiset::from_dirstate(&input_map, Some(EntryState::Normal));
314 let expected = DirsMultiset {
317 let expected = DirsMultiset {
315 inner: expected_inner,
318 inner: expected_inner,
316 };
319 };
317 assert_eq!(expected, new);
320 assert_eq!(expected, new);
318 }
321 }
319 }
322 }
@@ -1,148 +1,148 b''
1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
2 //
2 //
3 // This software may be used and distributed according to the terms of the
3 // This software may be used and distributed according to the terms of the
4 // GNU General Public License version 2 or any later version.
4 // GNU General Public License version 2 or any later version.
5 mod ancestors;
5 mod ancestors;
6 pub mod dagops;
6 pub mod dagops;
7 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
7 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
8 mod dirstate;
8 mod dirstate;
9 pub mod discovery;
9 pub mod discovery;
10 pub mod testing; // unconditionally built, for use from integration tests
10 pub mod testing; // unconditionally built, for use from integration tests
11 pub use dirstate::{
11 pub use dirstate::{
12 dirs_multiset::DirsMultiset,
12 dirs_multiset::{DirsMultiset, DirsMultisetIter},
13 dirstate_map::DirstateMap,
13 dirstate_map::DirstateMap,
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
15 CopyMap, DirstateEntry, DirstateParents, EntryState, StateMap,
15 CopyMap, DirstateEntry, DirstateParents, EntryState, StateMap,
16 };
16 };
17 mod filepatterns;
17 mod filepatterns;
18 pub mod utils;
18 pub mod utils;
19
19
20 pub use filepatterns::{
20 pub use filepatterns::{
21 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
21 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
22 };
22 };
23
23
24 /// Mercurial revision numbers
24 /// Mercurial revision numbers
25 ///
25 ///
26 /// As noted in revlog.c, revision numbers are actually encoded in
26 /// As noted in revlog.c, revision numbers are actually encoded in
27 /// 4 bytes, and are liberally converted to ints, whence the i32
27 /// 4 bytes, and are liberally converted to ints, whence the i32
28 pub type Revision = i32;
28 pub type Revision = i32;
29
29
30 /// Marker expressing the absence of a parent
30 /// Marker expressing the absence of a parent
31 ///
31 ///
32 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
32 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
33 /// to be smaller that all existing revisions.
33 /// to be smaller that all existing revisions.
34 pub const NULL_REVISION: Revision = -1;
34 pub const NULL_REVISION: Revision = -1;
35
35
36 /// Same as `mercurial.node.wdirrev`
36 /// Same as `mercurial.node.wdirrev`
37 ///
37 ///
38 /// This is also equal to `i32::max_value()`, but it's better to spell
38 /// This is also equal to `i32::max_value()`, but it's better to spell
39 /// it out explicitely, same as in `mercurial.node`
39 /// it out explicitely, same as in `mercurial.node`
40 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
40 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
41
41
42 /// The simplest expression of what we need of Mercurial DAGs.
42 /// The simplest expression of what we need of Mercurial DAGs.
43 pub trait Graph {
43 pub trait Graph {
44 /// Return the two parents of the given `Revision`.
44 /// Return the two parents of the given `Revision`.
45 ///
45 ///
46 /// Each of the parents can be independently `NULL_REVISION`
46 /// Each of the parents can be independently `NULL_REVISION`
47 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
47 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
48 }
48 }
49
49
50 pub type LineNumber = usize;
50 pub type LineNumber = usize;
51
51
52 #[derive(Clone, Debug, PartialEq)]
52 #[derive(Clone, Debug, PartialEq)]
53 pub enum GraphError {
53 pub enum GraphError {
54 ParentOutOfRange(Revision),
54 ParentOutOfRange(Revision),
55 WorkingDirectoryUnsupported,
55 WorkingDirectoryUnsupported,
56 }
56 }
57
57
58 #[derive(Clone, Debug, PartialEq)]
58 #[derive(Clone, Debug, PartialEq)]
59 pub enum DirstateParseError {
59 pub enum DirstateParseError {
60 TooLittleData,
60 TooLittleData,
61 Overflow,
61 Overflow,
62 CorruptedEntry(String),
62 CorruptedEntry(String),
63 Damaged,
63 Damaged,
64 }
64 }
65
65
66 impl From<std::io::Error> for DirstateParseError {
66 impl From<std::io::Error> for DirstateParseError {
67 fn from(e: std::io::Error) -> Self {
67 fn from(e: std::io::Error) -> Self {
68 DirstateParseError::CorruptedEntry(e.to_string())
68 DirstateParseError::CorruptedEntry(e.to_string())
69 }
69 }
70 }
70 }
71
71
72 impl ToString for DirstateParseError {
72 impl ToString for DirstateParseError {
73 fn to_string(&self) -> String {
73 fn to_string(&self) -> String {
74 use crate::DirstateParseError::*;
74 use crate::DirstateParseError::*;
75 match self {
75 match self {
76 TooLittleData => "Too little data for dirstate.".to_string(),
76 TooLittleData => "Too little data for dirstate.".to_string(),
77 Overflow => "Overflow in dirstate.".to_string(),
77 Overflow => "Overflow in dirstate.".to_string(),
78 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
78 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
79 Damaged => "Dirstate appears to be damaged.".to_string(),
79 Damaged => "Dirstate appears to be damaged.".to_string(),
80 }
80 }
81 }
81 }
82 }
82 }
83
83
84 #[derive(Debug, PartialEq)]
84 #[derive(Debug, PartialEq)]
85 pub enum DirstatePackError {
85 pub enum DirstatePackError {
86 CorruptedEntry(String),
86 CorruptedEntry(String),
87 CorruptedParent,
87 CorruptedParent,
88 BadSize(usize, usize),
88 BadSize(usize, usize),
89 }
89 }
90
90
91 impl From<std::io::Error> for DirstatePackError {
91 impl From<std::io::Error> for DirstatePackError {
92 fn from(e: std::io::Error) -> Self {
92 fn from(e: std::io::Error) -> Self {
93 DirstatePackError::CorruptedEntry(e.to_string())
93 DirstatePackError::CorruptedEntry(e.to_string())
94 }
94 }
95 }
95 }
96 #[derive(Debug, PartialEq)]
96 #[derive(Debug, PartialEq)]
97 pub enum DirstateMapError {
97 pub enum DirstateMapError {
98 PathNotFound(Vec<u8>),
98 PathNotFound(Vec<u8>),
99 EmptyPath,
99 EmptyPath,
100 }
100 }
101
101
102 pub enum DirstateError {
102 pub enum DirstateError {
103 Parse(DirstateParseError),
103 Parse(DirstateParseError),
104 Pack(DirstatePackError),
104 Pack(DirstatePackError),
105 Map(DirstateMapError),
105 Map(DirstateMapError),
106 IO(std::io::Error),
106 IO(std::io::Error),
107 }
107 }
108
108
109 impl From<DirstateParseError> for DirstateError {
109 impl From<DirstateParseError> for DirstateError {
110 fn from(e: DirstateParseError) -> Self {
110 fn from(e: DirstateParseError) -> Self {
111 DirstateError::Parse(e)
111 DirstateError::Parse(e)
112 }
112 }
113 }
113 }
114
114
115 impl From<DirstatePackError> for DirstateError {
115 impl From<DirstatePackError> for DirstateError {
116 fn from(e: DirstatePackError) -> Self {
116 fn from(e: DirstatePackError) -> Self {
117 DirstateError::Pack(e)
117 DirstateError::Pack(e)
118 }
118 }
119 }
119 }
120
120
121 #[derive(Debug)]
121 #[derive(Debug)]
122 pub enum PatternError {
122 pub enum PatternError {
123 UnsupportedSyntax(String),
123 UnsupportedSyntax(String),
124 }
124 }
125
125
126 #[derive(Debug)]
126 #[derive(Debug)]
127 pub enum PatternFileError {
127 pub enum PatternFileError {
128 IO(std::io::Error),
128 IO(std::io::Error),
129 Pattern(PatternError, LineNumber),
129 Pattern(PatternError, LineNumber),
130 }
130 }
131
131
132 impl From<std::io::Error> for PatternFileError {
132 impl From<std::io::Error> for PatternFileError {
133 fn from(e: std::io::Error) -> Self {
133 fn from(e: std::io::Error) -> Self {
134 PatternFileError::IO(e)
134 PatternFileError::IO(e)
135 }
135 }
136 }
136 }
137
137
138 impl From<DirstateMapError> for DirstateError {
138 impl From<DirstateMapError> for DirstateError {
139 fn from(e: DirstateMapError) -> Self {
139 fn from(e: DirstateMapError) -> Self {
140 DirstateError::Map(e)
140 DirstateError::Map(e)
141 }
141 }
142 }
142 }
143
143
144 impl From<std::io::Error> for DirstateError {
144 impl From<std::io::Error> for DirstateError {
145 fn from(e: std::io::Error) -> Self {
145 fn from(e: std::io::Error) -> Self {
146 DirstateError::IO(e)
146 DirstateError::IO(e)
147 }
147 }
148 }
148 }
General Comments 0
You need to be logged in to leave comments. Login now