use std::ffi::OsString; use crate::{Defaults, MagicSignature, SearchMode}; /// pub mod from_environment { /// The error returned by [Defaults::from_environment()](super::Defaults::from_environment()). #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { #[error(transparent)] ParseValue(#[from] gix_config_value::Error), #[error("Glob and no-glob settings are mutually exclusive")] MixedGlobAndNoGlob, } } impl Defaults { /// Initialize this instance using information from the environment as /// [per the official documentation](https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables) *(look for `PATHSPECS`)*, /// calling `var(variable_name)` for each variable that should be obtained. /// /// Used environment variables are `GIT_GLOB_PATHSPECS`, `GIT_NOGLOB_PATHSPECS`, `GIT_LITERAL_PATHSPECS` and `GIT_ICASE_PATHSPECS`. /// Note that there are lot of failure modes, and instead of offering lenient parsing, the caller may ignore errors and /// use other defaults instead. /// /// ### Deviation /// /// Instead of failing if `GIT_LITERAL_PATHSPECS` is used with glob globals, we ignore these. Also our implementation allows global /// `icase` settings in combination with this setting. pub fn from_environment(var: &mut dyn FnMut(&str) -> Option) -> Result { let mut env_bool = |name: &str| -> Result, gix_config_value::Error> { var(name) .map(|val| gix_config_value::Boolean::try_from(val).map(|b| b.0)) .transpose() }; let literal = env_bool("GIT_LITERAL_PATHSPECS")?.unwrap_or_default(); let signature = env_bool("GIT_ICASE_PATHSPECS")? .and_then(|val| val.then_some(MagicSignature::ICASE)) .unwrap_or_default(); if literal { return Ok(Defaults { signature, search_mode: SearchMode::Literal, literal, }); } let glob = env_bool("GIT_GLOB_PATHSPECS")?; let mut search_mode = glob .and_then(|glob| glob.then_some(SearchMode::PathAwareGlob)) .unwrap_or_default(); search_mode = env_bool("GIT_NOGLOB_PATHSPECS")? .map(|no_glob| { if glob.unwrap_or_default() && no_glob { Err(from_environment::Error::MixedGlobAndNoGlob) } else { Ok(SearchMode::Literal) } }) .transpose()? .unwrap_or(search_mode); Ok(Defaults { signature, search_mode, literal, }) } }