#![allow(clippy::result_large_err)] use super::Error; use crate::{ config, config::tree::{Core, gitoxide}, }; pub(crate) fn interpolate_context<'a>( git_install_dir: Option<&'a std::path::Path>, home_dir: Option<&'a std::path::Path>, ) -> gix_config::path::interpolate::Context<'a> { gix_config::path::interpolate::Context { git_install_dir, home_dir, home_for_user: Some(gix_config::path::interpolate::home_for_user), // TODO: figure out how to configure this } } pub(crate) fn base_options(lossy: bool, lenient: bool) -> gix_config::file::init::Options<'static> { gix_config::file::init::Options { lossy, ignore_io_errors: lenient, ..Default::default() } } /// Also sets the default if it's not set! pub(crate) fn config_bool( config: &gix_config::File, key: &'static config::tree::keys::Boolean, key_str: &str, default: bool, lenient: bool, ) -> Result { use config::tree::Key; debug_assert_eq!( key_str, key.logical_name(), "BUG: key name and hardcoded name must match" ); Ok(key .enrich_error(config.boolean(key_str)) .map_err(Error::from) .with_lenient_default(lenient)? .unwrap_or(default)) } pub(crate) fn config_bool_opt( config: &gix_config::File, key: &'static config::tree::keys::Boolean, key_str: &str, lenient: bool, ) -> Result, Error> { use config::tree::Key; debug_assert_eq!( key_str, key.logical_name(), "BUG: key name and hardcoded name must match" ); key.enrich_error(config.boolean(key_str)) .map_err(Error::from) .with_leniency(lenient) } pub(crate) fn query_refupdates( config: &gix_config::File, lenient_config: bool, ) -> Result, Error> { let key = "core.logAllRefUpdates"; Core::LOG_ALL_REF_UPDATES .try_into_ref_updates(config.boolean(key)) .with_leniency(lenient_config) .map_err(Into::into) } pub(crate) fn query_refs_namespace( config: &gix_config::File, lenient_config: bool, ) -> Result, config::refs_namespace::Error> { let key = "gitoxide.core.refsNamespace"; config .string(key) .map(|ns| gitoxide::Core::REFS_NAMESPACE.try_into_refs_namespace(ns)) .transpose() .with_leniency(lenient_config) } pub(crate) fn reflog_or_default( config_reflog: Option, has_worktree: bool, ) -> gix_ref::store::WriteReflog { config_reflog.unwrap_or(if has_worktree { gix_ref::store::WriteReflog::Normal } else { gix_ref::store::WriteReflog::Disable }) } pub(crate) type ObjectCaches = (Option, Option, usize, Option); /// Return `(static_pack_cache_limit, pack_cache_bytes, object_cache_bytes, alloc_limit_bytes)` as parsed from gix-config. pub(crate) fn parse_object_caches( config: &gix_config::File, lenient: bool, mut filter_config_section: fn(&gix_config::file::Metadata) -> bool, ) -> Result { let static_pack_cache_limit = gitoxide::Core::DEFAULT_PACK_CACHE_MEMORY_LIMIT .try_into_usize(config.integer_filter("gitoxide.core.deltaBaseCacheLimit", &mut filter_config_section)) .with_leniency(lenient)?; let pack_cache_bytes = Core::DELTA_BASE_CACHE_LIMIT .try_into_usize(config.integer_filter("core.deltaBaseCacheLimit", &mut filter_config_section)) .with_leniency(lenient)?; let object_cache_bytes = gitoxide::Objects::CACHE_LIMIT .try_into_usize(config.integer_filter("gitoxide.objects.cacheLimit", &mut filter_config_section)) .with_leniency(lenient)? .unwrap_or_default(); let alloc_limit_bytes = gitoxide::Objects::ALLOC_LIMIT .try_into_usize(config.integer_filter("gitoxide.objects.allocLimit", &mut filter_config_section)) .with_leniency(lenient)?; Ok(( static_pack_cache_limit, pack_cache_bytes, object_cache_bytes, alloc_limit_bytes, )) } pub(crate) fn parse_core_abbrev( config: &gix_config::File, object_hash: gix_hash::Kind, ) -> Result, Error> { Ok(config .string("core.abbrev") .map(|abbrev| Core::ABBREV.try_into_abbreviation(abbrev, object_hash)) .transpose()? .flatten()) } #[cfg(feature = "revision")] pub(crate) fn disambiguate_hint( config: &gix_config::File, lenient_config: bool, ) -> Result, config::key::GenericErrorWithValue> { match config.string("core.disambiguate") { None => Ok(None), Some(value) => Core::DISAMBIGUATE .try_into_object_kind_hint(value) .with_leniency(lenient_config), } } // TODO: Use a specialization here once trait specialization is stabilized. Would be perfect here for `T: Default`. pub trait ApplyLeniency { fn with_leniency(self, is_lenient: bool) -> Self; } pub trait ApplyLeniencyDefault { fn with_lenient_default(self, is_lenient: bool) -> Self; } pub trait ApplyLeniencyDefaultValue { fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self; } impl ApplyLeniency for Result, E> { fn with_leniency(self, is_lenient: bool) -> Self { match self { Ok(v) => Ok(v), Err(_) if is_lenient => Ok(None), Err(err) => Err(err), } } } impl ApplyLeniencyDefault for Result where T: Default, { fn with_lenient_default(self, is_lenient: bool) -> Self { match self { Ok(v) => Ok(v), Err(_) if is_lenient => Ok(T::default()), Err(err) => Err(err), } } } impl ApplyLeniencyDefaultValue for Result { fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self { match self { Ok(v) => Ok(v), Err(_) if is_lenient => Ok(default), Err(err) => Err(err), } } }