5 // Raphaël Gomès <rgomes@octobus.net> |
5 // Raphaël Gomès <rgomes@octobus.net> |
6 // |
6 // |
7 // This software may be used and distributed according to the terms of the |
7 // This software may be used and distributed according to the terms of the |
8 // GNU General Public License version 2 or any later version. |
8 // GNU General Public License version 2 or any later version. |
9 |
9 |
|
10 use crate::errors::{HgError, IoResultExt}; |
10 use crate::utils::files::{ |
11 use crate::utils::files::{ |
11 get_bytes_from_path, get_path_from_bytes, read_whole_file, |
12 get_bytes_from_path, get_path_from_bytes, read_whole_file, |
12 }; |
13 }; |
13 use format_bytes::format_bytes; |
14 use format_bytes::format_bytes; |
14 use lazy_static::lazy_static; |
15 use lazy_static::lazy_static; |
97 |
98 |
98 while let Some((index, bytes)) = lines_iter.next() { |
99 while let Some((index, bytes)) = lines_iter.next() { |
99 if let Some(m) = INCLUDE_RE.captures(&bytes) { |
100 if let Some(m) = INCLUDE_RE.captures(&bytes) { |
100 let filename_bytes = &m[1]; |
101 let filename_bytes = &m[1]; |
101 let filename_to_include = get_path_from_bytes(&filename_bytes); |
102 let filename_to_include = get_path_from_bytes(&filename_bytes); |
102 match read_include(&src, &filename_to_include) { |
103 let (include_src, result) = |
103 (include_src, Ok(data)) => { |
104 read_include(&src, &filename_to_include); |
104 layers.push(current_layer); |
105 let data = result.for_file(filename_to_include)?; |
105 layers.extend(Self::parse(&include_src, &data)?); |
106 layers.push(current_layer); |
106 current_layer = |
107 layers.extend(Self::parse(&include_src, &data)?); |
107 Self::new(ConfigOrigin::File(src.to_owned())); |
108 current_layer = Self::new(ConfigOrigin::File(src.to_owned())); |
108 } |
|
109 (_, Err(e)) => { |
|
110 return Err(ConfigError::IncludeError { |
|
111 path: filename_to_include.to_owned(), |
|
112 io_error: e, |
|
113 }) |
|
114 } |
|
115 } |
|
116 } else if let Some(_) = EMPTY_RE.captures(&bytes) { |
109 } else if let Some(_) = EMPTY_RE.captures(&bytes) { |
117 } else if let Some(m) = SECTION_RE.captures(&bytes) { |
110 } else if let Some(m) = SECTION_RE.captures(&bytes) { |
118 section = m[1].to_vec(); |
111 section = m[1].to_vec(); |
119 } else if let Some(m) = ITEM_RE.captures(&bytes) { |
112 } else if let Some(m) = ITEM_RE.captures(&bytes) { |
120 let item = m[1].to_vec(); |
113 let item = m[1].to_vec(); |
143 } else if let Some(m) = UNSET_RE.captures(&bytes) { |
136 } else if let Some(m) = UNSET_RE.captures(&bytes) { |
144 if let Some(map) = current_layer.sections.get_mut(§ion) { |
137 if let Some(map) = current_layer.sections.get_mut(§ion) { |
145 map.remove(&m[1]); |
138 map.remove(&m[1]); |
146 } |
139 } |
147 } else { |
140 } else { |
148 return Err(ConfigError::Parse { |
141 return Err(ConfigParseError { |
149 origin: ConfigOrigin::File(src.to_owned()), |
142 origin: ConfigOrigin::File(src.to_owned()), |
150 line: Some(index + 1), |
143 line: Some(index + 1), |
151 bytes: bytes.to_owned(), |
144 bytes: bytes.to_owned(), |
152 }); |
145 } |
|
146 .into()); |
153 } |
147 } |
154 } |
148 } |
155 if !current_layer.is_empty() { |
149 if !current_layer.is_empty() { |
156 layers.push(current_layer); |
150 layers.push(current_layer); |
157 } |
151 } |
224 ConfigOrigin::Environment(e) => e.to_owned(), |
218 ConfigOrigin::Environment(e) => e.to_owned(), |
225 } |
219 } |
226 } |
220 } |
227 } |
221 } |
228 |
222 |
|
223 #[derive(Debug)] |
|
224 pub struct ConfigParseError { |
|
225 pub origin: ConfigOrigin, |
|
226 pub line: Option<usize>, |
|
227 pub bytes: Vec<u8>, |
|
228 } |
|
229 |
229 #[derive(Debug, derive_more::From)] |
230 #[derive(Debug, derive_more::From)] |
230 pub enum ConfigError { |
231 pub enum ConfigError { |
231 Parse { |
232 Parse(ConfigParseError), |
232 origin: ConfigOrigin, |
233 Other(HgError), |
233 line: Option<usize>, |
|
234 bytes: Vec<u8>, |
|
235 }, |
|
236 /// Failed to include a sub config file |
|
237 IncludeError { |
|
238 path: PathBuf, |
|
239 io_error: std::io::Error, |
|
240 }, |
|
241 /// Any IO error that isn't expected |
|
242 #[from] |
|
243 IO(std::io::Error), |
|
244 } |
234 } |
245 |
235 |
246 fn make_regex(pattern: &'static str) -> Regex { |
236 fn make_regex(pattern: &'static str) -> Regex { |
247 Regex::new(pattern).expect("expected a valid regex") |
237 Regex::new(pattern).expect("expected a valid regex") |
248 } |
238 } |