pub use gix_config::*;
use gix_features::threading::OnceCell;
use crate::{bstr::BString, repository::identity, Repository};
pub(crate) mod cache;
mod snapshot;
#[cfg(feature = "credentials")]
pub use snapshot::credential_helpers;
pub mod overrides;
pub mod tree;
pub use tree::root::Tree;
pub struct Snapshot<'repo> {
pub repo: &'repo Repository,
}
pub struct SnapshotMut<'repo> {
pub repo: Option<&'repo mut Repository>,
pub(crate) config: gix_config::File<'static>,
}
pub struct CommitAutoRollback<'repo> {
pub repo: Option<&'repo mut Repository>,
pub(crate) prev_config: crate::Config,
}
pub mod section {
pub fn is_trusted(meta: &gix_config::file::Metadata) -> bool {
meta.trust == gix_sec::Trust::Full || meta.source.kind() != gix_config::source::Kind::Repository
}
}
pub mod set_value {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
SetRaw(#[from] gix_config::file::set_raw_value::Error),
#[error(transparent)]
Validate(#[from] crate::config::tree::key::validate::Error),
#[error("The key needs a subsection parameter to be valid.")]
SubSectionRequired,
#[error("The key must not be used with a subsection")]
SubSectionForbidden,
}
}
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
ConfigBoolean(#[from] boolean::Error),
#[error(transparent)]
ConfigUnsigned(#[from] unsigned_integer::Error),
#[error(transparent)]
ConfigTypedString(#[from] key::GenericErrorWithValue),
#[error(transparent)]
RefsNamespace(#[from] refs_namespace::Error),
#[error("Cannot handle objects formatted as {:?}", .name)]
UnsupportedObjectFormat { name: BString },
#[error(transparent)]
CoreAbbrev(#[from] abbrev::Error),
#[error("Could not read configuration file at \"{}\"", path.display())]
Io {
source: std::io::Error,
path: std::path::PathBuf,
},
#[error(transparent)]
Init(#[from] gix_config::file::init::Error),
#[error(transparent)]
ResolveIncludes(#[from] gix_config::file::includes::Error),
#[error(transparent)]
FromEnv(#[from] gix_config::file::init::from_env::Error),
#[error("The path {path:?} at the 'core.worktree' configuration could not be interpolated")]
PathInterpolation {
path: BString,
source: gix_config::path::interpolate::Error,
},
#[error("{source:?} configuration overrides at open or init time could not be applied.")]
ConfigOverrides {
#[source]
err: overrides::Error,
source: gix_config::Source,
},
}
pub mod merge {
pub mod pipeline_options {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
BigFileThreshold(#[from] crate::config::unsigned_integer::Error),
}
}
pub mod drivers {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
ConfigBoolean(#[from] crate::config::boolean::Error),
}
}
}
pub mod diff {
pub mod algorithm {
use crate::bstr::BString;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("Unknown diff algorithm named '{name}'")]
Unknown { name: BString },
#[error("The '{name}' algorithm is not yet implemented")]
Unimplemented { name: BString },
}
}
pub mod pipeline_options {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
FilesystemCapabilities(#[from] crate::config::boolean::Error),
#[error(transparent)]
BigFileThreshold(#[from] crate::config::unsigned_integer::Error),
}
}
pub mod drivers {
use crate::bstr::BString;
#[derive(Debug, thiserror::Error)]
#[error("Failed to parse value of 'diff.{name}.{attribute}'")]
pub struct Error {
pub name: BString,
pub attribute: &'static str,
pub source: Box<dyn std::error::Error + Send + Sync + 'static>,
}
}
}
pub mod stat_options {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
ConfigCheckStat(#[from] super::key::GenericErrorWithValue),
#[error(transparent)]
ConfigBoolean(#[from] super::boolean::Error),
}
}
#[cfg(feature = "attributes")]
pub mod checkout_options {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
ConfigCheckStat(#[from] super::key::GenericErrorWithValue),
#[error(transparent)]
ConfigBoolean(#[from] super::boolean::Error),
#[error(transparent)]
CheckoutWorkers(#[from] super::checkout::workers::Error),
#[error(transparent)]
Attributes(#[from] super::attribute_stack::Error),
#[error(transparent)]
FilterPipelineOptions(#[from] crate::filter::pipeline::options::Error),
#[error(transparent)]
CommandContext(#[from] crate::config::command_context::Error),
}
}
#[cfg(feature = "attributes")]
pub mod command_context {
use crate::config;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Boolean(#[from] config::boolean::Error),
#[error(transparent)]
ParseBool(#[from] gix_config::value::Error),
}
}
pub mod exclude_stack {
use crate::config;
use std::path::PathBuf;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("Could not read repository exclude")]
Io(#[from] std::io::Error),
#[error(transparent)]
EnvironmentPermission(#[from] gix_sec::permission::Error<PathBuf>),
#[error("The value for `core.excludesFile` could not be read from configuration")]
ExcludesFilePathInterpolation(#[from] gix_config::path::interpolate::Error),
#[error(transparent)]
ParsePreciousEnabled(#[from] config::boolean::Error),
}
}
pub mod attribute_stack {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("An attribute file could not be read")]
Io(#[from] std::io::Error),
#[error("Failed to interpolate the attribute file configured at `core.attributesFile`")]
AttributesFileInterpolation(#[from] gix_config::path::interpolate::Error),
}
}
pub mod protocol {
pub mod allow {
use crate::bstr::BString;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
#[error("The value {value:?} must be allow|deny|user in configuration key protocol{0}.allow", scheme.as_ref().map(|s| format!(".{s}")).unwrap_or_default())]
pub struct Error {
pub scheme: Option<String>,
pub value: BString,
}
}
}
pub mod ssh_connect_options {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
#[error(transparent)]
pub struct Error(#[from] super::key::GenericErrorWithValue);
}
pub mod key {
use crate::bstr::BString;
const fn prefix(kind: char) -> &'static str {
match kind {
'n' => "", 'k' => "The value of key", 't' => "The date format at key", 'i' => "The timeout at key", 'd' => "The duration [ms] at key", 'b' => "The boolean at key", 'v' => "The key", 'r' => "The refspec at", 's' => "The ssl version at", 'u' => "The url at", 'w' => "The utf-8 string at", _ => panic!("BUG: invalid prefix kind - add a case for it here"),
}
}
const fn suffix(kind: char) -> &'static str {
match kind {
'd' => "could not be decoded", 'i' => "was invalid", 'u' => "could not be parsed as unsigned integer", 'p' => "could not be parsed", _ => panic!("BUG: invalid suffix kind - add a case for it here"),
}
}
#[derive(Debug, thiserror::Error)]
#[error("{} \"{key}{}\"{} {}", prefix(PREFIX), value.as_ref().map(|v| format!("={v}")).unwrap_or_default(), environment_override.as_deref().map(|var| format!(" (possibly from {var})")).unwrap_or_default(), suffix(SUFFIX))]
pub struct Error<E: std::error::Error + Send + Sync + 'static, const PREFIX: char, const SUFFIX: char> {
pub key: BString,
pub value: Option<BString>,
pub environment_override: Option<&'static str>,
pub source: Option<E>,
}
impl<T, E, const PREFIX: char, const SUFFIX: char> From<&'static T> for Error<E, PREFIX, SUFFIX>
where
E: std::error::Error + Send + Sync + 'static,
T: super::tree::Key,
{
fn from(key: &'static T) -> Self {
Error {
key: key.logical_name().into(),
value: None,
environment_override: key.environment_override(),
source: None,
}
}
}
impl<E, const PREFIX: char, const SUFFIX: char> Error<E, PREFIX, SUFFIX>
where
E: std::error::Error + Send + Sync + 'static,
{
pub fn from_value(key: &'static impl super::tree::Key, value: BString) -> Self {
Error::from(key).with_value(value)
}
}
impl<E, const PREFIX: char, const SUFFIX: char> Error<E, PREFIX, SUFFIX>
where
E: std::error::Error + Send + Sync + 'static,
{
pub fn with_source(mut self, err: E) -> Self {
self.source = Some(err);
self
}
pub fn with_value(mut self, value: BString) -> Self {
self.value = Some(value);
self
}
}
pub type GenericError<E = gix_config::value::Error> = Error<E, 'k', 'i'>;
pub type GenericErrorWithValue<E = gix_config::value::Error> = Error<E, 'v', 'i'>;
}
pub mod encoding {
use crate::bstr::BString;
#[derive(Debug, thiserror::Error)]
#[error("The encoding named '{encoding}' seen in key '{key}={value}' is unsupported")]
pub struct Error {
pub key: BString,
pub value: BString,
pub encoding: BString,
}
}
pub mod checkout {
pub mod workers {
use crate::config;
pub type Error = config::key::Error<gix_config::value::Error, 'n', 'd'>;
}
}
pub mod abbrev {
use crate::bstr::BString;
#[derive(Debug, thiserror::Error)]
#[error("Invalid value for 'core.abbrev' = '{}'. It must be between 4 and {}", .value, .max)]
pub struct Error {
pub value: BString,
pub max: u8,
}
}
pub mod remote {
pub mod symbolic_name {
pub type Error = super::super::key::Error<crate::remote::name::Error, 'v', 'i'>;
}
}
pub mod time {
pub type Error = super::key::Error<gix_date::Error, 't', 'i'>;
}
pub mod lock_timeout {
pub type Error = super::key::Error<gix_config::value::Error, 'i', 'i'>;
}
pub mod duration {
pub type Error = super::key::Error<gix_config::value::Error, 'd', 'i'>;
}
pub mod boolean {
pub type Error = super::key::Error<gix_config::value::Error, 'b', 'i'>;
}
pub mod unsigned_integer {
pub type Error = super::key::Error<gix_config::value::Error, 'k', 'u'>;
}
pub mod url {
pub type Error = super::key::Error<gix_url::parse::Error, 'u', 'p'>;
}
pub mod string {
pub type Error = super::key::Error<crate::bstr::Utf8Error, 'w', 'd'>;
}
pub mod refspec {
pub type Error = super::key::Error<gix_refspec::parse::Error, 'r', 'p'>;
}
pub mod refs_namespace {
pub type Error = super::key::Error<gix_validate::reference::name::Error, 'v', 'i'>;
}
pub mod ssl_version {
pub type Error = super::key::Error<std::convert::Infallible, 's', 'i'>;
}
pub mod transport {
use std::borrow::Cow;
use crate::bstr::BStr;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(
"Could not interpret configuration key {key:?} as {kind} integer of desired range with value: {actual}"
)]
InvalidInteger {
key: &'static str,
kind: &'static str,
actual: i64,
},
#[error("Could not interpret configuration key {key:?}")]
ConfigValue {
source: gix_config::value::Error,
key: &'static str,
},
#[error("Could not interpolate path at key {key:?}")]
InterpolatePath {
source: gix_config::path::interpolate::Error,
key: &'static str,
},
#[error("Could not decode value at key {key:?} as UTF-8 string")]
IllformedUtf8 {
key: Cow<'static, BStr>,
source: crate::config::string::Error,
},
#[error("Invalid URL passed for configuration")]
ParseUrl(#[from] gix_url::parse::Error),
#[error("Could obtain configuration for an HTTP url")]
Http(#[from] http::Error),
}
pub mod http {
use std::borrow::Cow;
use crate::bstr::BStr;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Boolean(#[from] crate::config::boolean::Error),
#[error(transparent)]
UnsignedInteger(#[from] crate::config::unsigned_integer::Error),
#[error(transparent)]
ConnectTimeout(#[from] crate::config::duration::Error),
#[error("The proxy authentication at key `{key}` is invalid")]
InvalidProxyAuthMethod {
source: crate::config::key::GenericErrorWithValue,
key: Cow<'static, BStr>,
},
#[error("Could not configure the credential helpers for the authenticated proxy url")]
#[cfg(feature = "credentials")]
ConfigureProxyAuthenticate(#[from] crate::config::snapshot::credential_helpers::Error),
#[error(transparent)]
InvalidSslVersion(#[from] crate::config::ssl_version::Error),
#[error("The HTTP version must be 'HTTP/2' or 'HTTP/1.1'")]
InvalidHttpVersion(#[from] crate::config::key::GenericErrorWithValue),
#[error("The follow redirects value 'initial', or boolean true or false")]
InvalidFollowRedirects(#[source] crate::config::key::GenericErrorWithValue),
}
}
}
#[derive(Clone)]
pub(crate) struct Cache {
pub resolved: crate::Config,
pub hex_len: Option<usize>,
pub is_bare: Option<bool>,
pub object_hash: gix_hash::Kind,
pub use_multi_pack_index: bool,
pub reflog: Option<gix_ref::store::WriteReflog>,
pub refs_namespace: Option<gix_ref::Namespace>,
pub(crate) user_agent: OnceCell<String>,
pub(crate) personas: OnceCell<identity::Personas>,
pub(crate) url_rewrite: OnceCell<crate::remote::url::Rewrite>,
#[cfg(feature = "blob-diff")]
pub(crate) diff_renames: OnceCell<(Option<crate::diff::Rewrites>, bool)>,
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
pub(crate) url_scheme: OnceCell<crate::remote::url::SchemePermission>,
#[cfg(feature = "blob-diff")]
pub(crate) diff_algorithm: OnceCell<gix_diff::blob::Algorithm>,
pub(crate) pack_cache_bytes: Option<usize>,
pub(crate) object_cache_bytes: usize,
pub(crate) static_pack_cache_limit_bytes: Option<usize>,
filter_config_section: fn(&gix_config::file::Metadata) -> bool,
#[cfg(feature = "revision")]
pub object_kind_hint: Option<crate::revision::spec::parse::ObjectKindHint>,
pub ignore_case: bool,
pub lenient_config: bool,
#[cfg_attr(not(feature = "worktree-mutation"), allow(dead_code))]
attributes: crate::open::permissions::Attributes,
environment: crate::open::permissions::Environment,
}
pub(crate) mod shared {
use crate::{
config,
config::{cache::util::ApplyLeniency, tree::Core},
};
pub fn is_replace_refs_enabled(
config: &gix_config::File<'static>,
lenient: bool,
mut filter_config_section: fn(&gix_config::file::Metadata) -> bool,
) -> Result<Option<bool>, config::boolean::Error> {
config
.boolean_filter("core.useReplaceRefs", &mut filter_config_section)
.map(|b| Core::USE_REPLACE_REFS.enrich_error(b))
.transpose()
.with_leniency(lenient)
}
}