diff --git a/rust/hg-core/src/config/config.rs b/rust/hg-core/src/config/config.rs --- a/rust/hg-core/src/config/config.rs +++ b/rust/hg-core/src/config/config.rs @@ -8,7 +8,9 @@ // GNU General Public License version 2 or any later version. use super::layer; -use crate::config::layer::{ConfigError, ConfigLayer, ConfigValue}; +use crate::config::layer::{ + ConfigError, ConfigLayer, ConfigParseError, ConfigValue, +}; use std::path::PathBuf; use crate::repo::Repo; @@ -89,11 +91,11 @@ impl Config { &self, section: &[u8], item: &[u8], - ) -> Result, ConfigError> { + ) -> Result, ConfigParseError> { match self.get_inner(§ion, &item) { Some((layer, v)) => match parse_bool(&v.bytes) { Some(b) => Ok(Some(b)), - None => Err(ConfigError::Parse { + None => Err(ConfigParseError { origin: layer.origin.to_owned(), line: v.line, bytes: v.bytes.to_owned(), diff --git a/rust/hg-core/src/config/layer.rs b/rust/hg-core/src/config/layer.rs --- a/rust/hg-core/src/config/layer.rs +++ b/rust/hg-core/src/config/layer.rs @@ -7,6 +7,7 @@ // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. +use crate::errors::{HgError, IoResultExt}; use crate::utils::files::{ get_bytes_from_path, get_path_from_bytes, read_whole_file, }; @@ -99,20 +100,12 @@ impl ConfigLayer { if let Some(m) = INCLUDE_RE.captures(&bytes) { let filename_bytes = &m[1]; let filename_to_include = get_path_from_bytes(&filename_bytes); - match read_include(&src, &filename_to_include) { - (include_src, Ok(data)) => { - layers.push(current_layer); - layers.extend(Self::parse(&include_src, &data)?); - current_layer = - Self::new(ConfigOrigin::File(src.to_owned())); - } - (_, Err(e)) => { - return Err(ConfigError::IncludeError { - path: filename_to_include.to_owned(), - io_error: e, - }) - } - } + let (include_src, result) = + read_include(&src, &filename_to_include); + let data = result.for_file(filename_to_include)?; + layers.push(current_layer); + layers.extend(Self::parse(&include_src, &data)?); + current_layer = Self::new(ConfigOrigin::File(src.to_owned())); } else if let Some(_) = EMPTY_RE.captures(&bytes) { } else if let Some(m) = SECTION_RE.captures(&bytes) { section = m[1].to_vec(); @@ -145,11 +138,12 @@ impl ConfigLayer { map.remove(&m[1]); } } else { - return Err(ConfigError::Parse { + return Err(ConfigParseError { origin: ConfigOrigin::File(src.to_owned()), line: Some(index + 1), bytes: bytes.to_owned(), - }); + } + .into()); } } if !current_layer.is_empty() { @@ -226,21 +220,17 @@ impl ConfigOrigin { } } +#[derive(Debug)] +pub struct ConfigParseError { + pub origin: ConfigOrigin, + pub line: Option, + pub bytes: Vec, +} + #[derive(Debug, derive_more::From)] pub enum ConfigError { - Parse { - origin: ConfigOrigin, - line: Option, - bytes: Vec, - }, - /// Failed to include a sub config file - IncludeError { - path: PathBuf, - io_error: std::io::Error, - }, - /// Any IO error that isn't expected - #[from] - IO(std::io::Error), + Parse(ConfigParseError), + Other(HgError), } fn make_regex(pattern: &'static str) -> Regex {