diff options
Diffstat (limited to 'vendor/gix/src/config/mod.rs')
-rw-r--r-- | vendor/gix/src/config/mod.rs | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/vendor/gix/src/config/mod.rs b/vendor/gix/src/config/mod.rs new file mode 100644 index 000000000..1e2566777 --- /dev/null +++ b/vendor/gix/src/config/mod.rs @@ -0,0 +1,454 @@ +pub use gix_config::*; +use gix_features::threading::OnceCell; + +use crate::{bstr::BString, repository::identity, revision::spec, Repository}; + +pub(crate) mod cache; +mod snapshot; +pub use snapshot::credential_helpers; + +/// +pub mod overrides; + +pub mod tree; +pub use tree::root::Tree; + +/// A platform to access configuration values as read from disk. +/// +/// Note that these values won't update even if the underlying file(s) change. +pub struct Snapshot<'repo> { + pub(crate) repo: &'repo Repository, +} + +/// A platform to access configuration values and modify them in memory, while making them available when this platform is dropped +/// as form of auto-commit. +/// Note that the values will only affect this instance of the parent repository, and not other clones that may exist. +/// +/// Note that these values won't update even if the underlying file(s) change. +/// +/// Use [`forget()`][Self::forget()] to not apply any of the changes. +// TODO: make it possible to load snapshots with reloading via .config() and write mutated snapshots back to disk which should be the way +// to affect all instances of a repo, probably via `config_mut()` and `config_mut_at()`. +pub struct SnapshotMut<'repo> { + pub(crate) repo: Option<&'repo mut Repository>, + pub(crate) config: gix_config::File<'static>, +} + +/// A utility structure created by [`SnapshotMut::commit_auto_rollback()`] that restores the previous configuration on drop. +pub struct CommitAutoRollback<'repo> { + pub(crate) repo: Option<&'repo mut Repository>, + pub(crate) prev_config: crate::Config, +} + +pub(crate) 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 + } +} + +/// The error returned when failing to initialize the repository configuration. +/// +/// This configuration is on the critical path when opening a repository. +#[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("Cannot handle objects formatted as {:?}", .name)] + UnsupportedObjectFormat { name: BString }, + #[error(transparent)] + CoreAbbrev(#[from] abbrev::Error), + #[error("Could not read configuration file")] + Io(#[from] std::io::Error), + #[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(transparent)] + PathInterpolation(#[from] 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 diff { + /// + pub mod algorithm { + use crate::bstr::BString; + + /// The error produced when obtaining `diff.algorithm`. + #[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 checkout_options { + /// The error produced when collecting all information needed for checking out files into a worktree. + #[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("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; + + /// The error returned when obtaining the permission for a particular scheme. + #[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 { + /// The error produced when obtaining ssh connection configuration. + #[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' => "", // nothing + 'k' => "The value of key", // generic key + 't' => "The date format at key", // time + 'i' => "The timeout at key", // timeout + 'd' => "The duration [ms] at key", // duration + 'b' => "The boolean at key", // boolean + 'v' => "The key", // generic key with value + 'r' => "The refspec at", // refspec + 's' => "The ssl version at", // ssl-version + 'u' => "The url at", // url + 'w' => "The utf-8 string at", // string + _ => 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", // decoding + 'i' => "was invalid", // invalid + 'u' => "could not be parsed as unsigned integer", // unsigned integer + 'p' => "could not be parsed", // parsing + _ => panic!("BUG: invalid suffix kind - add a case for it here"), + } + } + /// A generic error suitable to produce decent messages for all kinds of configuration errors with config-key granularity. + /// + /// This error is meant to be reusable and help produce uniform error messages related to parsing any configuration key. + #[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> { + /// The configuration key that contained the value. + pub key: BString, + /// The value that was assigned to `key`. + pub value: Option<BString>, + /// The associated environment variable that would override this value. + pub environment_override: Option<&'static str>, + /// The source of the error if there was one. + pub source: Option<E>, + } + + /// Initialization + /// Instantiate a new error from the given `key`. + /// + /// Note that specifics of the error message are defined by the `PREFIX` and `SUFFIX` which is usually defined by a typedef. + 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, + } + } + } + + /// Initialization + impl<E, const PREFIX: char, const SUFFIX: char> Error<E, PREFIX, SUFFIX> + where + E: std::error::Error + Send + Sync + 'static, + { + /// Instantiate an error with all data from `key` along with the `value` of the key. + pub fn from_value(key: &'static impl super::tree::Key, value: BString) -> Self { + Error::from(key).with_value(value) + } + } + + /// Builder + impl<E, const PREFIX: char, const SUFFIX: char> Error<E, PREFIX, SUFFIX> + where + E: std::error::Error + Send + Sync + 'static, + { + /// Attach the given `err` as source. + pub fn with_source(mut self, err: E) -> Self { + self.source = Some(err); + self + } + + /// Attach the given `value` as value we observed when the error was produced. + pub fn with_value(mut self, value: BString) -> Self { + self.value = Some(value); + self + } + } + + /// A generic key error for use when it doesn't seem worth it say more than 'key is invalid' along with meta-data. + pub type GenericError<E = gix_config::value::Error> = Error<E, 'k', 'i'>; + + /// A generic key error which will also contain a value. + pub type GenericErrorWithValue<E = gix_config::value::Error> = Error<E, 'v', 'i'>; +} + +/// +pub mod checkout { + /// + pub mod workers { + use crate::config; + + /// The error produced when failing to parse the the `checkout.workers` key. + pub type Error = config::key::Error<gix_config::value::Error, 'n', 'd'>; + } +} + +/// +pub mod abbrev { + use crate::bstr::BString; + + /// The error describing an incorrect `core.abbrev` value. + #[derive(Debug, thiserror::Error)] + #[error("Invalid value for 'core.abbrev' = '{}'. It must be between 4 and {}", .value, .max)] + pub struct Error { + /// The value found in the git configuration + pub value: BString, + /// The maximum abbreviation length, the length of an object hash. + pub max: u8, + } +} + +/// +pub mod remote { + /// + pub mod symbolic_name { + /// The error produced when failing to produce a symbolic remote name from configuration. + pub type Error = super::super::key::Error<crate::remote::name::Error, 'v', 'i'>; + } +} + +/// +pub mod time { + /// The error produced when failing to parse time from configuration. + pub type Error = super::key::Error<gix_date::parse::Error, 't', 'i'>; +} + +/// +pub mod lock_timeout { + /// The error produced when failing to parse timeout for locks. + pub type Error = super::key::Error<gix_config::value::Error, 'i', 'i'>; +} + +/// +pub mod duration { + /// The error produced when failing to parse durations (in milliseconds). + pub type Error = super::key::Error<gix_config::value::Error, 'd', 'i'>; +} + +/// +pub mod boolean { + /// The error produced when failing to parse time from configuration. + pub type Error = super::key::Error<gix_config::value::Error, 'b', 'i'>; +} + +/// +pub mod unsigned_integer { + /// The error produced when failing to parse a signed integer from configuration. + pub type Error = super::key::Error<gix_config::value::Error, 'k', 'u'>; +} + +/// +pub mod url { + /// The error produced when failing to parse a url from the configuration. + pub type Error = super::key::Error<gix_url::parse::Error, 'u', 'p'>; +} + +/// +pub mod string { + /// The error produced when failing to interpret configuration as UTF-8 encoded string. + pub type Error = super::key::Error<crate::bstr::Utf8Error, 'w', 'd'>; +} + +/// +pub mod refspec { + /// The error produced when failing to parse a refspec from the configuration. + pub type Error = super::key::Error<gix_refspec::parse::Error, 'r', 'p'>; +} + +/// +pub mod ssl_version { + /// The error produced when failing to parse a refspec from the configuration. + pub type Error = super::key::Error<std::convert::Infallible, 's', 'i'>; +} + +/// +pub mod transport { + use std::borrow::Cow; + + use crate::bstr::BStr; + + /// The error produced when configuring a transport for a particular protocol. + #[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; + + /// The error produced when configuring a HTTP transport. + #[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")] + 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), + } + } +} + +/// Utility type to keep pre-obtained configuration values, only for those required during initial setup +/// and other basic operations that are common enough to warrant a permanent cache. +/// +/// All other values are obtained lazily using OnceCell. +#[derive(Clone)] +pub(crate) struct Cache { + pub resolved: crate::Config, + /// The hex-length to assume when shortening object ids. If `None`, it should be computed based on the approximate object count. + pub hex_len: Option<usize>, + /// true if the repository is designated as 'bare', without work tree. + pub is_bare: bool, + /// The type of hash to use. + pub object_hash: gix_hash::Kind, + /// If true, multi-pack indices, whether present or not, may be used by the object database. + pub use_multi_pack_index: bool, + /// The representation of `core.logallrefupdates`, or `None` if the variable wasn't set. + pub reflog: Option<gix_ref::store::WriteReflog>, + /// The configured user agent for presentation to servers. + pub(crate) user_agent: OnceCell<String>, + /// identities for later use, lazy initialization. + pub(crate) personas: OnceCell<identity::Personas>, + /// A lazily loaded rewrite list for remote urls + pub(crate) url_rewrite: OnceCell<crate::remote::url::Rewrite>, + /// The lazy-loaded rename information for diffs. + pub(crate) diff_renames: OnceCell<Option<crate::object::tree::diff::Rewrites>>, + /// A lazily loaded mapping to know which url schemes to allow + #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))] + pub(crate) url_scheme: OnceCell<crate::remote::url::SchemePermission>, + /// The algorithm to use when diffing blobs + pub(crate) diff_algorithm: OnceCell<gix_diff::blob::Algorithm>, + /// The amount of bytes to use for a memory backed delta pack cache. If `Some(0)`, no cache is used, if `None` + /// a standard cache is used which costs near to nothing and always pays for itself. + pub(crate) pack_cache_bytes: Option<usize>, + /// The amount of bytes to use for caching whole objects, or 0 to turn it off entirely. + pub(crate) object_cache_bytes: usize, + /// The config section filter from the options used to initialize this instance. Keep these in sync! + filter_config_section: fn(&gix_config::file::Metadata) -> bool, + /// The object kind to pick if a prefix is ambiguous. + pub object_kind_hint: Option<spec::parse::ObjectKindHint>, + /// If true, we are on a case-insensitive file system. + pub ignore_case: bool, + /// If true, we should default what's possible if something is misconfigured, on case by case basis, to be more resilient. + /// Also available in options! Keep in sync! + pub lenient_config: bool, + /// Define how we can use values obtained with `xdg_config(…)` and its `XDG_CONFIG_HOME` variable. + xdg_config_home_env: gix_sec::Permission, + /// Define how we can use values obtained with `xdg_config(…)`. and its `HOME` variable. + home_env: gix_sec::Permission, + // TODO: make core.precomposeUnicode available as well. +} |