#![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<bool, Error> { 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<Option<bool>, 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<Option<gix_ref::store::WriteReflog>, 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<Option<gix_ref::Namespace>, 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<gix_ref::store::WriteReflog>, 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<usize>, Option<usize>, usize, Option<usize>); /// 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<ObjectCaches, Error> { 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<Option<usize>, 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<Option<crate::revision::spec::parse::ObjectKindHint>, 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<T> { fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self;} impl<T, E> ApplyLeniency for Result<Option<T>, 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<T, E> ApplyLeniencyDefault for Result<T, E>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<T, E> ApplyLeniencyDefaultValue<T> for Result<T, E> { 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), } }}
#![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<bool, Error> {
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<Option<bool>, 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<Option<gix_ref::store::WriteReflog>, 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<Option<gix_ref::Namespace>, 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<gix_ref::store::WriteReflog>,
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<usize>, Option<usize>, usize, Option<usize>);
/// 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<ObjectCaches, Error> {
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<Option<usize>, 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<Option<crate::revision::spec::parse::ObjectKindHint>, 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<T> {
fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self;
}
impl<T, E> ApplyLeniency for Result<Option<T>, 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<T, E> ApplyLeniencyDefault for Result<T, E>
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<T, E> ApplyLeniencyDefaultValue<T> for Result<T, E> {
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),
}
}
}