9 use crate::revlog::revlog::RevlogError; |
9 use crate::revlog::revlog::RevlogError; |
10 use crate::revlog::Node; |
10 use crate::revlog::Node; |
11 |
11 |
12 use crate::utils::hg_path::HgPath; |
12 use crate::utils::hg_path::HgPath; |
13 |
13 |
|
14 use crate::errors::HgError; |
14 use itertools::put_back; |
15 use itertools::put_back; |
15 use itertools::PutBack; |
16 use itertools::PutBack; |
16 use std::cmp::Ordering; |
17 use std::cmp::Ordering; |
17 |
18 |
18 pub struct CatOutput<'a> { |
19 pub struct CatOutput<'a> { |
26 /// The node ID that the given revset was resolved to |
27 /// The node ID that the given revset was resolved to |
27 pub node: Node, |
28 pub node: Node, |
28 } |
29 } |
29 |
30 |
30 // Find an item in an iterator over a sorted collection. |
31 // Find an item in an iterator over a sorted collection. |
31 fn find_item<'a, 'b, 'c, D, I: Iterator<Item = (&'a HgPath, D)>>( |
32 fn find_item<'a, D, I: Iterator<Item = Result<(&'a HgPath, D), HgError>>>( |
32 i: &mut PutBack<I>, |
33 i: &mut PutBack<I>, |
33 needle: &'b HgPath, |
34 needle: &HgPath, |
34 ) -> Option<D> { |
35 ) -> Result<Option<D>, HgError> { |
35 loop { |
36 loop { |
36 match i.next() { |
37 match i.next() { |
37 None => return None, |
38 None => return Ok(None), |
38 Some(val) => match needle.as_bytes().cmp(val.0.as_bytes()) { |
39 Some(result) => { |
39 Ordering::Less => { |
40 let (path, value) = result?; |
40 i.put_back(val); |
41 match needle.as_bytes().cmp(path.as_bytes()) { |
41 return None; |
42 Ordering::Less => { |
|
43 i.put_back(Ok((path, value))); |
|
44 return Ok(None); |
|
45 } |
|
46 Ordering::Greater => continue, |
|
47 Ordering::Equal => return Ok(Some(value)), |
42 } |
48 } |
43 Ordering::Greater => continue, |
49 } |
44 Ordering::Equal => return Some(val.1), |
|
45 }, |
|
46 } |
50 } |
47 } |
51 } |
48 } |
52 } |
49 |
53 |
50 fn find_files_in_manifest< |
54 fn find_files_in_manifest< |
51 'manifest, |
55 'manifest, |
52 'query, |
56 'query, |
53 Data, |
57 Data, |
54 Manifest: Iterator<Item = (&'manifest HgPath, Data)>, |
58 Manifest: Iterator<Item = Result<(&'manifest HgPath, Data), HgError>>, |
55 Query: Iterator<Item = &'query HgPath>, |
59 Query: Iterator<Item = &'query HgPath>, |
56 >( |
60 >( |
57 manifest: Manifest, |
61 manifest: Manifest, |
58 query: Query, |
62 query: Query, |
59 ) -> (Vec<(&'query HgPath, Data)>, Vec<&'query HgPath>) { |
63 ) -> Result<(Vec<(&'query HgPath, Data)>, Vec<&'query HgPath>), HgError> { |
60 let mut manifest = put_back(manifest); |
64 let mut manifest = put_back(manifest); |
61 let mut res = vec![]; |
65 let mut res = vec![]; |
62 let mut missing = vec![]; |
66 let mut missing = vec![]; |
63 |
67 |
64 for file in query { |
68 for file in query { |
65 match find_item(&mut manifest, file) { |
69 match find_item(&mut manifest, file)? { |
66 None => missing.push(file), |
70 None => missing.push(file), |
67 Some(item) => res.push((file, item)), |
71 Some(item) => res.push((file, item)), |
68 } |
72 } |
69 } |
73 } |
70 return (res, missing); |
74 return Ok((res, missing)); |
71 } |
75 } |
72 |
76 |
73 /// Output the given revision of files |
77 /// Output the given revision of files |
74 /// |
78 /// |
75 /// * `root`: Repository root |
79 /// * `root`: Repository root |
92 files.sort_unstable(); |
96 files.sort_unstable(); |
93 |
97 |
94 let (found, missing) = find_files_in_manifest( |
98 let (found, missing) = find_files_in_manifest( |
95 manifest.files_with_nodes(), |
99 manifest.files_with_nodes(), |
96 files.into_iter().map(|f| f.as_ref()), |
100 files.into_iter().map(|f| f.as_ref()), |
97 ); |
101 )?; |
98 |
102 |
99 for (file_path, node_bytes) in found { |
103 for (file_path, node_bytes) in found { |
100 found_any = true; |
104 found_any = true; |
101 let file_log = repo.filelog(file_path)?; |
105 let file_log = repo.filelog(file_path)?; |
102 let file_node = Node::from_hex_for_repo(node_bytes)?; |
106 let file_node = Node::from_hex_for_repo(node_bytes)?; |