diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/gix/src/config | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix/src/config')
-rw-r--r-- | vendor/gix/src/config/cache/access.rs | 134 | ||||
-rw-r--r-- | vendor/gix/src/config/cache/incubate.rs | 34 | ||||
-rw-r--r-- | vendor/gix/src/config/cache/init.rs | 71 | ||||
-rw-r--r-- | vendor/gix/src/config/cache/util.rs | 3 | ||||
-rw-r--r-- | vendor/gix/src/config/mod.rs | 45 | ||||
-rw-r--r-- | vendor/gix/src/config/tree/mod.rs | 9 | ||||
-rw-r--r-- | vendor/gix/src/config/tree/sections/clone.rs | 4 | ||||
-rw-r--r-- | vendor/gix/src/config/tree/sections/gitoxide.rs | 48 | ||||
-rw-r--r-- | vendor/gix/src/config/tree/sections/index.rs | 62 | ||||
-rw-r--r-- | vendor/gix/src/config/tree/sections/mod.rs | 5 |
10 files changed, 331 insertions, 84 deletions
diff --git a/vendor/gix/src/config/cache/access.rs b/vendor/gix/src/config/cache/access.rs index 8244eaf27..77324efe3 100644 --- a/vendor/gix/src/config/cache/access.rs +++ b/vendor/gix/src/config/cache/access.rs @@ -1,6 +1,7 @@ #![allow(clippy::result_large_err)] use std::{borrow::Cow, path::PathBuf, time::Duration}; +use gix_attributes::Source; use gix_lock::acquire::Fail; use crate::{ @@ -9,7 +10,7 @@ use crate::{ config::{ cache::util::{ApplyLeniency, ApplyLeniencyDefault}, checkout_options, - tree::{Checkout, Core, Key}, + tree::{gitoxide, Checkout, Core, Key}, Cache, }, remote, @@ -137,7 +138,7 @@ impl Cache { pub(crate) fn checkout_options( &self, git_dir: &std::path::Path, - ) -> Result<gix_worktree::index::checkout::Options, checkout_options::Error> { + ) -> Result<gix_worktree::checkout::Options, checkout_options::Error> { fn boolean( me: &Cache, full_key: &str, @@ -154,63 +155,118 @@ impl Cache { .unwrap_or(default)) } - fn assemble_attribute_globals( - me: &Cache, - _git_dir: &std::path::Path, - ) -> Result<gix_attributes::MatchGroup, checkout_options::Error> { - let _attributes_file = match me - .trusted_file_path("core", None, Core::ATTRIBUTES_FILE.name) - .transpose()? - { - Some(attributes) => Some(attributes.into_owned()), - None => me.xdg_config_path("attributes").ok().flatten(), - }; - // TODO: implement gix_attributes::MatchGroup::<gix_attributes::Attributes>::from_git_dir(), similar to what's done for `Ignore`. - Ok(Default::default()) - } - let thread_limit = self.apply_leniency( self.resolved .integer_filter_by_key("checkout.workers", &mut self.filter_config_section.clone()) .map(|value| Checkout::WORKERS.try_from_workers(value)), )?; - Ok(gix_worktree::index::checkout::Options { - fs: gix_worktree::fs::Capabilities { - precompose_unicode: boolean(self, "core.precomposeUnicode", &Core::PRECOMPOSE_UNICODE, false)?, - ignore_case: boolean(self, "core.ignoreCase", &Core::IGNORE_CASE, false)?, - executable_bit: boolean(self, "core.fileMode", &Core::FILE_MODE, true)?, - symlink: boolean(self, "core.symlinks", &Core::SYMLINKS, true)?, - }, + let capabilities = gix_fs::Capabilities { + precompose_unicode: boolean(self, "core.precomposeUnicode", &Core::PRECOMPOSE_UNICODE, false)?, + ignore_case: boolean(self, "core.ignoreCase", &Core::IGNORE_CASE, false)?, + executable_bit: boolean(self, "core.fileMode", &Core::FILE_MODE, true)?, + symlink: boolean(self, "core.symlinks", &Core::SYMLINKS, true)?, + }; + Ok(gix_worktree::checkout::Options { + attributes: self + .assemble_attribute_globals( + git_dir, + gix_worktree::cache::state::attributes::Source::IdMappingThenWorktree, + self.attributes, + )? + .0, + fs: capabilities, thread_limit, destination_is_initially_empty: false, overwrite_existing: false, keep_going: false, - trust_ctime: boolean(self, "core.trustCTime", &Core::TRUST_C_TIME, true)?, - check_stat: self - .apply_leniency( - self.resolved - .string("core", None, "checkStat") - .map(|v| Core::CHECK_STAT.try_into_checkstat(v)), - )? - .unwrap_or(true), - attribute_globals: assemble_attribute_globals(self, git_dir)?, + stat_options: gix_index::entry::stat::Options { + trust_ctime: boolean(self, "core.trustCTime", &Core::TRUST_C_TIME, true)?, + use_nsec: boolean(self, "gitoxide.core.useNsec", &gitoxide::Core::USE_NSEC, false)?, + use_stdev: boolean(self, "gitoxide.core.useStdev", &gitoxide::Core::USE_STDEV, false)?, + check_stat: self + .apply_leniency( + self.resolved + .string("core", None, "checkStat") + .map(|v| Core::CHECK_STAT.try_into_checkstat(v)), + )? + .unwrap_or(true), + }, }) } + + pub(crate) fn assemble_exclude_globals( + &self, + git_dir: &std::path::Path, + overrides: Option<gix_ignore::Search>, + source: gix_worktree::cache::state::ignore::Source, + buf: &mut Vec<u8>, + ) -> Result<gix_worktree::cache::state::Ignore, config::exclude_stack::Error> { + let excludes_file = match self.excludes_file().transpose()? { + Some(user_path) => Some(user_path), + None => self.xdg_config_path("ignore")?, + }; + Ok(gix_worktree::cache::state::Ignore::new( + overrides.unwrap_or_default(), + gix_ignore::Search::from_git_dir(git_dir, excludes_file, buf)?, + None, + source, + )) + } + // TODO: at least one test, maybe related to core.attributesFile configuration. + pub(crate) fn assemble_attribute_globals( + &self, + git_dir: &std::path::Path, + source: gix_worktree::cache::state::attributes::Source, + attributes: crate::open::permissions::Attributes, + ) -> Result<(gix_worktree::cache::state::Attributes, Vec<u8>), config::attribute_stack::Error> { + let configured_or_user_attributes = match self + .trusted_file_path("core", None, Core::ATTRIBUTES_FILE.name) + .transpose()? + { + Some(attributes) => Some(attributes), + None => { + if attributes.git { + self.xdg_config_path("attributes").ok().flatten().map(Cow::Owned) + } else { + None + } + } + }; + let attribute_files = [gix_attributes::Source::GitInstallation, gix_attributes::Source::System] + .into_iter() + .filter(|source| match source { + Source::GitInstallation => attributes.git_binary, + Source::System => attributes.system, + Source::Git | Source::Local => unreachable!("we don't offer turning this off right now"), + }) + .filter_map(|source| source.storage_location(&mut Self::make_source_env(self.environment))) + .chain(configured_or_user_attributes); + let info_attributes_path = git_dir.join("info").join("attributes"); + let mut buf = Vec::new(); + let mut collection = gix_attributes::search::MetadataCollection::default(); + let res = gix_worktree::cache::state::Attributes::new( + gix_attributes::Search::new_globals(attribute_files, &mut buf, &mut collection)?, + Some(info_attributes_path), + source, + collection, + ); + Ok((res, buf)) + } + pub(crate) fn xdg_config_path( &self, resource_file_name: &str, ) -> Result<Option<PathBuf>, gix_sec::permission::Error<PathBuf>> { std::env::var_os("XDG_CONFIG_HOME") - .map(|path| (PathBuf::from(path), &self.xdg_config_home_env)) + .map(|path| (PathBuf::from(path), &self.environment.xdg_config_home)) .or_else(|| { - std::env::var_os("HOME").map(|path| { + gix_path::env::home_dir().map(|mut p| { ( { - let mut p = PathBuf::from(path); p.push(".config"); p }, - &self.home_env, + &self.environment.home, ) }) }) @@ -226,8 +282,6 @@ impl Cache { /// We never fail for here even if the permission is set to deny as we `gix-config` will fail later /// if it actually wants to use the home directory - we don't want to fail prematurely. pub(crate) fn home_dir(&self) -> Option<PathBuf> { - std::env::var_os("HOME") - .map(PathBuf::from) - .and_then(|path| self.home_env.check_opt(path)) + gix_path::env::home_dir().and_then(|path| self.environment.home.check_opt(path)) } } diff --git a/vendor/gix/src/config/cache/incubate.rs b/vendor/gix/src/config/cache/incubate.rs index 047f2132b..44c537b50 100644 --- a/vendor/gix/src/config/cache/incubate.rs +++ b/vendor/gix/src/config/cache/incubate.rs @@ -30,6 +30,7 @@ impl StageOne { gix_config::Source::Local, git_dir_trust, lossy, + lenient, )?; // Note that we assume the repo is bare by default unless we are told otherwise. This is relevant if @@ -64,6 +65,7 @@ impl StageOne { gix_config::Source::Worktree, git_dir_trust, lossy, + lenient, )?; config.append(worktree_config); }; @@ -86,24 +88,48 @@ fn load_config( source: gix_config::Source, git_dir_trust: gix_sec::Trust, lossy: Option<bool>, + lenient: bool, ) -> Result<gix_config::File<'static>, Error> { - buf.clear(); let metadata = gix_config::file::Metadata::from(source) .at(&config_path) .with(git_dir_trust); let mut file = match std::fs::File::open(&config_path) { Ok(f) => f, Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(gix_config::File::new(metadata)), - Err(err) => return Err(err.into()), + Err(err) => { + let err = Error::Io { + source: err, + path: config_path, + }; + if lenient { + log::warn!("ignoring: {err:#?}"); + return Ok(gix_config::File::new(metadata)); + } else { + return Err(err); + } + } + }; + + buf.clear(); + if let Err(err) = std::io::copy(&mut file, buf) { + let err = Error::Io { + source: err, + path: config_path, + }; + if lenient { + log::warn!("ignoring: {err:#?}"); + buf.clear(); + } else { + return Err(err); + } }; - std::io::copy(&mut file, buf)?; let config = gix_config::File::from_bytes_owned( buf, metadata, gix_config::file::init::Options { includes: gix_config::file::includes::Options::no_follow(), - ..util::base_options(lossy) + ..util::base_options(lossy, lenient) }, )?; diff --git a/vendor/gix/src/config/cache/init.rs b/vendor/gix/src/config/cache/init.rs index dc76f78bb..ee20e0354 100644 --- a/vendor/gix/src/config/cache/init.rs +++ b/vendor/gix/src/config/cache/init.rs @@ -1,5 +1,5 @@ #![allow(clippy::result_large_err)] -use std::borrow::Cow; +use std::{borrow::Cow, ffi::OsString}; use gix_sec::Permission; @@ -12,7 +12,7 @@ use crate::{ tree::{gitoxide, Core, Http}, Cache, }, - repository, + open, }; /// Initialization @@ -32,23 +32,24 @@ impl Cache { filter_config_section: fn(&gix_config::file::Metadata) -> bool, git_install_dir: Option<&std::path::Path>, home: Option<&std::path::Path>, - repository::permissions::Environment { + environment @ open::permissions::Environment { git_prefix, - home: home_env, - xdg_config_home: xdg_config_home_env, ssh_prefix: _, + xdg_config_home: _, + home: _, http_transport, identity, objects, - }: repository::permissions::Environment, - repository::permissions::Config { + }: open::permissions::Environment, + attributes: open::permissions::Attributes, + open::permissions::Config { git_binary: use_installation, system: use_system, git: use_git, user: use_user, env: use_env, includes: use_includes, - }: repository::permissions::Config, + }: open::permissions::Config, lenient_config: bool, api_config_overrides: &[BString], cli_config_overrides: &[BString], @@ -65,12 +66,10 @@ impl Cache { } else { gix_config::file::includes::Options::no_follow() }, - ..util::base_options(lossy) + ..util::base_options(lossy, lenient_config) }; let config = { - let home_env = &home_env; - let xdg_config_home_env = &xdg_config_home_env; let git_prefix = &git_prefix; let metas = [ gix_config::source::Kind::GitInstallation, @@ -88,15 +87,7 @@ impl Cache { _ => {} } source - .storage_location(&mut |name| { - match name { - git_ if git_.starts_with("GIT_") => Some(git_prefix), - "XDG_CONFIG_HOME" => Some(xdg_config_home_env), - "HOME" => Some(home_env), - _ => None, - } - .and_then(|perm| perm.check_opt(name).and_then(std::env::var_os)) - }) + .storage_location(&mut Self::make_source_env(environment)) .map(|p| (source, p.into_owned())) }) .map(|(source, path)| gix_config::file::Metadata { @@ -118,7 +109,7 @@ impl Cache { ) .map_err(|err| match err { gix_config::file::init::from_paths::Error::Init(err) => Error::from(err), - gix_config::file::init::from_paths::Error::Io(err) => err.into(), + gix_config::file::init::from_paths::Error::Io { source, path } => Error::Io { source, path }, })? .unwrap_or_default(); @@ -175,9 +166,9 @@ impl Cache { ignore_case, hex_len, filter_config_section, - xdg_config_home_env, - home_env, + environment, lenient_config, + attributes, user_agent: Default::default(), personas: Default::default(), url_rewrite: Default::default(), @@ -240,6 +231,31 @@ impl Cache { Ok(()) } + + pub(crate) fn make_source_env( + crate::open::permissions::Environment { + xdg_config_home, + git_prefix, + home, + .. + }: open::permissions::Environment, + ) -> impl FnMut(&str) -> Option<OsString> { + move |name| { + match name { + git_ if git_.starts_with("GIT_") => Some(git_prefix), + "XDG_CONFIG_HOME" => Some(xdg_config_home), + "HOME" => { + return if home.is_allowed() { + gix_path::env::home_dir().map(Into::into) + } else { + None + } + } + _ => None, + } + .and_then(|perm| perm.check_opt(name).and_then(gix_path::env::var)) + } + } } impl crate::Repository { @@ -349,6 +365,15 @@ fn apply_environment_overrides( ), ( "gitoxide", + Some(Cow::Borrowed("core".into())), + git_prefix, + &[{ + let key = &gitoxide::Core::SHALLOW_FILE; + (env(key), key.name) + }], + ), + ( + "gitoxide", Some(Cow::Borrowed("author".into())), identity, &[ diff --git a/vendor/gix/src/config/cache/util.rs b/vendor/gix/src/config/cache/util.rs index c12f850e6..d5a0a4acb 100644 --- a/vendor/gix/src/config/cache/util.rs +++ b/vendor/gix/src/config/cache/util.rs @@ -17,9 +17,10 @@ pub(crate) fn interpolate_context<'a>( } } -pub(crate) fn base_options(lossy: Option<bool>) -> gix_config::file::init::Options<'static> { +pub(crate) fn base_options(lossy: Option<bool>, lenient: bool) -> gix_config::file::init::Options<'static> { gix_config::file::init::Options { lossy: lossy.unwrap_or(!cfg!(debug_assertions)), + ignore_io_errors: lenient, ..Default::default() } } diff --git a/vendor/gix/src/config/mod.rs b/vendor/gix/src/config/mod.rs index 1e2566777..5da569605 100644 --- a/vendor/gix/src/config/mod.rs +++ b/vendor/gix/src/config/mod.rs @@ -62,8 +62,11 @@ pub enum Error { UnsupportedObjectFormat { name: BString }, #[error(transparent)] CoreAbbrev(#[from] abbrev::Error), - #[error("Could not read configuration file")] - Io(#[from] std::io::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)] @@ -110,6 +113,36 @@ pub mod checkout_options { ConfigBoolean(#[from] super::boolean::Error), #[error(transparent)] CheckoutWorkers(#[from] super::checkout::workers::Error), + #[error(transparent)] + Attributes(#[from] super::attribute_stack::Error), + } +} + +/// +pub mod exclude_stack { + use std::path::PathBuf; + + /// The error produced when setting up a stack to query `gitignore` information. + #[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), + } +} + +/// +pub mod attribute_stack { + /// The error produced when setting up the attribute stack to query `gitattributes`. + #[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), } @@ -247,7 +280,7 @@ pub mod checkout { pub mod workers { use crate::config; - /// The error produced when failing to parse the the `checkout.workers` key. + /// The error produced when failing to parse the `checkout.workers` key. pub type Error = config::key::Error<gix_config::value::Error, 'n', 'd'>; } } @@ -446,9 +479,7 @@ pub(crate) struct Cache { /// 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, + attributes: crate::open::permissions::Attributes, + environment: crate::open::permissions::Environment, // TODO: make core.precomposeUnicode available as well. } diff --git a/vendor/gix/src/config/tree/mod.rs b/vendor/gix/src/config/tree/mod.rs index fd769f3ed..b378b8c49 100644 --- a/vendor/gix/src/config/tree/mod.rs +++ b/vendor/gix/src/config/tree/mod.rs @@ -38,6 +38,8 @@ pub(crate) mod root { pub const GITOXIDE: sections::Gitoxide = sections::Gitoxide; /// The `http` section. pub const HTTP: sections::Http = sections::Http; + /// The `index` section. + pub const INDEX: sections::Index = sections::Index; /// The `init` section. pub const INIT: sections::Init = sections::Init; /// The `pack` section. @@ -69,6 +71,7 @@ pub(crate) mod root { &Self::EXTENSIONS, &Self::GITOXIDE, &Self::HTTP, + &Self::INDEX, &Self::INIT, &Self::PACK, &Self::PROTOCOL, @@ -84,9 +87,9 @@ pub(crate) mod root { mod sections; pub use sections::{ - branch, checkout, core, credential, diff, extensions, gitoxide, http, protocol, remote, ssh, Author, Branch, - Checkout, Clone, Committer, Core, Credential, Diff, Extensions, Gitoxide, Http, Init, Pack, Protocol, Remote, Safe, - Ssh, Url, User, + branch, checkout, core, credential, diff, extensions, gitoxide, http, index, protocol, remote, ssh, Author, Branch, + Checkout, Clone, Committer, Core, Credential, Diff, Extensions, Gitoxide, Http, Index, Init, Pack, Protocol, + Remote, Safe, Ssh, Url, User, }; /// Generic value implementations for static instantiation. diff --git a/vendor/gix/src/config/tree/sections/clone.rs b/vendor/gix/src/config/tree/sections/clone.rs index 616185a0b..6cb274e7d 100644 --- a/vendor/gix/src/config/tree/sections/clone.rs +++ b/vendor/gix/src/config/tree/sections/clone.rs @@ -7,6 +7,8 @@ impl Clone { /// The `clone.defaultRemoteName` key. pub const DEFAULT_REMOTE_NAME: keys::RemoteName = keys::RemoteName::new_remote_name("defaultRemoteName", &config::Tree::CLONE); + /// The `clone.rejectShallow` key. + pub const REJECT_SHALLOW: keys::Boolean = keys::Boolean::new_boolean("rejectShallow", &config::Tree::CLONE); } impl Section for Clone { @@ -15,6 +17,6 @@ impl Section for Clone { } fn keys(&self) -> &[&dyn Key] { - &[&Self::DEFAULT_REMOTE_NAME] + &[&Self::DEFAULT_REMOTE_NAME, &Self::REJECT_SHALLOW] } } diff --git a/vendor/gix/src/config/tree/sections/gitoxide.rs b/vendor/gix/src/config/tree/sections/gitoxide.rs index 8c3defd0b..7d60f1287 100644 --- a/vendor/gix/src/config/tree/sections/gitoxide.rs +++ b/vendor/gix/src/config/tree/sections/gitoxide.rs @@ -1,10 +1,15 @@ -use crate::config::tree::{keys, Gitoxide, Key, Section}; +use crate::{ + config, + 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.core` section. + pub const CORE: Core = Core; /// The `gitoxide.commit` section. pub const COMMIT: Commit = Commit; /// The `gitoxide.committer` section. @@ -39,6 +44,7 @@ impl Section for Gitoxide { &[ &Self::ALLOW, &Self::AUTHOR, + &Self::CORE, &Self::COMMIT, &Self::COMMITTER, &Self::HTTP, @@ -56,6 +62,41 @@ mod subsections { Tree, }; + /// The `Core` sub-section. + #[derive(Copy, Clone, Default)] + pub struct Core; + + impl Core { + /// The `gitoxide.core.useNsec` key. + pub const USE_NSEC: keys::Boolean = keys::Boolean::new_boolean("useNsec", &Gitoxide::CORE) + .with_note("A runtime version of the USE_NSEC build flag."); + + /// The `gitoxide.core.useStdev` key. + pub const USE_STDEV: keys::Boolean = keys::Boolean::new_boolean("useStdev", &Gitoxide::CORE) + .with_note("A runtime version of the USE_STDEV build flag."); + + /// The `gitoxide.core.shallowFile` key. + pub const SHALLOW_FILE: keys::Path = keys::Path::new_path("shallowFile", &Gitoxide::CORE) + .with_environment_override("GIT_SHALLOW_FILE") + .with_deviation( + "relative file paths will always be made relative to the git-common-dir, whereas `git` keeps them as is.", + ); + } + + impl Section for Core { + fn name(&self) -> &str { + "core" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::USE_NSEC, &Self::USE_STDEV, &Self::SHALLOW_FILE] + } + + fn parent(&self) -> Option<&dyn Section> { + Some(&Tree::GITOXIDE) + } + } + /// The `Http` sub-section. #[derive(Copy, Clone, Default)] pub struct Http; @@ -341,6 +382,7 @@ mod subsections { } } } +pub use subsections::{Allow, Author, Commit, Committer, Core, Http, Https, Objects, Ssh, User}; pub mod validate { use std::error::Error; @@ -357,7 +399,3 @@ pub mod validate { } } } - -pub use subsections::{Allow, Author, Commit, Committer, Http, Https, Objects, Ssh, User}; - -use crate::config; diff --git a/vendor/gix/src/config/tree/sections/index.rs b/vendor/gix/src/config/tree/sections/index.rs new file mode 100644 index 000000000..d03322247 --- /dev/null +++ b/vendor/gix/src/config/tree/sections/index.rs @@ -0,0 +1,62 @@ +use crate::{ + config, + config::tree::{keys, Index, Key, Section}, +}; + +impl Index { + /// The `index.threads` key. + pub const THREADS: IndexThreads = + IndexThreads::new_with_validate("threads", &config::Tree::INDEX, validate::IndexThreads); +} + +/// The `index.threads` key. +pub type IndexThreads = keys::Any<validate::IndexThreads>; + +mod index_threads { + use crate::bstr::BStr; + use crate::config; + use crate::config::key::GenericErrorWithValue; + use crate::config::tree::index::IndexThreads; + use std::borrow::Cow; + + impl IndexThreads { + /// Parse `value` into the amount of threads to use, with `1` being single-threaded, or `0` indicating + /// to select the amount of threads, with any other number being the specific amount of threads to use. + pub fn try_into_index_threads( + &'static self, + value: Cow<'_, BStr>, + ) -> Result<usize, config::key::GenericErrorWithValue> { + gix_config::Integer::try_from(value.as_ref()) + .ok() + .and_then(|i| i.to_decimal().and_then(|i| i.try_into().ok())) + .or_else(|| { + gix_config::Boolean::try_from(value.as_ref()) + .ok() + .map(|b| if b.0 { 0 } else { 1 }) + }) + .ok_or_else(|| GenericErrorWithValue::from_value(self, value.into_owned())) + } + } +} + +impl Section for Index { + fn name(&self) -> &str { + "index" + } + + fn keys(&self) -> &[&dyn Key] { + &[&Self::THREADS] + } +} + +mod validate { + use crate::{bstr::BStr, config::tree::keys}; + + pub struct IndexThreads; + impl keys::Validate for IndexThreads { + fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { + super::Index::THREADS.try_into_index_threads(value.into())?; + Ok(()) + } + } +} diff --git a/vendor/gix/src/config/tree/sections/mod.rs b/vendor/gix/src/config/tree/sections/mod.rs index fb9b50786..9f0a50c93 100644 --- a/vendor/gix/src/config/tree/sections/mod.rs +++ b/vendor/gix/src/config/tree/sections/mod.rs @@ -55,6 +55,11 @@ pub mod gitoxide; pub struct Http; pub mod http; +/// The `index` top-level section. +#[derive(Copy, Clone, Default)] +pub struct Index; +pub mod index; + /// The `init` top-level section. #[derive(Copy, Clone, Default)] pub struct Init; |