diff options
Diffstat (limited to 'vendor/gix/src/config/tree/sections')
20 files changed, 1924 insertions, 0 deletions
diff --git a/vendor/gix/src/config/tree/sections/author.rs b/vendor/gix/src/config/tree/sections/author.rs new file mode 100644 index 000000000..4101e3817 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/author.rs @@ -0,0 +1,23 @@ +use crate::{ + config, + config::tree::{gitoxide, keys, Author, Key, Section}, +}; + +impl Author { + /// The `author.name` key. + pub const NAME: keys::Any = + keys::Any::new("name", &config::Tree::AUTHOR).with_fallback(&gitoxide::Author::NAME_FALLBACK); + /// The `author.email` key. + pub const EMAIL: keys::Any = + keys::Any::new("email", &config::Tree::AUTHOR).with_fallback(&gitoxide::Author::EMAIL_FALLBACK); +} + +impl Section for Author { + fn name(&self) -> &str { + "author" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::NAME, &Self::EMAIL] + } +} diff --git a/vendor/gix/src/config/tree/sections/branch.rs b/vendor/gix/src/config/tree/sections/branch.rs new file mode 100644 index 000000000..8e1e0a4b8 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/branch.rs @@ -0,0 +1,65 @@ +use crate::config::tree::{keys, traits::SubSectionRequirement, Branch, Key, Section}; + +const NAME_PARAMETER: Option<SubSectionRequirement> = Some(SubSectionRequirement::Parameter("name")); + +impl Branch { + /// The `branch.<name>.merge` key. + pub const MERGE: Merge = Merge::new_with_validate("merge", &crate::config::Tree::BRANCH, validate::FullNameRef) + .with_subsection_requirement(NAME_PARAMETER); + /// The `branch.<name>.pushRemote` key. + pub const PUSH_REMOTE: keys::RemoteName = + keys::RemoteName::new_remote_name("pushRemote", &crate::config::Tree::BRANCH) + .with_subsection_requirement(NAME_PARAMETER); + /// The `branch.<name>.remote` key. + pub const REMOTE: keys::RemoteName = keys::RemoteName::new_remote_name("remote", &crate::config::Tree::BRANCH) + .with_subsection_requirement(NAME_PARAMETER); +} + +impl Section for Branch { + fn name(&self) -> &str { + "branch" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::MERGE, &Self::PUSH_REMOTE, &Self::REMOTE] + } +} + +/// The `branch.<name>.merge` key. +pub type Merge = keys::Any<validate::FullNameRef>; + +mod merge { + use std::borrow::Cow; + + use gix_ref::FullNameRef; + + use crate::{bstr::BStr, config::tree::branch::Merge}; + + impl Merge { + /// Return the validated full ref name from `value` if it is valid. + pub fn try_into_fullrefname( + value: Cow<'_, BStr>, + ) -> Result<Cow<'_, FullNameRef>, gix_validate::reference::name::Error> { + match value { + Cow::Borrowed(v) => v.try_into().map(Cow::Borrowed), + Cow::Owned(v) => v.try_into().map(Cow::Owned), + } + } + } +} + +/// +pub mod validate { + use crate::{ + bstr::BStr, + config::tree::{branch::Merge, keys}, + }; + + pub struct FullNameRef; + impl keys::Validate for FullNameRef { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + Merge::try_into_fullrefname(value.into())?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/checkout.rs b/vendor/gix/src/config/tree/sections/checkout.rs new file mode 100644 index 000000000..27f31ee84 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/checkout.rs @@ -0,0 +1,58 @@ +use crate::{ + config, + config::tree::{keys, Checkout, Key, Section}, +}; + +impl Checkout { + /// The `checkout.workers` key. + pub const WORKERS: Workers = Workers::new_with_validate("workers", &config::Tree::CHECKOUT, validate::Workers) + .with_deviation("if unset, uses all cores instead of just one"); +} + +/// The `checkout.workers` key. +pub type Workers = keys::Any<validate::Workers>; + +impl Section for Checkout { + fn name(&self) -> &str { + "checkout" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::WORKERS] + } +} + +mod workers { + use crate::config::tree::checkout::Workers; + + impl Workers { + /// Return the amount of threads to use for checkout, with `0` meaning all available ones, after decoding our integer value from `config`, + /// or `None` if the value isn't set which is typically interpreted as "as many threads as available" + pub fn try_from_workers( + &'static self, + value: Result<i64, gix_config::value::Error>, + ) -> Result<usize, crate::config::checkout::workers::Error> { + match value { + Ok(v) if v < 0 => Ok(0), + Ok(v) => Ok(v.try_into().expect("positive i64 can always be usize on 64 bit")), + Err(err) => Err(crate::config::key::Error::from(&super::Checkout::WORKERS).with_source(err)), + } + } + } +} + +/// +pub mod validate { + use crate::{bstr::BStr, config::tree::keys}; + + pub struct Workers; + impl keys::Validate for Workers { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + super::Checkout::WORKERS.try_from_workers(gix_config::Integer::try_from(value).and_then(|i| { + i.to_decimal() + .ok_or_else(|| gix_config::value::Error::new("Integer overflow", value.to_owned())) + }))?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/clone.rs b/vendor/gix/src/config/tree/sections/clone.rs new file mode 100644 index 000000000..616185a0b --- /dev/null +++ b/vendor/gix/src/config/tree/sections/clone.rs @@ -0,0 +1,20 @@ +use crate::{ + config, + config::tree::{keys, Clone, Key, Section}, +}; + +impl Clone { + /// The `clone.defaultRemoteName` key. + pub const DEFAULT_REMOTE_NAME: keys::RemoteName = + keys::RemoteName::new_remote_name("defaultRemoteName", &config::Tree::CLONE); +} + +impl Section for Clone { + fn name(&self) -> &str { + "clone" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::DEFAULT_REMOTE_NAME] + } +} diff --git a/vendor/gix/src/config/tree/sections/committer.rs b/vendor/gix/src/config/tree/sections/committer.rs new file mode 100644 index 000000000..acc25c930 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/committer.rs @@ -0,0 +1,23 @@ +use crate::{ + config, + config::tree::{gitoxide, keys, Committer, Key, Section}, +}; + +impl Committer { + /// The `committer.name` key. + pub const NAME: keys::Any = + keys::Any::new("name", &config::Tree::COMMITTER).with_fallback(&gitoxide::Committer::NAME_FALLBACK); + /// The `committer.email` key. + pub const EMAIL: keys::Any = + keys::Any::new("email", &config::Tree::COMMITTER).with_fallback(&gitoxide::Committer::EMAIL_FALLBACK); +} + +impl Section for Committer { + fn name(&self) -> &str { + "committer" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::NAME, &Self::EMAIL] + } +} diff --git a/vendor/gix/src/config/tree/sections/core.rs b/vendor/gix/src/config/tree/sections/core.rs new file mode 100644 index 000000000..6ea0580e1 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/core.rs @@ -0,0 +1,302 @@ +use crate::{ + config, + config::tree::{keys, Core, Key, Section}, +}; + +impl Core { + /// The `core.abbrev` key. + pub const ABBREV: Abbrev = Abbrev::new_with_validate("abbrev", &config::Tree::CORE, validate::Abbrev); + /// The `core.bare` key. + pub const BARE: keys::Boolean = keys::Boolean::new_boolean("bare", &config::Tree::CORE); + /// The `core.checkStat` key. + pub const CHECK_STAT: CheckStat = + CheckStat::new_with_validate("checkStat", &config::Tree::CORE, validate::CheckStat); + /// The `core.deltaBaseCacheLimit` key. + pub const DELTA_BASE_CACHE_LIMIT: keys::UnsignedInteger = + keys::UnsignedInteger::new_unsigned_integer("deltaBaseCacheLimit", &config::Tree::CORE) + .with_environment_override("GITOXIDE_PACK_CACHE_MEMORY") + .with_note("if unset, we default to a small 64 slot fixed-size cache that holds at most 64 full delta base objects of any size. Set to 0 to deactivate it entirely"); + /// The `core.disambiguate` key. + pub const DISAMBIGUATE: Disambiguate = + Disambiguate::new_with_validate("disambiguate", &config::Tree::CORE, validate::Disambiguate); + /// The `core.fileMode` key. + pub const FILE_MODE: keys::Boolean = keys::Boolean::new_boolean("fileMode", &config::Tree::CORE); + /// The `core.ignoreCase` key. + pub const IGNORE_CASE: keys::Boolean = keys::Boolean::new_boolean("ignoreCase", &config::Tree::CORE); + /// The `core.filesRefLockTimeout` key. + pub const FILES_REF_LOCK_TIMEOUT: keys::LockTimeout = + keys::LockTimeout::new_lock_timeout("filesRefLockTimeout", &config::Tree::CORE); + /// The `core.packedRefsTimeout` key. + pub const PACKED_REFS_TIMEOUT: keys::LockTimeout = + keys::LockTimeout::new_lock_timeout("packedRefsTimeout", &config::Tree::CORE); + /// The `core.multiPackIndex` key. + pub const MULTIPACK_INDEX: keys::Boolean = keys::Boolean::new_boolean("multiPackIndex", &config::Tree::CORE); + /// The `core.logAllRefUpdates` key. + pub const LOG_ALL_REF_UPDATES: LogAllRefUpdates = + LogAllRefUpdates::new_with_validate("logAllRefUpdates", &config::Tree::CORE, validate::LogAllRefUpdates); + /// The `core.precomposeUnicode` key. + /// + /// Needs application to use [env::args_os][crate::env::args_os()] to conform all input paths before they are used. + pub const PRECOMPOSE_UNICODE: keys::Boolean = keys::Boolean::new_boolean("precomposeUnicode", &config::Tree::CORE) + .with_note("application needs to conform all program input by using gix::env::args_os()"); + /// The `core.repositoryFormatVersion` key. + pub const REPOSITORY_FORMAT_VERSION: keys::UnsignedInteger = + keys::UnsignedInteger::new_unsigned_integer("repositoryFormatVersion", &config::Tree::CORE); + /// The `core.symlinks` key. + pub const SYMLINKS: keys::Boolean = keys::Boolean::new_boolean("symlinks", &config::Tree::CORE); + /// The `core.trustCTime` key. + pub const TRUST_C_TIME: keys::Boolean = keys::Boolean::new_boolean("trustCTime", &config::Tree::CORE); + /// The `core.worktree` key. + pub const WORKTREE: keys::Any = keys::Any::new("worktree", &config::Tree::CORE) + .with_environment_override("GIT_WORK_TREE") + .with_deviation("Overriding the worktree with environment variables is supported using `ThreadSafeRepository::open_with_environment_overrides()"); + /// The `core.askPass` key. + pub const ASKPASS: keys::Executable = keys::Executable::new_executable("askPass", &config::Tree::CORE) + .with_environment_override("GIT_ASKPASS") + .with_note("fallback is 'SSH_ASKPASS'"); + /// The `core.excludesFile` key. + pub const EXCLUDES_FILE: keys::Executable = keys::Executable::new_executable("excludesFile", &config::Tree::CORE); + /// The `core.attributesFile` key. + pub const ATTRIBUTES_FILE: keys::Executable = + keys::Executable::new_executable("attributesFile", &config::Tree::CORE) + .with_deviation("for checkout - it's already queried but needs building of attributes group, and of course support during checkout"); + /// The `core.sshCommand` key. + pub const SSH_COMMAND: keys::Executable = keys::Executable::new_executable("sshCommand", &config::Tree::CORE) + .with_environment_override("GIT_SSH_COMMAND"); +} + +impl Section for Core { + fn name(&self) -> &str { + "core" + } + + fn keys(&self) -> &[&dyn Key] { + &[ + &Self::ABBREV, + &Self::BARE, + &Self::CHECK_STAT, + &Self::DELTA_BASE_CACHE_LIMIT, + &Self::DISAMBIGUATE, + &Self::FILE_MODE, + &Self::IGNORE_CASE, + &Self::FILES_REF_LOCK_TIMEOUT, + &Self::PACKED_REFS_TIMEOUT, + &Self::MULTIPACK_INDEX, + &Self::LOG_ALL_REF_UPDATES, + &Self::PRECOMPOSE_UNICODE, + &Self::REPOSITORY_FORMAT_VERSION, + &Self::SYMLINKS, + &Self::TRUST_C_TIME, + &Self::WORKTREE, + &Self::ASKPASS, + &Self::EXCLUDES_FILE, + &Self::ATTRIBUTES_FILE, + &Self::SSH_COMMAND, + ] + } +} + +/// The `core.checkStat` key. +pub type CheckStat = keys::Any<validate::CheckStat>; + +/// The `core.abbrev` key. +pub type Abbrev = keys::Any<validate::Abbrev>; + +/// The `core.logAllRefUpdates` key. +pub type LogAllRefUpdates = keys::Any<validate::LogAllRefUpdates>; + +/// The `core.disambiguate` key. +pub type Disambiguate = keys::Any<validate::Disambiguate>; + +mod disambiguate { + use std::borrow::Cow; + + use crate::{ + bstr::{BStr, ByteSlice}, + config, + config::tree::core::Disambiguate, + revision::spec::parse::ObjectKindHint, + }; + + impl Disambiguate { + /// Convert a disambiguation marker into the respective enum. + pub fn try_into_object_kind_hint( + &'static self, + value: Cow<'_, BStr>, + ) -> Result<Option<ObjectKindHint>, config::key::GenericErrorWithValue> { + let hint = match value.as_ref().as_bytes() { + b"none" => return Ok(None), + b"commit" => ObjectKindHint::Commit, + b"committish" => ObjectKindHint::Committish, + b"tree" => ObjectKindHint::Tree, + b"treeish" => ObjectKindHint::Treeish, + b"blob" => ObjectKindHint::Blob, + _ => return Err(config::key::GenericErrorWithValue::from_value(self, value.into_owned())), + }; + Ok(Some(hint)) + } + } +} + +mod log_all_ref_updates { + use std::borrow::Cow; + + use crate::{bstr::BStr, config, config::tree::core::LogAllRefUpdates}; + + impl LogAllRefUpdates { + /// Returns the mode for ref-updates as parsed from `value`. If `value` is not a boolean, `string_on_failure` will be called + /// to obtain the key `core.logAllRefUpdates` as string instead. For correctness, this two step process is necessary as + /// the interpretation of booleans in special in `gix-config`, i.e. we can't just treat it as string. + pub fn try_into_ref_updates<'a>( + &'static self, + value: Option<Result<bool, gix_config::value::Error>>, + string_on_failure: impl FnOnce() -> Option<Cow<'a, BStr>>, + ) -> Result<Option<gix_ref::store::WriteReflog>, config::key::GenericErrorWithValue> { + match value.transpose().ok().flatten() { + Some(bool) => Ok(Some(if bool { + gix_ref::store::WriteReflog::Normal + } else { + gix_ref::store::WriteReflog::Disable + })), + None => match string_on_failure() { + Some(val) if val.eq_ignore_ascii_case(b"always") => Ok(Some(gix_ref::store::WriteReflog::Always)), + Some(val) => Err(config::key::GenericErrorWithValue::from_value(self, val.into_owned())), + None => Ok(None), + }, + } + } + } +} + +mod check_stat { + use std::borrow::Cow; + + use crate::{ + bstr::{BStr, ByteSlice}, + config, + config::tree::core::CheckStat, + }; + + impl CheckStat { + /// Returns true if the full set of stat entries should be checked, and it's just as lenient as git. + pub fn try_into_checkstat( + &'static self, + value: Cow<'_, BStr>, + ) -> Result<bool, config::key::GenericErrorWithValue> { + Ok(match value.as_ref().as_bytes() { + b"minimal" => false, + b"default" => true, + _ => { + return Err(config::key::GenericErrorWithValue::from_value(self, value.into_owned())); + } + }) + } + } +} + +mod abbrev { + use std::borrow::Cow; + + use config::abbrev::Error; + + use crate::{ + bstr::{BStr, ByteSlice}, + config, + config::tree::core::Abbrev, + }; + + impl Abbrev { + /// Convert the given `hex_len_str` into the amount of characters that a short hash should have. + /// If `None` is returned, the correct value can be determined based on the amount of objects in the repo. + pub fn try_into_abbreviation( + &'static self, + hex_len_str: Cow<'_, BStr>, + object_hash: gix_hash::Kind, + ) -> Result<Option<usize>, Error> { + let max = object_hash.len_in_hex() as u8; + if hex_len_str.trim().is_empty() { + return Err(Error { + value: hex_len_str.into_owned(), + max, + }); + } + if hex_len_str.trim().eq_ignore_ascii_case(b"auto") { + Ok(None) + } else { + let value_bytes = hex_len_str.as_ref(); + if let Ok(false) = gix_config::Boolean::try_from(value_bytes).map(Into::into) { + Ok(object_hash.len_in_hex().into()) + } else { + let value = gix_config::Integer::try_from(value_bytes) + .map_err(|_| Error { + value: hex_len_str.clone().into_owned(), + max, + })? + .to_decimal() + .ok_or_else(|| Error { + value: hex_len_str.clone().into_owned(), + max, + })?; + if value < 4 || value as usize > object_hash.len_in_hex() { + return Err(Error { + value: hex_len_str.clone().into_owned(), + max, + }); + } + Ok(Some(value as usize)) + } + } + } + } +} + +mod validate { + use crate::{bstr::BStr, config::tree::keys}; + + pub struct LockTimeout; + impl keys::Validate for LockTimeout { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + let value = gix_config::Integer::try_from(value)? + .to_decimal() + .ok_or_else(|| format!("integer {value} cannot be represented as integer")); + super::Core::FILES_REF_LOCK_TIMEOUT.try_into_lock_timeout(Ok(value?))?; + Ok(()) + } + } + + pub struct Disambiguate; + impl keys::Validate for Disambiguate { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + super::Core::DISAMBIGUATE.try_into_object_kind_hint(value.into())?; + Ok(()) + } + } + + pub struct LogAllRefUpdates; + impl keys::Validate for LogAllRefUpdates { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + super::Core::LOG_ALL_REF_UPDATES + .try_into_ref_updates(Some(gix_config::Boolean::try_from(value).map(|b| b.0)), || { + Some(value.into()) + })?; + Ok(()) + } + } + + pub struct CheckStat; + impl keys::Validate for CheckStat { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + super::Core::CHECK_STAT.try_into_checkstat(value.into())?; + Ok(()) + } + } + + pub struct Abbrev; + impl keys::Validate for Abbrev { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + // TODO: when there is options, validate against all hashes and assure all fail to trigger a validation failure. + super::Core::ABBREV.try_into_abbreviation(value.into(), gix_hash::Kind::Sha1)?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/credential.rs b/vendor/gix/src/config/tree/sections/credential.rs new file mode 100644 index 000000000..d370db0c5 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/credential.rs @@ -0,0 +1,56 @@ +use crate::{ + config, + config::tree::{keys, Credential, Key, Section}, +}; + +impl Credential { + /// The `credential.helper` key. + pub const HELPER: keys::Program = keys::Program::new_program("helper", &config::Tree::CREDENTIAL); + /// The `credential.username` key. + pub const USERNAME: keys::Any = keys::Any::new("username", &config::Tree::CREDENTIAL); + /// The `credential.useHttpPath` key. + pub const USE_HTTP_PATH: keys::Boolean = keys::Boolean::new_boolean("useHttpPath", &config::Tree::CREDENTIAL); + + /// The `credential.<url>` subsection + pub const URL_PARAMETER: UrlParameter = UrlParameter; +} + +/// The `credential.<url>` parameter section. +pub struct UrlParameter; + +impl UrlParameter { + /// The `credential.<url>.helper` key. + pub const HELPER: keys::Program = keys::Program::new_program("helper", &Credential::URL_PARAMETER); + /// The `credential.<url>.username` key. + pub const USERNAME: keys::Any = keys::Any::new("username", &Credential::URL_PARAMETER); + /// The `credential.<url>.useHttpPath` key. + pub const USE_HTTP_PATH: keys::Boolean = keys::Boolean::new_boolean("useHttpPath", &Credential::URL_PARAMETER); +} + +impl Section for UrlParameter { + fn name(&self) -> &str { + "<url>" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::HELPER, &Self::USERNAME, &Self::USE_HTTP_PATH] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&config::Tree::CREDENTIAL) + } +} + +impl Section for Credential { + fn name(&self) -> &str { + "credential" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::HELPER, &Self::USERNAME, &Self::USE_HTTP_PATH] + } + + fn sub_sections(&self) -> &[&dyn Section] { + &[&Self::URL_PARAMETER] + } +} diff --git a/vendor/gix/src/config/tree/sections/diff.rs b/vendor/gix/src/config/tree/sections/diff.rs new file mode 100644 index 000000000..103bb7001 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/diff.rs @@ -0,0 +1,133 @@ +use crate::{ + config, + config::tree::{keys, Diff, Key, Section}, +}; + +impl Diff { + /// The `diff.algorithm` key. + pub const ALGORITHM: Algorithm = Algorithm::new_with_validate("algorithm", &config::Tree::DIFF, validate::Algorithm) + .with_deviation("'patience' diff is not implemented and can default to 'histogram' if lenient config is used, and defaults to histogram if unset for fastest and best results"); + /// The `diff.renameLimit` key. + pub const RENAME_LIMIT: keys::UnsignedInteger = keys::UnsignedInteger::new_unsigned_integer( + "renameLimit", + &config::Tree::DIFF, + ) + .with_note( + "The limit is actually squared, so 1000 stands for up to 1 million diffs if fuzzy rename tracking is enabled", + ); + /// The `diff.renames` key. + pub const RENAMES: Renames = Renames::new_renames("renames", &config::Tree::DIFF); +} + +impl Section for Diff { + fn name(&self) -> &str { + "diff" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::ALGORITHM, &Self::RENAME_LIMIT, &Self::RENAMES] + } +} + +/// The `diff.algorithm` key. +pub type Algorithm = keys::Any<validate::Algorithm>; + +/// The `diff.renames` key. +pub type Renames = keys::Any<validate::Renames>; + +mod algorithm { + use std::borrow::Cow; + + use crate::{ + bstr::BStr, + config, + config::{diff::algorithm::Error, tree::sections::diff::Algorithm}, + }; + + impl Algorithm { + /// Derive the diff algorithm identified by `name`, case-insensitively. + pub fn try_into_algorithm(&self, name: Cow<'_, BStr>) -> Result<gix_diff::blob::Algorithm, Error> { + let algo = if name.eq_ignore_ascii_case(b"myers") || name.eq_ignore_ascii_case(b"default") { + gix_diff::blob::Algorithm::Myers + } else if name.eq_ignore_ascii_case(b"minimal") { + gix_diff::blob::Algorithm::MyersMinimal + } else if name.eq_ignore_ascii_case(b"histogram") { + gix_diff::blob::Algorithm::Histogram + } else if name.eq_ignore_ascii_case(b"patience") { + return Err(config::diff::algorithm::Error::Unimplemented { + name: name.into_owned(), + }); + } else { + return Err(Error::Unknown { + name: name.into_owned(), + }); + }; + Ok(algo) + } + } +} + +mod renames { + use std::borrow::Cow; + + use crate::{ + bstr::{BStr, ByteSlice}, + config::{ + key::GenericError, + tree::{keys, sections::diff::Renames, Section}, + }, + diff::rename::Tracking, + }; + + impl Renames { + /// Create a new instance. + pub const fn new_renames(name: &'static str, section: &'static dyn Section) -> Self { + keys::Any::new_with_validate(name, section, super::validate::Renames) + } + /// Try to convert the configuration into a valid rename tracking variant. Use `value` and if it's an error, call `value_string` + /// to try and interpret the key as string. + pub fn try_into_renames<'a>( + &'static self, + value: Result<bool, gix_config::value::Error>, + value_string: impl FnOnce() -> Option<Cow<'a, BStr>>, + ) -> Result<Tracking, GenericError> { + Ok(match value { + Ok(true) => Tracking::Renames, + Ok(false) => Tracking::Disabled, + Err(err) => { + let value = value_string().ok_or_else(|| GenericError::from(self))?; + match value.as_ref().as_bytes() { + b"copy" | b"copies" => Tracking::RenamesAndCopies, + _ => return Err(GenericError::from_value(self, value.into_owned()).with_source(err)), + } + } + }) + } + } +} + +mod validate { + use std::borrow::Cow; + + use crate::{ + bstr::BStr, + config::tree::{keys, Diff}, + }; + + pub struct Algorithm; + impl keys::Validate for Algorithm { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + Diff::ALGORITHM.try_into_algorithm(value.into())?; + Ok(()) + } + } + + pub struct Renames; + impl keys::Validate for Renames { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + let boolean = gix_config::Boolean::try_from(value).map(|b| b.0); + Diff::RENAMES.try_into_renames(boolean, || Some(Cow::Borrowed(value)))?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/extensions.rs b/vendor/gix/src/config/tree/sections/extensions.rs new file mode 100644 index 000000000..77130f804 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/extensions.rs @@ -0,0 +1,59 @@ +use crate::{ + config, + config::tree::{keys, Extensions, Key, Section}, +}; + +impl Extensions { + /// The `extensions.worktreeConfig` key. + pub const WORKTREE_CONFIG: keys::Boolean = keys::Boolean::new_boolean("worktreeConfig", &config::Tree::EXTENSIONS); + /// The `extensions.objectFormat` key. + pub const OBJECT_FORMAT: ObjectFormat = + ObjectFormat::new_with_validate("objectFormat", &config::Tree::EXTENSIONS, validate::ObjectFormat).with_note( + "Support for SHA256 is prepared but not fully implemented yet. For now we abort when encountered", + ); +} + +/// The `core.checkStat` key. +pub type ObjectFormat = keys::Any<validate::ObjectFormat>; + +mod object_format { + use std::borrow::Cow; + + use crate::{bstr::BStr, config, config::tree::sections::extensions::ObjectFormat}; + + impl ObjectFormat { + pub fn try_into_object_format( + &'static self, + value: Cow<'_, BStr>, + ) -> Result<gix_hash::Kind, config::key::GenericErrorWithValue> { + if value.as_ref().eq_ignore_ascii_case(b"sha1") { + Ok(gix_hash::Kind::Sha1) + } else { + Err(config::key::GenericErrorWithValue::from_value(self, value.into_owned())) + } + } + } +} + +impl Section for Extensions { + fn name(&self) -> &str { + "extensions" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::OBJECT_FORMAT, &Self::WORKTREE_CONFIG] + } +} + +mod validate { + use crate::{bstr::BStr, config::tree::keys}; + + pub struct ObjectFormat; + + impl keys::Validate for ObjectFormat { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + super::Extensions::OBJECT_FORMAT.try_into_object_format(value.into())?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/gitoxide.rs b/vendor/gix/src/config/tree/sections/gitoxide.rs new file mode 100644 index 000000000..8c3defd0b --- /dev/null +++ b/vendor/gix/src/config/tree/sections/gitoxide.rs @@ -0,0 +1,363 @@ +use crate::config::tree::{keys, Gitoxide, Key, Section}; + +impl Gitoxide { + /// The `gitoxide.allow` section. + pub const ALLOW: Allow = Allow; + /// The `gitoxide.author` section. + pub const AUTHOR: Author = Author; + /// The `gitoxide.commit` section. + pub const COMMIT: Commit = Commit; + /// The `gitoxide.committer` section. + pub const COMMITTER: Committer = Committer; + /// The `gitoxide.http` section. + pub const HTTP: Http = Http; + /// The `gitoxide.https` section. + pub const HTTPS: Https = Https; + /// The `gitoxide.objects` section. + pub const OBJECTS: Objects = Objects; + /// The `gitoxide.ssh` section. + pub const SSH: Ssh = Ssh; + /// The `gitoxide.user` section. + pub const USER: User = User; + + /// The `gitoxide.userAgent` Key. + pub const USER_AGENT: keys::Any = keys::Any::new("userAgent", &config::Tree::GITOXIDE).with_note( + "The user agent presented on the git protocol layer, serving as fallback for when no `http.userAgent` is set", + ); +} + +impl Section for Gitoxide { + fn name(&self) -> &str { + "gitoxide" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::USER_AGENT] + } + + fn sub_sections(&self) -> &[&dyn Section] { + &[ + &Self::ALLOW, + &Self::AUTHOR, + &Self::COMMIT, + &Self::COMMITTER, + &Self::HTTP, + &Self::HTTPS, + &Self::OBJECTS, + &Self::SSH, + &Self::USER, + ] + } +} + +mod subsections { + use crate::config::{ + tree::{http, keys, Gitoxide, Key, Section}, + Tree, + }; + + /// The `Http` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Http; + + impl Http { + /// The `gitoxide.http.proxy` key. + pub const PROXY: keys::String = + keys::String::new_string("proxy", &Gitoxide::HTTP).with_environment_override("http_proxy"); + /// The `gitoxide.http.allProxy` key. + pub const ALL_PROXY: keys::String = keys::String::new_string("allProxy", &Gitoxide::HTTP) + .with_environment_override("all_proxy") + .with_note("fallback environment is `ALL_PROXY`"); + /// The `gitoxide.http.verbose` key. + /// + /// If set, curl will be configured to log verbosely. + pub const VERBOSE: keys::Boolean = keys::Boolean::new_boolean("verbose", &Gitoxide::HTTP) + .with_environment_override("GIT_CURL_VERBOSE") + .with_deviation("we parse it as boolean for convenience (infallible) but git only checks the presence"); + /// The `gitoxide.http.noProxy` key. + pub const NO_PROXY: keys::String = keys::String::new_string("noProxy", &Gitoxide::HTTP) + .with_environment_override("no_proxy") + .with_note("fallback environment is `NO_PROXY`"); + /// The `gitoxide.http.connectTimeout` key. + pub const CONNECT_TIMEOUT: keys::DurationInMilliseconds = + keys::DurationInMilliseconds::new_duration("connectTimeout", &Gitoxide::HTTP).with_note( + "entirely new, and in milliseconds, to describe how long to wait until a connection attempt is aborted", + ); + /// The `gitoxide.http.sslVersionMin` key. + pub const SSL_VERSION_MIN: http::SslVersion = + http::SslVersion::new_ssl_version("sslVersionMin", &Gitoxide::HTTP).with_note( + "entirely new to set the lower bound for the allowed ssl version range. Overwrites the min bound of `http.sslVersion` if set. Min and Max must be set to become effective.", + ); + /// The `gitoxide.http.sslVersionMax` key. + pub const SSL_VERSION_MAX: http::SslVersion = + http::SslVersion::new_ssl_version("sslVersionMax", &Gitoxide::HTTP).with_note( + "entirely new to set the upper bound for the allowed ssl version range. Overwrites the max bound of `http.sslVersion` if set. Min and Max must be set to become effective.", + ); + /// The `gitoxide.http.proxyAuthMethod` key. + pub const PROXY_AUTH_METHOD: http::ProxyAuthMethod = + http::ProxyAuthMethod::new_proxy_auth_method("proxyAuthMethod", &Gitoxide::HTTP) + .with_environment_override("GIT_HTTP_PROXY_AUTHMETHOD"); + } + + impl Section for Http { + fn name(&self) -> &str { + "http" + } + + fn keys(&self) -> &[&dyn Key] { + &[ + &Self::PROXY, + &Self::ALL_PROXY, + &Self::VERBOSE, + &Self::NO_PROXY, + &Self::CONNECT_TIMEOUT, + &Self::SSL_VERSION_MIN, + &Self::SSL_VERSION_MAX, + &Self::PROXY_AUTH_METHOD, + ] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `Https` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Https; + + impl Https { + /// The `gitoxide.https.proxy` key. + pub const PROXY: keys::String = keys::String::new_string("proxy", &Gitoxide::HTTPS) + .with_environment_override("HTTPS_PROXY") + .with_note("fallback environment variable is `https_proxy`"); + } + + impl Section for Https { + fn name(&self) -> &str { + "https" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::PROXY] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `allow` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Allow; + + /// The `gitoxide.allow.protocolFromUser` key. + pub type ProtocolFromUser = keys::Any<super::validate::ProtocolFromUser>; + + impl Allow { + /// The `gitoxide.allow.protocolFromUser` key. + pub const PROTOCOL_FROM_USER: ProtocolFromUser = ProtocolFromUser::new_with_validate( + "protocolFromUser", + &Gitoxide::ALLOW, + super::validate::ProtocolFromUser, + ) + .with_environment_override("GIT_PROTOCOL_FROM_USER"); + } + + impl Section for Allow { + fn name(&self) -> &str { + "allow" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::PROTOCOL_FROM_USER] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `author` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Author; + + impl Author { + /// The `gitoxide.author.nameFallback` key. + pub const NAME_FALLBACK: keys::Any = + keys::Any::new("nameFallback", &Gitoxide::AUTHOR).with_environment_override("GIT_AUTHOR_NAME"); + /// The `gitoxide.author.emailFallback` key. + pub const EMAIL_FALLBACK: keys::Any = + keys::Any::new("emailFallback", &Gitoxide::AUTHOR).with_environment_override("GIT_AUTHOR_EMAIL"); + } + + impl Section for Author { + fn name(&self) -> &str { + "author" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::NAME_FALLBACK, &Self::EMAIL_FALLBACK] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `user` sub-section. + #[derive(Copy, Clone, Default)] + pub struct User; + + impl User { + /// The `gitoxide.user.emailFallback` key. + pub const EMAIL_FALLBACK: keys::Any = + keys::Any::new("emailFallback", &Gitoxide::USER).with_environment_override("EMAIL"); + } + + impl Section for User { + fn name(&self) -> &str { + "user" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::EMAIL_FALLBACK] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `ssh` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Ssh; + + impl Ssh { + /// The `gitoxide.ssh.commandWithoutShellFallback` key. + pub const COMMAND_WITHOUT_SHELL_FALLBACK: keys::Executable = + keys::Executable::new_executable("commandWithoutShellFallback", &Gitoxide::SSH) + .with_environment_override("GIT_SSH") + .with_note("is always executed without shell and treated as fallback"); + } + + impl Section for Ssh { + fn name(&self) -> &str { + "ssh" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::COMMAND_WITHOUT_SHELL_FALLBACK] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `objects` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Objects; + + impl Objects { + /// The `gitoxide.objects.cacheLimit` key. + pub const CACHE_LIMIT: keys::UnsignedInteger = + keys::UnsignedInteger::new_unsigned_integer("cacheLimit", &Gitoxide::OBJECTS) + .with_note("If unset or 0, there is no object cache") + .with_environment_override("GITOXIDE_OBJECT_CACHE_MEMORY"); + /// The `gitoxide.objects.noReplace` key. + pub const NO_REPLACE: keys::Boolean = keys::Boolean::new_boolean("noReplace", &Gitoxide::OBJECTS) + .with_environment_override("GIT_NO_REPLACE_OBJECTS"); + /// The `gitoxide.objects.replaceRefBase` key. + pub const REPLACE_REF_BASE: keys::Any = + keys::Any::new("replaceRefBase", &Gitoxide::OBJECTS).with_environment_override("GIT_REPLACE_REF_BASE"); + } + + impl Section for Objects { + fn name(&self) -> &str { + "objects" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::CACHE_LIMIT, &Self::NO_REPLACE, &Self::REPLACE_REF_BASE] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `committer` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Committer; + + impl Committer { + /// The `gitoxide.committer.nameFallback` key. + pub const NAME_FALLBACK: keys::Any = + keys::Any::new("nameFallback", &Gitoxide::COMMITTER).with_environment_override("GIT_COMMITTER_NAME"); + /// The `gitoxide.committer.emailFallback` key. + pub const EMAIL_FALLBACK: keys::Any = + keys::Any::new("emailFallback", &Gitoxide::COMMITTER).with_environment_override("GIT_COMMITTER_EMAIL"); + } + + impl Section for Committer { + fn name(&self) -> &str { + "committer" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::NAME_FALLBACK, &Self::EMAIL_FALLBACK] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + + /// The `commit` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Commit; + + impl Commit { + /// The `gitoxide.commit.authorDate` key. + pub const AUTHOR_DATE: keys::Time = + keys::Time::new_time("authorDate", &Gitoxide::COMMIT).with_environment_override("GIT_AUTHOR_DATE"); + /// The `gitoxide.commit.committerDate` key. + pub const COMMITTER_DATE: keys::Time = + keys::Time::new_time("committerDate", &Gitoxide::COMMIT).with_environment_override("GIT_COMMITTER_DATE"); + } + + impl Section for Commit { + fn name(&self) -> &str { + "commit" + } + + fn keys(&self) -> &[&dyn Key] { + &[] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } +} + +pub mod validate { + use std::error::Error; + + use crate::{bstr::BStr, config::tree::keys::Validate}; + + pub struct ProtocolFromUser; + impl Validate for ProtocolFromUser { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + if value != "1" { + return Err("GIT_PROTOCOL_FROM_USER is either unset or as the value '1'".into()); + } + Ok(()) + } + } +} + +pub use subsections::{Allow, Author, Commit, Committer, Http, Https, Objects, Ssh, User}; + +use crate::config; diff --git a/vendor/gix/src/config/tree/sections/http.rs b/vendor/gix/src/config/tree/sections/http.rs new file mode 100644 index 000000000..f45c37076 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/http.rs @@ -0,0 +1,317 @@ +use crate::{ + config, + config::tree::{keys, Http, Key, Section}, +}; + +impl Http { + /// The `http.sslVersion` key. + pub const SSL_VERSION: SslVersion = SslVersion::new_ssl_version("sslVersion", &config::Tree::HTTP) + .with_environment_override("GIT_SSL_VERSION") + .with_deviation( + "accepts the new 'default' value which means to use the curl default just like the empty string does", + ); + /// The `http.proxy` key. + pub const PROXY: keys::String = + keys::String::new_string("proxy", &config::Tree::HTTP).with_deviation("fails on strings with illformed UTF-8"); + /// The `http.proxyAuthMethod` key. + pub const PROXY_AUTH_METHOD: ProxyAuthMethod = + ProxyAuthMethod::new_proxy_auth_method("proxyAuthMethod", &config::Tree::HTTP) + .with_deviation("implemented like git, but never actually tried"); + /// The `http.version` key. + pub const VERSION: Version = Version::new_with_validate("version", &config::Tree::HTTP, validate::Version) + .with_deviation("fails on illformed UTF-8"); + /// The `http.userAgent` key. + pub const USER_AGENT: keys::String = + keys::String::new_string("userAgent", &config::Tree::HTTP).with_deviation("fails on illformed UTF-8"); + /// The `http.extraHeader` key. + pub const EXTRA_HEADER: ExtraHeader = + ExtraHeader::new_with_validate("extraHeader", &config::Tree::HTTP, validate::ExtraHeader) + .with_deviation("fails on illformed UTF-8, without leniency"); + /// The `http.followRedirects` key. + pub const FOLLOW_REDIRECTS: FollowRedirects = + FollowRedirects::new_with_validate("followRedirects", &config::Tree::HTTP, validate::FollowRedirects); + /// The `http.lowSpeedTime` key. + pub const LOW_SPEED_TIME: keys::UnsignedInteger = + keys::UnsignedInteger::new_unsigned_integer("lowSpeedTime", &config::Tree::HTTP) + .with_deviation("fails on negative values"); + /// The `http.lowSpeedLimit` key. + pub const LOW_SPEED_LIMIT: keys::UnsignedInteger = + keys::UnsignedInteger::new_unsigned_integer("lowSpeedLimit", &config::Tree::HTTP) + .with_deviation("fails on negative values"); + /// The `http.schannelUseSSLCAInfo` key. + pub const SCHANNEL_USE_SSL_CA_INFO: keys::Boolean = + keys::Boolean::new_boolean("schannelUseSSLCAInfo", &config::Tree::HTTP) + .with_deviation("only used as switch internally to turn off using the sslCAInfo, unconditionally. If unset, it has no effect, whereas in `git` it defaults to false."); + /// The `http.sslCAInfo` key. + pub const SSL_CA_INFO: keys::Path = + keys::Path::new_path("sslCAInfo", &config::Tree::HTTP).with_environment_override("GIT_SSL_CAINFO"); + /// The `http.schannelCheckRevoke` key. + pub const SCHANNEL_CHECK_REVOKE: keys::Boolean = + keys::Boolean::new_boolean("schannelCheckRevoke", &config::Tree::HTTP); +} + +impl Section for Http { + fn name(&self) -> &str { + "http" + } + + fn keys(&self) -> &[&dyn Key] { + &[ + &Self::SSL_VERSION, + &Self::PROXY, + &Self::PROXY_AUTH_METHOD, + &Self::VERSION, + &Self::USER_AGENT, + &Self::EXTRA_HEADER, + &Self::FOLLOW_REDIRECTS, + &Self::LOW_SPEED_TIME, + &Self::LOW_SPEED_LIMIT, + &Self::SCHANNEL_USE_SSL_CA_INFO, + &Self::SSL_CA_INFO, + &Self::SCHANNEL_CHECK_REVOKE, + ] + } +} + +/// The `http.followRedirects` key. +pub type FollowRedirects = keys::Any<validate::FollowRedirects>; + +/// The `http.extraHeader` key. +pub type ExtraHeader = keys::Any<validate::ExtraHeader>; + +/// The `http.sslVersion` key, as well as others of the same type. +pub type SslVersion = keys::Any<validate::SslVersion>; + +/// The `http.proxyAuthMethod` key, as well as others of the same type. +pub type ProxyAuthMethod = keys::Any<validate::ProxyAuthMethod>; + +/// The `http.version` key. +pub type Version = keys::Any<validate::Version>; + +mod key_impls { + use crate::config::tree::{ + http::{ProxyAuthMethod, SslVersion}, + keys, Section, + }; + + impl SslVersion { + pub const fn new_ssl_version(name: &'static str, section: &'static dyn Section) -> Self { + keys::Any::new_with_validate(name, section, super::validate::SslVersion) + } + } + + impl ProxyAuthMethod { + pub const fn new_proxy_auth_method(name: &'static str, section: &'static dyn Section) -> Self { + keys::Any::new_with_validate(name, section, super::validate::ProxyAuthMethod) + } + } + + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + impl crate::config::tree::http::FollowRedirects { + /// Convert `value` into the redirect specification, or query the same value as `boolean` + /// for additional possible input values. + /// + /// Note that `boolean` only queries the underlying key as boolean, which is a necessity to handle + /// empty booleans correctly, that is those without a value separator. + pub fn try_into_follow_redirects( + &'static self, + value: std::borrow::Cow<'_, crate::bstr::BStr>, + boolean: impl FnOnce() -> Result<Option<bool>, gix_config::value::Error>, + ) -> Result< + crate::protocol::transport::client::http::options::FollowRedirects, + crate::config::key::GenericErrorWithValue, + > { + use crate::{bstr::ByteSlice, protocol::transport::client::http::options::FollowRedirects}; + Ok(if value.as_ref().as_bytes() == b"initial" { + FollowRedirects::Initial + } else if let Some(value) = boolean().map_err(|err| { + crate::config::key::GenericErrorWithValue::from_value(self, value.into_owned()).with_source(err) + })? { + if value { + FollowRedirects::All + } else { + FollowRedirects::None + } + } else { + FollowRedirects::Initial + }) + } + } + + impl super::ExtraHeader { + /// Convert a list of values into extra-headers, while failing entirely on illformed UTF-8. + pub fn try_into_extra_header( + &'static self, + values: Vec<std::borrow::Cow<'_, crate::bstr::BStr>>, + ) -> Result<Vec<String>, crate::config::string::Error> { + let mut out = Vec::with_capacity(values.len()); + for value in values { + if value.is_empty() { + out.clear(); + } else { + out.push(self.try_into_string(value)?); + } + } + Ok(out) + } + } + + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + impl super::Version { + pub fn try_into_http_version( + &'static self, + value: std::borrow::Cow<'_, crate::bstr::BStr>, + ) -> Result< + gix_protocol::transport::client::http::options::HttpVersion, + crate::config::key::GenericErrorWithValue, + > { + use gix_protocol::transport::client::http::options::HttpVersion; + + use crate::bstr::ByteSlice; + Ok(match value.as_ref().as_bytes() { + b"HTTP/1.1" => HttpVersion::V1_1, + b"HTTP/2" => HttpVersion::V2, + _ => { + return Err(crate::config::key::GenericErrorWithValue::from_value( + self, + value.into_owned(), + )) + } + }) + } + } + + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + impl ProxyAuthMethod { + pub fn try_into_proxy_auth_method( + &'static self, + value: std::borrow::Cow<'_, crate::bstr::BStr>, + ) -> Result< + gix_protocol::transport::client::http::options::ProxyAuthMethod, + crate::config::key::GenericErrorWithValue, + > { + use gix_protocol::transport::client::http::options::ProxyAuthMethod; + + use crate::bstr::ByteSlice; + Ok(match value.as_ref().as_bytes() { + b"anyauth" => ProxyAuthMethod::AnyAuth, + b"basic" => ProxyAuthMethod::Basic, + b"digest" => ProxyAuthMethod::Digest, + b"negotiate" => ProxyAuthMethod::Negotiate, + b"ntlm" => ProxyAuthMethod::Ntlm, + _ => { + return Err(crate::config::key::GenericErrorWithValue::from_value( + self, + value.into_owned(), + )) + } + }) + } + } + + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + impl SslVersion { + pub fn try_into_ssl_version( + &'static self, + value: std::borrow::Cow<'_, crate::bstr::BStr>, + ) -> Result<gix_protocol::transport::client::http::options::SslVersion, crate::config::ssl_version::Error> + { + use gix_protocol::transport::client::http::options::SslVersion::*; + + use crate::bstr::ByteSlice; + Ok(match value.as_ref().as_bytes() { + b"default" | b"" => Default, + b"tlsv1" => TlsV1, + b"sslv2" => SslV2, + b"sslv3" => SslV3, + b"tlsv1.0" => TlsV1_0, + b"tlsv1.1" => TlsV1_1, + b"tlsv1.2" => TlsV1_2, + b"tlsv1.3" => TlsV1_3, + _ => return Err(crate::config::ssl_version::Error::from_value(self, value.into_owned())), + }) + } + } +} + +pub mod validate { + use std::error::Error; + + use crate::{ + bstr::{BStr, ByteSlice}, + config::tree::keys::Validate, + }; + + pub struct SslVersion; + impl Validate for SslVersion { + fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + super::Http::SSL_VERSION.try_into_ssl_version(std::borrow::Cow::Borrowed(_value))?; + + Ok(()) + } + } + + pub struct ProxyAuthMethod; + impl Validate for ProxyAuthMethod { + fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + super::Http::PROXY_AUTH_METHOD.try_into_proxy_auth_method(std::borrow::Cow::Borrowed(_value))?; + + Ok(()) + } + } + + pub struct Version; + impl Validate for Version { + fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + super::Http::VERSION.try_into_http_version(std::borrow::Cow::Borrowed(_value))?; + + Ok(()) + } + } + + pub struct ExtraHeader; + impl Validate for ExtraHeader { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + value.to_str()?; + Ok(()) + } + } + + pub struct FollowRedirects; + impl Validate for FollowRedirects { + fn validate(&self, _value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + #[cfg(any( + feature = "blocking-http-transport-reqwest", + feature = "blocking-http-transport-curl" + ))] + super::Http::FOLLOW_REDIRECTS.try_into_follow_redirects(std::borrow::Cow::Borrowed(_value), || { + gix_config::Boolean::try_from(_value).map(|b| Some(b.0)) + })?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/init.rs b/vendor/gix/src/config/tree/sections/init.rs new file mode 100644 index 000000000..de42d3b62 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/init.rs @@ -0,0 +1,20 @@ +use crate::{ + config, + config::tree::{keys, Init, Key, Section}, +}; + +impl Init { + /// The `init.defaultBranch` key. + pub const DEFAULT_BRANCH: keys::Any = keys::Any::new("defaultBranch", &config::Tree::INIT) + .with_deviation("If not set, we use `main` instead of `master`"); +} + +impl Section for Init { + fn name(&self) -> &str { + "init" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::DEFAULT_BRANCH] + } +} diff --git a/vendor/gix/src/config/tree/sections/mod.rs b/vendor/gix/src/config/tree/sections/mod.rs new file mode 100644 index 000000000..fb9b50786 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/mod.rs @@ -0,0 +1,96 @@ +#![allow(missing_docs)] + +/// The `author` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Author; +mod author; + +/// The `branch` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Branch; +pub mod branch; + +/// The `checkout` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Checkout; +pub mod checkout; + +/// The `clone` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Clone; +mod clone; + +/// The `committer` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Committer; +mod committer; + +/// The `core` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Core; +pub mod core; + +/// The `credential` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Credential; +pub mod credential; + +/// The `diff` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Diff; +pub mod diff; + +/// The `extension` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Extensions; +pub mod extensions; + +/// The `gitoxide` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Gitoxide; +pub mod gitoxide; + +/// The `http` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Http; +pub mod http; + +/// The `init` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Init; +mod init; + +/// The `pack` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Pack; +pub mod pack; + +/// The `protocol` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Protocol; +pub mod protocol; + +/// The `remote` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Remote; +pub mod remote; + +/// The `safe` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Safe; +mod safe; + +/// The `ssh` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Ssh; +pub mod ssh; + +/// The `user` top-level section. +#[derive(Copy, Clone, Default)] +pub struct User; +mod user; + +/// The `url` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Url; +mod url; diff --git a/vendor/gix/src/config/tree/sections/pack.rs b/vendor/gix/src/config/tree/sections/pack.rs new file mode 100644 index 000000000..941817e5b --- /dev/null +++ b/vendor/gix/src/config/tree/sections/pack.rs @@ -0,0 +1,64 @@ +use crate::{ + config, + config::tree::{keys, Key, Pack, Section}, +}; + +impl Pack { + /// The `pack.threads` key. + pub const THREADS: keys::UnsignedInteger = + keys::UnsignedInteger::new_unsigned_integer("threads", &config::Tree::PACK) + .with_deviation("Leaving this key unspecified uses all available cores, instead of 1"); + + /// The `pack.indexVersion` key. + pub const INDEX_VERSION: IndexVersion = + IndexVersion::new_with_validate("indexVersion", &config::Tree::PACK, validate::IndexVersion); +} + +/// The `pack.indexVersion` key. +pub type IndexVersion = keys::Any<validate::IndexVersion>; + +mod index_version { + use crate::{config, config::tree::sections::pack::IndexVersion}; + + impl IndexVersion { + /// Try to interpret an integer value as index version. + pub fn try_into_index_version( + &'static self, + value: Result<i64, gix_config::value::Error>, + ) -> Result<gix_pack::index::Version, config::key::GenericError> { + let value = value.map_err(|err| config::key::GenericError::from(self).with_source(err))?; + Ok(match value { + 1 => gix_pack::index::Version::V1, + 2 => gix_pack::index::Version::V2, + _ => return Err(config::key::GenericError::from(self)), + }) + } + } +} + +impl Section for Pack { + fn name(&self) -> &str { + "pack" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::THREADS, &Self::INDEX_VERSION] + } +} + +mod validate { + use crate::{bstr::BStr, config::tree::keys}; + + pub struct IndexVersion; + impl keys::Validate for IndexVersion { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + super::Pack::INDEX_VERSION.try_into_index_version(gix_config::Integer::try_from(value).and_then( + |int| { + int.to_decimal() + .ok_or_else(|| gix_config::value::Error::new("integer out of range", value)) + }, + ))?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/protocol.rs b/vendor/gix/src/config/tree/sections/protocol.rs new file mode 100644 index 000000000..58e907b0f --- /dev/null +++ b/vendor/gix/src/config/tree/sections/protocol.rs @@ -0,0 +1,85 @@ +use crate::{ + config, + config::tree::{keys, Key, Protocol, Section}, +}; + +impl Protocol { + /// The `protocol.allow` key. + pub const ALLOW: Allow = Allow::new_with_validate("allow", &config::Tree::PROTOCOL, validate::Allow); + + /// The `protocol.<name>` subsection + pub const NAME_PARAMETER: NameParameter = NameParameter; +} + +/// The `protocol.allow` key type. +pub type Allow = keys::Any<validate::Allow>; + +#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))] +mod allow { + use std::borrow::Cow; + + use crate::{bstr::BStr, config, config::tree::protocol::Allow, remote::url::scheme_permission}; + + impl Allow { + /// Convert `value` into its respective `Allow` variant, possibly informing about the `scheme` we are looking at in the error. + pub fn try_into_allow( + &'static self, + value: Cow<'_, BStr>, + scheme: Option<&str>, + ) -> Result<scheme_permission::Allow, config::protocol::allow::Error> { + scheme_permission::Allow::try_from(value).map_err(|value| config::protocol::allow::Error { + value, + scheme: scheme.map(ToOwned::to_owned), + }) + } + } +} + +/// The `protocol.<name>` parameter section. +pub struct NameParameter; + +impl NameParameter { + /// The `credential.<url>.helper` key. + pub const ALLOW: Allow = Allow::new_with_validate("allow", &Protocol::NAME_PARAMETER, validate::Allow); +} + +impl Section for NameParameter { + fn name(&self) -> &str { + "<name>" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::ALLOW] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&config::Tree::PROTOCOL) + } +} + +impl Section for Protocol { + fn name(&self) -> &str { + "protocol" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::ALLOW] + } + + fn sub_sections(&self) -> &[&dyn Section] { + &[&Self::NAME_PARAMETER] + } +} + +mod validate { + use crate::{bstr::BStr, config::tree::keys}; + + pub struct Allow; + impl keys::Validate for Allow { + fn validate(&self, _value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))] + super::Protocol::ALLOW.try_into_allow(std::borrow::Cow::Borrowed(_value), None)?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/remote.rs b/vendor/gix/src/config/tree/sections/remote.rs new file mode 100644 index 000000000..b242c9c14 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/remote.rs @@ -0,0 +1,101 @@ +use crate::{ + config, + config::tree::{http, keys, Key, Remote, Section, SubSectionRequirement}, +}; + +const NAME_PARAMETER: Option<SubSectionRequirement> = Some(SubSectionRequirement::Parameter("name")); + +impl Remote { + /// The `remote.pushDefault` key + pub const PUSH_DEFAULT: keys::RemoteName = keys::RemoteName::new_remote_name("pushDefault", &config::Tree::REMOTE); + /// The `remote.<name>.tagOpt` key + pub const TAG_OPT: TagOpt = TagOpt::new_with_validate("tagOpt", &config::Tree::REMOTE, validate::TagOpt) + .with_subsection_requirement(Some(SubSectionRequirement::Parameter("name"))); + /// The `remote.<name>.url` key + pub const URL: keys::Url = + keys::Url::new_url("url", &config::Tree::REMOTE).with_subsection_requirement(NAME_PARAMETER); + /// The `remote.<name>.pushUrl` key + pub const PUSH_URL: keys::Url = + keys::Url::new_url("pushUrl", &config::Tree::REMOTE).with_subsection_requirement(NAME_PARAMETER); + /// The `remote.<name>.fetch` key + pub const FETCH: keys::FetchRefSpec = keys::FetchRefSpec::new_fetch_refspec("fetch", &config::Tree::REMOTE) + .with_subsection_requirement(NAME_PARAMETER); + /// The `remote.<name>.push` key + pub const PUSH: keys::PushRefSpec = + keys::PushRefSpec::new_push_refspec("push", &config::Tree::REMOTE).with_subsection_requirement(NAME_PARAMETER); + /// The `remote.<name>.proxy` key + pub const PROXY: keys::String = + keys::String::new_string("proxy", &config::Tree::REMOTE).with_subsection_requirement(NAME_PARAMETER); + /// The `remote.<name>.proxyAuthMethod` key. + pub const PROXY_AUTH_METHOD: http::ProxyAuthMethod = + http::ProxyAuthMethod::new_proxy_auth_method("proxyAuthMethod", &config::Tree::REMOTE) + .with_subsection_requirement(NAME_PARAMETER) + .with_deviation("implemented like git, but never actually tried"); +} + +impl Section for Remote { + fn name(&self) -> &str { + "remote" + } + + fn keys(&self) -> &[&dyn Key] { + &[ + &Self::PUSH_DEFAULT, + &Self::TAG_OPT, + &Self::URL, + &Self::PUSH_URL, + &Self::FETCH, + &Self::PUSH, + &Self::PROXY, + &Self::PROXY_AUTH_METHOD, + ] + } +} + +/// The `remote.<name>.tagOpt` key type. +pub type TagOpt = keys::Any<validate::TagOpt>; + +mod tag_opts { + use std::borrow::Cow; + + use crate::{ + bstr::{BStr, ByteSlice}, + config, + config::tree::remote::TagOpt, + remote, + }; + + impl TagOpt { + /// Try to interpret `value` as tag option. + /// + /// # Note + /// + /// It's heavily biased towards the git command-line unfortunately, and the only + /// value of its kind. Maybe in future more values will be supported which are less + /// about passing them to a sub-process. + pub fn try_into_tag_opt( + &'static self, + value: Cow<'_, BStr>, + ) -> Result<remote::fetch::Tags, config::key::GenericErrorWithValue> { + Ok(match value.as_ref().as_bytes() { + b"--tags" => remote::fetch::Tags::All, + b"--no-tags" => remote::fetch::Tags::None, + _ => return Err(config::key::GenericErrorWithValue::from_value(self, value.into_owned())), + }) + } + } +} + +pub mod validate { + use std::{borrow::Cow, error::Error}; + + use crate::{bstr::BStr, config::tree::keys::Validate}; + + pub struct TagOpt; + impl Validate for TagOpt { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { + super::Remote::TAG_OPT.try_into_tag_opt(Cow::Borrowed(value))?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/safe.rs b/vendor/gix/src/config/tree/sections/safe.rs new file mode 100644 index 000000000..e76d28888 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/safe.rs @@ -0,0 +1,27 @@ +use crate::{ + config, + config::tree::{keys, Key, Safe, Section}, +}; + +impl Safe { + /// The `safe.directory` key + pub const DIRECTORY: keys::Any = keys::Any::new("directory", &config::Tree::SAFE); +} + +impl Safe { + /// Implements the directory filter to trust only global and system files, for use with `safe.directory`. + pub fn directory_filter(meta: &gix_config::file::Metadata) -> bool { + let kind = meta.source.kind(); + kind == gix_config::source::Kind::System || kind == gix_config::source::Kind::Global + } +} + +impl Section for Safe { + fn name(&self) -> &str { + "safe" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::DIRECTORY] + } +} diff --git a/vendor/gix/src/config/tree/sections/ssh.rs b/vendor/gix/src/config/tree/sections/ssh.rs new file mode 100644 index 000000000..600ee663b --- /dev/null +++ b/vendor/gix/src/config/tree/sections/ssh.rs @@ -0,0 +1,65 @@ +use crate::{ + config, + config::tree::{keys, Key, Section, Ssh}, +}; + +impl Ssh { + /// The `ssh.variant` key + pub const VARIANT: Variant = Variant::new_with_validate("variant", &config::Tree::SSH, validate::Variant) + .with_environment_override("GIT_SSH_VARIANT") + .with_deviation("We error if a variant is chosen that we don't know, as opposed to defaulting to 'ssh'"); +} + +/// The `ssh.variant` key. +pub type Variant = keys::Any<validate::Variant>; + +#[cfg(feature = "blocking-network-client")] +mod variant { + use std::borrow::Cow; + + use crate::{bstr::BStr, config, config::tree::ssh::Variant}; + + impl Variant { + pub fn try_into_variant( + &'static self, + value: Cow<'_, BStr>, + ) -> Result<Option<gix_protocol::transport::client::ssh::ProgramKind>, config::key::GenericErrorWithValue> + { + use gix_protocol::transport::client::ssh::ProgramKind; + + use crate::bstr::ByteSlice; + Ok(Some(match value.as_ref().as_bytes() { + b"auto" => return Ok(None), + b"ssh" => ProgramKind::Ssh, + b"plink" => ProgramKind::Plink, + b"putty" => ProgramKind::Putty, + b"tortoiseplink" => ProgramKind::TortoisePlink, + b"simple" => ProgramKind::Simple, + _ => return Err(config::key::GenericErrorWithValue::from_value(self, value.into_owned())), + })) + } + } +} + +impl Section for Ssh { + fn name(&self) -> &str { + "ssh" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::VARIANT] + } +} + +mod validate { + use crate::{bstr::BStr, config::tree::keys}; + + pub struct Variant; + impl keys::Validate for Variant { + fn validate(&self, _value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + #[cfg(feature = "blocking-network-client")] + super::Ssh::VARIANT.try_into_variant(_value.into())?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/url.rs b/vendor/gix/src/config/tree/sections/url.rs new file mode 100644 index 000000000..6a9c0bfdb --- /dev/null +++ b/vendor/gix/src/config/tree/sections/url.rs @@ -0,0 +1,25 @@ +use crate::{ + config, + config::tree::{keys, Key, Section, SubSectionRequirement, Url}, +}; + +const BASE_PARAMETER: Option<SubSectionRequirement> = Some(SubSectionRequirement::Parameter("base")); + +impl Url { + /// The `url.<base>.insteadOf` key + pub const INSTEAD_OF: keys::Any = + keys::Any::new("insteadOf", &config::Tree::URL).with_subsection_requirement(BASE_PARAMETER); + /// The `url.<base>.pushInsteadOf` key + pub const PUSH_INSTEAD_OF: keys::Any = + keys::Any::new("pushInsteadOf", &config::Tree::URL).with_subsection_requirement(BASE_PARAMETER); +} + +impl Section for Url { + fn name(&self) -> &str { + "url" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::INSTEAD_OF, &Self::PUSH_INSTEAD_OF] + } +} diff --git a/vendor/gix/src/config/tree/sections/user.rs b/vendor/gix/src/config/tree/sections/user.rs new file mode 100644 index 000000000..d1f4f7102 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/user.rs @@ -0,0 +1,22 @@ +use crate::{ + config, + config::tree::{gitoxide, keys, Key, Section, User}, +}; + +impl User { + /// The `user.name` key + pub const NAME: keys::Any = keys::Any::new("name", &config::Tree::USER); + /// The `user.email` key + pub const EMAIL: keys::Any = + keys::Any::new("email", &config::Tree::USER).with_fallback(&gitoxide::User::EMAIL_FALLBACK); +} + +impl Section for User { + fn name(&self) -> &str { + "user" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::NAME, &Self::EMAIL] + } +} |