summaryrefslogtreecommitdiffstats
path: root/vendor/gix/src/config
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix/src/config')
-rw-r--r--vendor/gix/src/config/cache/access.rs200
-rw-r--r--vendor/gix/src/config/cache/incubate.rs4
-rw-r--r--vendor/gix/src/config/cache/init.rs58
-rw-r--r--vendor/gix/src/config/cache/util.rs36
-rw-r--r--vendor/gix/src/config/mod.rs60
-rw-r--r--vendor/gix/src/config/overrides.rs12
-rw-r--r--vendor/gix/src/config/snapshot/access.rs54
-rw-r--r--vendor/gix/src/config/snapshot/credential_helpers.rs4
-rw-r--r--vendor/gix/src/config/snapshot/mod.rs1
-rw-r--r--vendor/gix/src/config/tree/keys.rs2
-rw-r--r--vendor/gix/src/config/tree/mod.rs8
-rw-r--r--vendor/gix/src/config/tree/sections/core.rs249
-rw-r--r--vendor/gix/src/config/tree/sections/diff.rs21
-rw-r--r--vendor/gix/src/config/tree/sections/fetch.rs81
-rw-r--r--vendor/gix/src/config/tree/sections/gitoxide.rs62
-rw-r--r--vendor/gix/src/config/tree/sections/index.rs5
-rw-r--r--vendor/gix/src/config/tree/sections/mod.rs2
-rw-r--r--vendor/gix/src/config/tree/sections/protocol.rs2
18 files changed, 725 insertions, 136 deletions
diff --git a/vendor/gix/src/config/cache/access.rs b/vendor/gix/src/config/cache/access.rs
index cea56f973..352bc9712 100644
--- a/vendor/gix/src/config/cache/access.rs
+++ b/vendor/gix/src/config/cache/access.rs
@@ -1,16 +1,15 @@
#![allow(clippy::result_large_err)]
use std::{borrow::Cow, path::PathBuf, time::Duration};
-use gix_attributes::Source;
use gix_lock::acquire::Fail;
use crate::{
bstr::BStr,
config,
config::{
- cache::util::{ApplyLeniency, ApplyLeniencyDefault},
- checkout_options,
- tree::{gitoxide, Checkout, Core, Key},
+ boolean,
+ cache::util::{ApplyLeniency, ApplyLeniencyDefaultValue},
+ tree::{Core, Key},
Cache,
},
remote,
@@ -19,7 +18,9 @@ use crate::{
/// Access
impl Cache {
+ #[cfg(feature = "blob-diff")]
pub(crate) fn diff_algorithm(&self) -> Result<gix_diff::blob::Algorithm, config::diff::algorithm::Error> {
+ use crate::config::cache::util::ApplyLeniencyDefault;
use crate::config::diff::algorithm::Error;
self.diff_algorithm
.get_or_try_init(|| {
@@ -69,6 +70,18 @@ impl Cache {
.get_or_try_init(|| remote::url::SchemePermission::from_config(&self.resolved, self.filter_config_section))
}
+ pub(crate) fn may_use_commit_graph(&self) -> Result<bool, config::boolean::Error> {
+ const DEFAULT: bool = true;
+ self.resolved
+ .boolean_by_key("core.commitGraph")
+ .map_or(Ok(DEFAULT), |res| {
+ Core::COMMIT_GRAPH
+ .enrich_error(res)
+ .with_lenient_default_value(self.lenient_config, DEFAULT)
+ })
+ }
+
+ #[cfg(feature = "blob-diff")]
pub(crate) fn diff_renames(
&self,
) -> Result<Option<crate::object::tree::diff::Rewrites>, crate::object::tree::diff::rewrites::Error> {
@@ -100,9 +113,10 @@ impl Cache {
}
/// The path to the user-level excludes file to ignore certain files in the worktree.
+ #[cfg(feature = "excludes")]
pub(crate) fn excludes_file(&self) -> Option<Result<PathBuf, gix_config::path::interpolate::Error>> {
self.trusted_file_path("core", None, Core::EXCLUDES_FILE.name)?
- .map(|p| p.into_owned())
+ .map(std::borrow::Cow::into_owned)
.into()
}
@@ -123,7 +137,7 @@ impl Cache {
let install_dir = crate::path::install_dir().ok();
let home = self.home_dir();
- let ctx = crate::config::cache::interpolate_context(install_dir.as_deref(), home.as_deref());
+ let ctx = config::cache::interpolate_context(install_dir.as_deref(), home.as_deref());
Some(path.interpolate(ctx))
}
@@ -131,80 +145,108 @@ impl Cache {
res.transpose().with_leniency(self.lenient_config)
}
+ pub(crate) fn fs_capabilities(&self) -> Result<gix_fs::Capabilities, boolean::Error> {
+ Ok(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)?,
+ })
+ }
+
+ #[cfg(feature = "index")]
+ pub(crate) fn stat_options(&self) -> Result<gix_index::entry::stat::Options, config::stat_options::Error> {
+ use crate::config::tree::gitoxide;
+ Ok(gix_index::entry::stat::Options {
+ trust_ctime: boolean(
+ self,
+ "core.trustCTime",
+ &Core::TRUST_C_TIME,
+ // For now, on MacOS it's known to not be trust-worthy at least with the Rust STDlib, being 2s off
+ !cfg!(target_os = "macos"),
+ )?,
+ 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),
+ })
+ }
+
/// Collect everything needed to checkout files into a worktree.
/// Note that some of the options being returned will be defaulted so safe settings, the caller might have to override them
/// depending on the use-case.
+ #[cfg(feature = "worktree-mutation")]
pub(crate) fn checkout_options(
&self,
- git_dir: &std::path::Path,
- ) -> Result<gix_worktree::checkout::Options, checkout_options::Error> {
- fn boolean(
- me: &Cache,
- full_key: &str,
- key: &'static config::tree::keys::Boolean,
- default: bool,
- ) -> Result<bool, checkout_options::Error> {
- debug_assert_eq!(
- full_key,
- key.logical_name(),
- "BUG: key name and hardcoded name must match"
- );
- Ok(me
- .apply_leniency(me.resolved.boolean_by_key(full_key).map(|v| key.enrich_error(v)))?
- .unwrap_or(default))
- }
-
+ repo: &crate::Repository,
+ attributes_source: gix_worktree::stack::state::attributes::Source,
+ ) -> Result<gix_worktree_state::checkout::Options, config::checkout_options::Error> {
+ use crate::config::tree::gitoxide;
+ let git_dir = repo.git_dir();
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)),
+ .map(|value| crate::config::tree::Checkout::WORKERS.try_from_workers(value)),
)?;
- 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)?,
+ let capabilities = self.fs_capabilities()?;
+ let filters = {
+ let collection = Default::default();
+ let mut filters = gix_filter::Pipeline::new(&collection, crate::filter::Pipeline::options(repo)?);
+ if let Ok(mut head) = repo.head() {
+ let ctx = filters.driver_context_mut();
+ ctx.ref_name = head.referent_name().map(|name| name.as_bstr().to_owned());
+ ctx.treeish = head.peel_to_commit_in_place().ok().map(|commit| commit.id);
+ }
+ filters
+ };
+ let filter_process_delay = if boolean(
+ self,
+ "gitoxide.core.filterProcessDelay",
+ &gitoxide::Core::FILTER_PROCESS_DELAY,
+ true,
+ )? {
+ gix_filter::driver::apply::Delay::Allow
+ } else {
+ gix_filter::driver::apply::Delay::Forbid
};
- Ok(gix_worktree::checkout::Options {
+ Ok(gix_worktree_state::checkout::Options {
+ filter_process_delay,
+ filters,
attributes: self
- .assemble_attribute_globals(
- git_dir,
- gix_worktree::cache::state::attributes::Source::IdMappingThenWorktree,
- self.attributes,
- )?
+ .assemble_attribute_globals(git_dir, attributes_source, self.attributes)?
.0,
fs: capabilities,
thread_limit,
destination_is_initially_empty: false,
overwrite_existing: false,
keep_going: false,
- 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),
- },
+ stat_options: self.stat_options().map_err(|err| match err {
+ config::stat_options::Error::ConfigCheckStat(err) => {
+ config::checkout_options::Error::ConfigCheckStat(err)
+ }
+ config::stat_options::Error::ConfigBoolean(err) => config::checkout_options::Error::ConfigBoolean(err),
+ })?,
})
}
+ #[cfg(feature = "excludes")]
pub(crate) fn assemble_exclude_globals(
&self,
git_dir: &std::path::Path,
overrides: Option<gix_ignore::Search>,
- source: gix_worktree::cache::state::ignore::Source,
+ source: gix_worktree::stack::state::ignore::Source,
buf: &mut Vec<u8>,
- ) -> Result<gix_worktree::cache::state::Ignore, config::exclude_stack::Error> {
+ ) -> Result<gix_worktree::stack::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(
+ Ok(gix_worktree::stack::state::Ignore::new(
overrides.unwrap_or_default(),
gix_ignore::Search::from_git_dir(git_dir, excludes_file, buf)?,
None,
@@ -212,12 +254,14 @@ impl Cache {
))
}
// TODO: at least one test, maybe related to core.attributesFile configuration.
+ #[cfg(feature = "attributes")]
pub(crate) fn assemble_attribute_globals(
&self,
git_dir: &std::path::Path,
- source: gix_worktree::cache::state::attributes::Source,
+ source: gix_worktree::stack::state::attributes::Source,
attributes: crate::open::permissions::Attributes,
- ) -> Result<(gix_worktree::cache::state::Attributes, Vec<u8>), config::attribute_stack::Error> {
+ ) -> Result<(gix_worktree::stack::state::Attributes, Vec<u8>), config::attribute_stack::Error> {
+ use gix_attributes::Source;
let configured_or_user_attributes = match self
.trusted_file_path("core", None, Core::ATTRIBUTES_FILE.name)
.transpose()?
@@ -243,15 +287,45 @@ impl Cache {
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(
+ let state = gix_worktree::stack::state::Attributes::new(
gix_attributes::Search::new_globals(attribute_files, &mut buf, &mut collection)?,
Some(info_attributes_path),
source,
collection,
);
- Ok((res, buf))
+ Ok((state, buf))
}
+ #[cfg(feature = "attributes")]
+ pub(crate) fn pathspec_defaults(
+ &self,
+ ) -> Result<gix_pathspec::Defaults, gix_pathspec::defaults::from_environment::Error> {
+ use crate::config::tree::gitoxide;
+ let res = gix_pathspec::Defaults::from_environment(&mut |name| {
+ let key = [
+ &gitoxide::Pathspec::ICASE,
+ &gitoxide::Pathspec::GLOB,
+ &gitoxide::Pathspec::NOGLOB,
+ &gitoxide::Pathspec::LITERAL,
+ ]
+ .iter()
+ .find_map(|key| (key.environment_override().expect("set") == name).then_some(key))
+ .expect("we must know all possible input variable names");
+
+ let val = self
+ .resolved
+ .string("gitoxide", Some("pathspec".into()), key.name())
+ .map(gix_path::from_bstr)?;
+ Some(val.into_owned().into())
+ });
+ if res.is_err() && self.lenient_config {
+ Ok(gix_pathspec::Defaults::default())
+ } else {
+ res
+ }
+ }
+
+ #[cfg(any(feature = "attributes", feature = "excludes"))]
pub(crate) fn xdg_config_path(
&self,
resource_file_name: &str,
@@ -284,3 +358,19 @@ impl Cache {
gix_path::env::home_dir().and_then(|path| self.environment.home.check_opt(path))
}
}
+
+fn boolean(
+ me: &Cache,
+ full_key: &str,
+ key: &'static config::tree::keys::Boolean,
+ default: bool,
+) -> Result<bool, boolean::Error> {
+ debug_assert_eq!(
+ full_key,
+ key.logical_name(),
+ "BUG: key name and hardcoded name must match"
+ );
+ Ok(me
+ .apply_leniency(me.resolved.boolean_by_key(full_key).map(|v| key.enrich_error(v)))?
+ .unwrap_or(default))
+}
diff --git a/vendor/gix/src/config/cache/incubate.rs b/vendor/gix/src/config/cache/incubate.rs
index 44c537b50..cf7c5dcdf 100644
--- a/vendor/gix/src/config/cache/incubate.rs
+++ b/vendor/gix/src/config/cache/incubate.rs
@@ -102,7 +102,7 @@ fn load_config(
path: config_path,
};
if lenient {
- log::warn!("ignoring: {err:#?}");
+ gix_trace::warn!("ignoring: {err:#?}");
return Ok(gix_config::File::new(metadata));
} else {
return Err(err);
@@ -117,7 +117,7 @@ fn load_config(
path: config_path,
};
if lenient {
- log::warn!("ignoring: {err:#?}");
+ gix_trace::warn!("ignoring: {err:#?}");
buf.clear();
} else {
return Err(err);
diff --git a/vendor/gix/src/config/cache/init.rs b/vendor/gix/src/config/cache/init.rs
index 6fcbcc4ec..3c482b154 100644
--- a/vendor/gix/src/config/cache/init.rs
+++ b/vendor/gix/src/config/cache/init.rs
@@ -13,6 +13,7 @@ use crate::{
Cache,
},
open,
+ repository::init::setup_objects,
};
/// Initialization
@@ -71,7 +72,7 @@ impl Cache {
let config = {
let git_prefix = &git_prefix;
- let metas = [
+ let mut metas = [
gix_config::source::Kind::GitInstallation,
gix_config::source::Kind::System,
gix_config::source::Kind::Global,
@@ -99,7 +100,7 @@ impl Cache {
let err_on_nonexisting_paths = false;
let mut globals = gix_config::File::from_paths_metadata_buf(
- metas,
+ &mut metas,
&mut buf,
err_on_nonexisting_paths,
gix_config::file::init::Options {
@@ -150,6 +151,7 @@ impl Cache {
true,
lenient_config,
)?;
+ #[cfg(feature = "revision")]
let object_kind_hint = util::disambiguate_hint(&config, lenient_config)?;
let (static_pack_cache_limit_bytes, pack_cache_bytes, object_cache_bytes) =
util::parse_object_caches(&config, lenient_config, filter_config_section)?;
@@ -158,6 +160,7 @@ impl Cache {
resolved: config.into(),
use_multi_pack_index,
object_hash,
+ #[cfg(feature = "revision")]
object_kind_hint,
static_pack_cache_limit_bytes,
pack_cache_bytes,
@@ -173,9 +176,11 @@ impl Cache {
user_agent: Default::default(),
personas: Default::default(),
url_rewrite: Default::default(),
+ #[cfg(feature = "blob-diff")]
diff_renames: Default::default(),
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
url_scheme: Default::default(),
+ #[cfg(feature = "blob-diff")]
diff_algorithm: Default::default(),
})
}
@@ -210,19 +215,26 @@ impl Cache {
false,
self.lenient_config,
)?;
- let object_kind_hint = util::disambiguate_hint(config, self.lenient_config)?;
+
+ #[cfg(feature = "revision")]
+ {
+ let object_kind_hint = util::disambiguate_hint(config, self.lenient_config)?;
+ self.object_kind_hint = object_kind_hint;
+ }
let reflog = util::query_refupdates(config, self.lenient_config)?;
self.hex_len = hex_len;
self.ignore_case = ignore_case;
- self.object_kind_hint = object_kind_hint;
self.reflog = reflog;
self.user_agent = Default::default();
self.personas = Default::default();
self.url_rewrite = Default::default();
- self.diff_renames = Default::default();
- self.diff_algorithm = Default::default();
+ #[cfg(feature = "blob-diff")]
+ {
+ self.diff_renames = Default::default();
+ self.diff_algorithm = Default::default();
+ }
(
self.static_pack_cache_limit_bytes,
self.pack_cache_bytes,
@@ -268,8 +280,19 @@ impl crate::Repository {
&mut self,
config: crate::Config,
) -> Result<(), Error> {
+ let (a, b, c) = (
+ self.config.static_pack_cache_limit_bytes,
+ self.config.pack_cache_bytes,
+ self.config.object_cache_bytes,
+ );
self.config.reread_values_and_clear_caches_replacing_config(config)?;
self.apply_changed_values();
+ if a != self.config.static_pack_cache_limit_bytes
+ || b != self.config.pack_cache_bytes
+ || c != self.config.object_cache_bytes
+ {
+ setup_objects(&mut self.objects, &self.config);
+ }
Ok(())
}
@@ -446,6 +469,29 @@ fn apply_environment_overrides(
}],
),
(
+ "gitoxide",
+ Some(Cow::Borrowed("pathspec".into())),
+ git_prefix,
+ &[
+ {
+ let key = &gitoxide::Pathspec::LITERAL;
+ (env(key), key.name)
+ },
+ {
+ let key = &gitoxide::Pathspec::GLOB;
+ (env(key), key.name)
+ },
+ {
+ let key = &gitoxide::Pathspec::NOGLOB;
+ (env(key), key.name)
+ },
+ {
+ let key = &gitoxide::Pathspec::ICASE;
+ (env(key), key.name)
+ },
+ ],
+ ),
+ (
"ssh",
None,
git_prefix,
diff --git a/vendor/gix/src/config/cache/util.rs b/vendor/gix/src/config/cache/util.rs
index 7c478fcf9..4032b2cb1 100644
--- a/vendor/gix/src/config/cache/util.rs
+++ b/vendor/gix/src/config/cache/util.rs
@@ -3,7 +3,6 @@ use super::Error;
use crate::{
config,
config::tree::{gitoxide, Core},
- revision::spec::parse::ObjectKindHint,
};
pub(crate) fn interpolate_context<'a>(
@@ -51,7 +50,7 @@ pub(crate) fn query_refupdates(
) -> Result<Option<gix_ref::store::WriteReflog>, Error> {
let key = "core.logAllRefUpdates";
Core::LOG_ALL_REF_UPDATES
- .try_into_ref_updates(config.boolean_by_key(key), || config.string_by_key(key))
+ .try_into_ref_updates(config.boolean_by_key(key))
.with_leniency(lenient_config)
.map_err(Into::into)
}
@@ -74,7 +73,7 @@ pub(crate) fn parse_object_caches(
mut filter_config_section: fn(&gix_config::file::Metadata) -> bool,
) -> Result<(Option<usize>, Option<usize>, usize), Error> {
let static_pack_cache_limit = config
- .integer_filter_by_key("core.deltaBaseCacheLimit", &mut filter_config_section)
+ .integer_filter_by_key("gitoxide.core.deltaBaseCacheLimit", &mut filter_config_section)
.map(|res| gitoxide::Core::DEFAULT_PACK_CACHE_MEMORY_LIMIT.try_into_usize(res))
.transpose()
.with_leniency(lenient)?;
@@ -103,10 +102,11 @@ pub(crate) fn parse_core_abbrev(
.flatten())
}
+#[cfg(feature = "revision")]
pub(crate) fn disambiguate_hint(
config: &gix_config::File<'static>,
lenient_config: bool,
-) -> Result<Option<ObjectKindHint>, config::key::GenericErrorWithValue> {
+) -> Result<Option<crate::revision::spec::parse::ObjectKindHint>, config::key::GenericErrorWithValue> {
match config.string_by_key("core.disambiguate") {
None => Ok(None),
Some(value) => Core::DISAMBIGUATE
@@ -120,10 +120,18 @@ pub trait ApplyLeniency {
fn with_leniency(self, is_lenient: bool) -> Self;
}
+pub trait IgnoreEmptyPath {
+ fn ignore_empty(self) -> Self;
+}
+
pub trait ApplyLeniencyDefault {
fn with_lenient_default(self, is_lenient: bool) -> Self;
}
+pub trait ApplyLeniencyDefaultValue<T> {
+ fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self;
+}
+
impl<T, E> ApplyLeniency for Result<Option<T>, E> {
fn with_leniency(self, is_lenient: bool) -> Self {
match self {
@@ -134,6 +142,16 @@ impl<T, E> ApplyLeniency for Result<Option<T>, E> {
}
}
+impl IgnoreEmptyPath for Result<Option<std::borrow::Cow<'_, std::path::Path>>, gix_config::path::interpolate::Error> {
+ fn ignore_empty(self) -> Self {
+ match self {
+ Ok(maybe_path) => Ok(maybe_path),
+ Err(gix_config::path::interpolate::Error::Missing { .. }) => Ok(None),
+ Err(err) => Err(err),
+ }
+ }
+}
+
impl<T, E> ApplyLeniencyDefault for Result<T, E>
where
T: Default,
@@ -146,3 +164,13 @@ where
}
}
}
+
+impl<T, E> ApplyLeniencyDefaultValue<T> for Result<T, E> {
+ fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self {
+ match self {
+ Ok(v) => Ok(v),
+ Err(_) if is_lenient => Ok(default),
+ Err(err) => Err(err),
+ }
+ }
+}
diff --git a/vendor/gix/src/config/mod.rs b/vendor/gix/src/config/mod.rs
index 3353806f8..102c7a482 100644
--- a/vendor/gix/src/config/mod.rs
+++ b/vendor/gix/src/config/mod.rs
@@ -1,10 +1,11 @@
pub use gix_config::*;
use gix_features::threading::OnceCell;
-use crate::{bstr::BString, repository::identity, revision::spec, Repository};
+use crate::{bstr::BString, repository::identity, Repository};
pub(crate) mod cache;
mod snapshot;
+#[cfg(feature = "credentials")]
pub use snapshot::credential_helpers;
///
@@ -46,6 +47,23 @@ pub(crate) mod section {
}
}
+///
+pub mod set_value {
+ /// The error produced when calling [`SnapshotMut::set(_subsection)?_value()`][crate::config::SnapshotMut::set_value()]
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ SetRaw(#[from] gix_config::file::set_raw_value::Error),
+ #[error(transparent)]
+ Validate(#[from] crate::config::tree::key::validate::Error),
+ #[error("The key needs a subsection parameter to be valid.")]
+ SubSectionRequired,
+ #[error("The key must not be used with a subsection")]
+ SubSectionForbidden,
+ }
+}
+
/// The error returned when failing to initialize the repository configuration.
///
/// This configuration is on the critical path when opening a repository.
@@ -102,6 +120,20 @@ pub mod diff {
}
///
+pub mod stat_options {
+ /// The error produced when collecting stat information, and returned by [Repository::stat_options()](crate::Repository::stat_options()).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error(transparent)]
+ ConfigCheckStat(#[from] super::key::GenericErrorWithValue),
+ #[error(transparent)]
+ ConfigBoolean(#[from] super::boolean::Error),
+ }
+}
+
+///
+#[cfg(feature = "attributes")]
pub mod checkout_options {
/// The error produced when collecting all information needed for checking out files into a worktree.
#[derive(Debug, thiserror::Error)]
@@ -115,6 +147,8 @@ pub mod checkout_options {
CheckoutWorkers(#[from] super::checkout::workers::Error),
#[error(transparent)]
Attributes(#[from] super::attribute_stack::Error),
+ #[error(transparent)]
+ FilterPipelineOptions(#[from] crate::filter::pipeline::options::Error),
}
}
@@ -275,6 +309,23 @@ pub mod key {
}
///
+pub mod encoding {
+ use crate::bstr::BString;
+
+ /// The error produced when failing to parse the `core.checkRoundTripEncoding` key.
+ #[derive(Debug, thiserror::Error)]
+ #[error("The encoding named '{encoding}' seen in key '{key}={value}' is unsupported")]
+ pub struct Error {
+ /// The configuration key that contained the value.
+ pub key: BString,
+ /// The value that was assigned to `key`.
+ pub value: BString,
+ /// The encoding that failed.
+ pub encoding: BString,
+ }
+}
+
+///
pub mod checkout {
///
pub mod workers {
@@ -424,6 +475,7 @@ pub mod transport {
key: Cow<'static, BStr>,
},
#[error("Could not configure the credential helpers for the authenticated proxy url")]
+ #[cfg(feature = "credentials")]
ConfigureProxyAuthenticate(#[from] crate::config::snapshot::credential_helpers::Error),
#[error(transparent)]
InvalidSslVersion(#[from] crate::config::ssl_version::Error),
@@ -459,11 +511,13 @@ pub(crate) struct Cache {
/// A lazily loaded rewrite list for remote urls
pub(crate) url_rewrite: OnceCell<crate::remote::url::Rewrite>,
/// The lazy-loaded rename information for diffs.
+ #[cfg(feature = "blob-diff")]
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
+ #[cfg(feature = "blob-diff")]
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.
@@ -475,12 +529,14 @@ pub(crate) struct Cache {
/// 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>,
+ #[cfg(feature = "revision")]
+ pub object_kind_hint: Option<crate::revision::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,
+ #[cfg_attr(not(feature = "worktree-mutation"), allow(dead_code))]
attributes: crate::open::permissions::Attributes,
environment: crate::open::permissions::Environment,
// TODO: make core.precomposeUnicode available as well.
diff --git a/vendor/gix/src/config/overrides.rs b/vendor/gix/src/config/overrides.rs
index 4bdf4a13f..6b3fc728c 100644
--- a/vendor/gix/src/config/overrides.rs
+++ b/vendor/gix/src/config/overrides.rs
@@ -26,11 +26,15 @@ pub(crate) fn append(
let mut file = gix_config::File::new(gix_config::file::Metadata::from(source));
for key_value in values {
let key_value = key_value.as_ref();
- let mut tokens = key_value.splitn(2, |b| *b == b'=').map(|v| v.trim());
+ let mut tokens = key_value.splitn(2, |b| *b == b'=').map(ByteSlice::trim);
let key = tokens.next().expect("always one value").as_bstr();
let value = tokens.next();
- let key = gix_config::parse::key(key.to_str().map_err(|_| Error::InvalidKey { input: key.into() })?)
- .ok_or_else(|| Error::InvalidKey { input: key.into() })?;
+ let key = gix_config::parse::key(
+ key.to_str()
+ .map_err(|_| Error::InvalidKey { input: key.into() })?
+ .into(),
+ )
+ .ok_or_else(|| Error::InvalidKey { input: key.into() })?;
let mut section = file.section_mut_or_create_new(key.section_name, key.subsection_name)?;
let key =
gix_config::parse::section::Key::try_from(key.value_name.to_owned()).map_err(|err| Error::SectionKey {
@@ -38,7 +42,7 @@ pub(crate) fn append(
key: key.value_name.into(),
})?;
let comment = make_comment(key_value);
- let value = value.map(|v| v.as_bstr());
+ let value = value.map(ByteSlice::as_bstr);
match comment {
Some(comment) => section.push_with_comment(key, value, &**comment),
None => section.push(key, value),
diff --git a/vendor/gix/src/config/snapshot/access.rs b/vendor/gix/src/config/snapshot/access.rs
index 1710348a9..7dc593880 100644
--- a/vendor/gix/src/config/snapshot/access.rs
+++ b/vendor/gix/src/config/snapshot/access.rs
@@ -2,9 +2,11 @@
use std::borrow::Cow;
use gix_features::threading::OwnShared;
+use gix_macros::momo;
+use crate::bstr::ByteSlice;
use crate::{
- bstr::BStr,
+ bstr::{BStr, BString},
config::{CommitAutoRollback, Snapshot, SnapshotMut},
};
@@ -25,6 +27,7 @@ impl<'repo> Snapshot<'repo> {
}
/// Like [`boolean()`][Self::boolean()], but it will report an error if the value couldn't be interpreted as boolean.
+ #[momo]
pub fn try_boolean<'a>(&self, key: impl Into<&'a BStr>) -> Option<Result<bool, gix_config::value::Error>> {
self.repo.config.resolved.boolean_by_key(key)
}
@@ -40,6 +43,7 @@ impl<'repo> Snapshot<'repo> {
}
/// Like [`integer()`][Self::integer()], but it will report an error if the value couldn't be interpreted as boolean.
+ #[momo]
pub fn try_integer<'a>(&self, key: impl Into<&'a BStr>) -> Option<Result<i64, gix_config::value::Error>> {
self.repo.config.resolved.integer_by_key(key)
}
@@ -47,6 +51,7 @@ impl<'repo> Snapshot<'repo> {
/// Return the string at `key`, or `None` if there is no such value.
///
/// Note that this method takes the most recent value at `key` even if it is from a file with reduced trust.
+ #[momo]
pub fn string<'a>(&self, key: impl Into<&'a BStr>) -> Option<Cow<'_, BStr>> {
self.repo.config.resolved.string_by_key(key)
}
@@ -54,11 +59,12 @@ impl<'repo> Snapshot<'repo> {
/// Return the trusted and fully interpolated path at `key`, or `None` if there is no such value
/// or if no value was found in a trusted file.
/// An error occurs if the path could not be interpolated to its final value.
+ #[momo]
pub fn trusted_path<'a>(
&self,
key: impl Into<&'a BStr>,
) -> Option<Result<Cow<'_, std::path::Path>, gix_config::path::interpolate::Error>> {
- let key = gix_config::parse::key(key)?;
+ let key = gix_config::parse::key(key.into())?;
self.repo
.config
.trusted_file_path(key.section_name, key.subsection_name, key.value_name)
@@ -99,6 +105,50 @@ impl<'repo> SnapshotMut<'repo> {
self.commit_inner(repo)
}
+ /// Set the value at `key` to `new_value`, possibly creating the section if it doesn't exist yet, or overriding the most recent existing
+ /// value, which will be returned.
+ #[momo]
+ pub fn set_value<'b>(
+ &mut self,
+ key: &'static dyn crate::config::tree::Key,
+ new_value: impl Into<&'b BStr>,
+ ) -> Result<Option<BString>, crate::config::set_value::Error> {
+ if let Some(crate::config::tree::SubSectionRequirement::Parameter(_)) = key.subsection_requirement() {
+ return Err(crate::config::set_value::Error::SubSectionRequired);
+ }
+ let value = new_value.into();
+ key.validate(value)?;
+ let current = self
+ .config
+ .set_raw_value(key.section().name(), None, key.name(), value)?;
+ Ok(current.map(std::borrow::Cow::into_owned))
+ }
+
+ /// Set the value at `key` to `new_value` in the given `subsection`, possibly creating the section and sub-section if it doesn't exist yet,
+ /// or overriding the most recent existing value, which will be returned.
+ #[momo]
+ pub fn set_subsection_value<'a, 'b>(
+ &mut self,
+ key: &'static dyn crate::config::tree::Key,
+ subsection: impl Into<&'a BStr>,
+ new_value: impl Into<&'b BStr>,
+ ) -> Result<Option<BString>, crate::config::set_value::Error> {
+ if let Some(crate::config::tree::SubSectionRequirement::Never) = key.subsection_requirement() {
+ return Err(crate::config::set_value::Error::SubSectionForbidden);
+ }
+ let value = new_value.into();
+ key.validate(value)?;
+
+ let name = key
+ .full_name(Some(subsection.into()))
+ .expect("we know it needs a subsection");
+ let key = gix_config::parse::key((**name).as_bstr()).expect("statically known keys can always be parsed");
+ let current =
+ self.config
+ .set_raw_value(key.section_name, key.subsection_name, key.value_name.to_owned(), value)?;
+ Ok(current.map(std::borrow::Cow::into_owned))
+ }
+
pub(crate) fn commit_inner(
&mut self,
repo: &'repo mut crate::Repository,
diff --git a/vendor/gix/src/config/snapshot/credential_helpers.rs b/vendor/gix/src/config/snapshot/credential_helpers.rs
index c4eef35d6..189e74471 100644
--- a/vendor/gix/src/config/snapshot/credential_helpers.rs
+++ b/vendor/gix/src/config/snapshot/credential_helpers.rs
@@ -2,6 +2,7 @@ use std::{borrow::Cow, convert::TryFrom};
pub use error::Error;
+use crate::config::cache::util::IgnoreEmptyPath;
use crate::{
bstr::{ByteSlice, ByteVec},
config::{
@@ -140,7 +141,8 @@ impl Snapshot<'_> {
let prompt_options = gix_prompt::Options {
askpass: self
.trusted_path(Core::ASKPASS.logical_name().as_str())
- .transpose()?
+ .transpose()
+ .ignore_empty()?
.map(|c| Cow::Owned(c.into_owned())),
..Default::default()
}
diff --git a/vendor/gix/src/config/snapshot/mod.rs b/vendor/gix/src/config/snapshot/mod.rs
index 80ec6f948..de143ea1f 100644
--- a/vendor/gix/src/config/snapshot/mod.rs
+++ b/vendor/gix/src/config/snapshot/mod.rs
@@ -2,4 +2,5 @@ mod _impls;
mod access;
///
+#[cfg(feature = "credentials")]
pub mod credential_helpers;
diff --git a/vendor/gix/src/config/tree/keys.rs b/vendor/gix/src/config/tree/keys.rs
index b03fa49c6..5a5257af5 100644
--- a/vendor/gix/src/config/tree/keys.rs
+++ b/vendor/gix/src/config/tree/keys.rs
@@ -464,7 +464,7 @@ mod remote_name {
}
}
-/// Provide a way to validate a value, or decode a value from `gix-config`.
+/// Provide a way to validate a value, or decode a value from `git-config`.
pub trait Validate {
/// Validate `value` or return an error.
fn validate(&self, value: &BStr) -> Result<(), Box<dyn Error + Send + Sync + 'static>>;
diff --git a/vendor/gix/src/config/tree/mod.rs b/vendor/gix/src/config/tree/mod.rs
index 3f69ccb97..d8415154f 100644
--- a/vendor/gix/src/config/tree/mod.rs
+++ b/vendor/gix/src/config/tree/mod.rs
@@ -31,6 +31,7 @@ pub(crate) mod root {
/// The `credential` section.
pub const CREDENTIAL: sections::Credential = sections::Credential;
/// The `diff` section.
+ #[cfg(feature = "blob-diff")]
pub const DIFF: sections::Diff = sections::Diff;
/// The `extensions` section.
pub const EXTENSIONS: sections::Extensions = sections::Extensions;
@@ -69,6 +70,7 @@ pub(crate) mod root {
&Self::COMMITTER,
&Self::CORE,
&Self::CREDENTIAL,
+ #[cfg(feature = "blob-diff")]
&Self::DIFF,
&Self::EXTENSIONS,
&Self::FETCH,
@@ -90,10 +92,12 @@ pub(crate) mod root {
mod sections;
pub use sections::{
- branch, checkout, core, credential, diff, extensions, fetch, gitoxide, http, index, protocol, remote, ssh, Author,
- Branch, Checkout, Clone, Committer, Core, Credential, Diff, Extensions, Fetch, Gitoxide, Http, Index, Init, Pack,
+ branch, checkout, core, credential, extensions, fetch, gitoxide, http, index, protocol, remote, ssh, Author,
+ Branch, Checkout, Clone, Committer, Core, Credential, Extensions, Fetch, Gitoxide, Http, Index, Init, Pack,
Protocol, Remote, Safe, Ssh, Url, User,
};
+#[cfg(feature = "blob-diff")]
+pub use sections::{diff, Diff};
/// Generic value implementations for static instantiation.
pub mod keys;
diff --git a/vendor/gix/src/config/tree/sections/core.rs b/vendor/gix/src/config/tree/sections/core.rs
index 93d2fcd01..ab3e2bab9 100644
--- a/vendor/gix/src/config/tree/sections/core.rs
+++ b/vendor/gix/src/config/tree/sections/core.rs
@@ -45,7 +45,8 @@ impl 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);
+ pub const TRUST_C_TIME: keys::Boolean = keys::Boolean::new_boolean("trustCTime", &config::Tree::CORE)
+ .with_deviation("Currently the default is false, instead of true, as it seems to be 2s off in tests");
/// The `core.worktree` key.
pub const WORKTREE: keys::Any = keys::Any::new("worktree", &config::Tree::CORE)
.with_environment_override("GIT_WORK_TREE")
@@ -66,6 +67,24 @@ impl Core {
/// The `core.useReplaceRefs` key.
pub const USE_REPLACE_REFS: keys::Boolean = keys::Boolean::new_boolean("useReplaceRefs", &config::Tree::CORE)
.with_environment_override("GIT_NO_REPLACE_OBJECTS");
+ /// The `core.commitGraph` key.
+ pub const COMMIT_GRAPH: keys::Boolean = keys::Boolean::new_boolean("commitGraph", &config::Tree::CORE);
+ /// The `core.safecrlf` key.
+ #[cfg(feature = "attributes")]
+ pub const SAFE_CRLF: SafeCrlf = SafeCrlf::new_with_validate("safecrlf", &config::Tree::CORE, validate::SafeCrlf);
+ /// The `core.autocrlf` key.
+ #[cfg(feature = "attributes")]
+ pub const AUTO_CRLF: AutoCrlf = AutoCrlf::new_with_validate("autocrlf", &config::Tree::CORE, validate::AutoCrlf);
+ /// The `core.eol` key.
+ #[cfg(feature = "attributes")]
+ pub const EOL: Eol = Eol::new_with_validate("eol", &config::Tree::CORE, validate::Eol);
+ /// The `core.checkRoundTripEncoding` key.
+ #[cfg(feature = "attributes")]
+ pub const CHECK_ROUND_TRIP_ENCODING: CheckRoundTripEncoding = CheckRoundTripEncoding::new_with_validate(
+ "checkRoundTripEncoding",
+ &config::Tree::CORE,
+ validate::CheckRoundTripEncoding,
+ );
}
impl Section for Core {
@@ -96,6 +115,15 @@ impl Section for Core {
&Self::ATTRIBUTES_FILE,
&Self::SSH_COMMAND,
&Self::USE_REPLACE_REFS,
+ &Self::COMMIT_GRAPH,
+ #[cfg(feature = "attributes")]
+ &Self::SAFE_CRLF,
+ #[cfg(feature = "attributes")]
+ &Self::AUTO_CRLF,
+ #[cfg(feature = "attributes")]
+ &Self::EOL,
+ #[cfg(feature = "attributes")]
+ &Self::CHECK_ROUND_TRIP_ENCODING,
]
}
}
@@ -112,6 +140,154 @@ pub type LogAllRefUpdates = keys::Any<validate::LogAllRefUpdates>;
/// The `core.disambiguate` key.
pub type Disambiguate = keys::Any<validate::Disambiguate>;
+#[cfg(feature = "attributes")]
+mod filter {
+ use super::validate;
+ use crate::config::tree::keys;
+
+ /// The `core.safecrlf` key.
+ pub type SafeCrlf = keys::Any<validate::SafeCrlf>;
+
+ /// The `core.autocrlf` key.
+ pub type AutoCrlf = keys::Any<validate::AutoCrlf>;
+
+ /// The `core.eol` key.
+ pub type Eol = keys::Any<validate::Eol>;
+
+ /// The `core.checkRoundTripEncoding` key.
+ pub type CheckRoundTripEncoding = keys::Any<validate::CheckRoundTripEncoding>;
+
+ mod check_round_trip_encoding {
+ use std::borrow::Cow;
+
+ use crate::{
+ bstr::{BStr, ByteSlice},
+ config,
+ config::tree::{core::CheckRoundTripEncoding, Key},
+ };
+
+ impl CheckRoundTripEncoding {
+ /// Convert `value` into a list of encodings, which are either space or coma separated. Fail if an encoding is unknown.
+ /// If `None`, the default is returned.
+ pub fn try_into_encodings(
+ &'static self,
+ value: Option<Cow<'_, BStr>>,
+ ) -> Result<Vec<&'static gix_filter::encoding::Encoding>, config::encoding::Error> {
+ Ok(match value {
+ None => vec![gix_filter::encoding::SHIFT_JIS],
+ Some(value) => {
+ let mut out = Vec::new();
+ for encoding in value
+ .as_ref()
+ .split(|b| *b == b',' || *b == b' ')
+ .filter(|e| !e.trim().is_empty())
+ {
+ out.push(
+ gix_filter::encoding::Encoding::for_label(encoding.trim()).ok_or_else(|| {
+ config::encoding::Error {
+ key: self.logical_name().into(),
+ value: value.as_ref().to_owned(),
+ encoding: encoding.into(),
+ }
+ })?,
+ );
+ }
+ out
+ }
+ })
+ }
+ }
+ }
+
+ mod eol {
+ use std::borrow::Cow;
+
+ use crate::{
+ bstr::{BStr, ByteSlice},
+ config,
+ config::tree::core::Eol,
+ };
+
+ impl Eol {
+ /// Convert `value` into the default end-of-line mode.
+ ///
+ /// ### Deviation
+ ///
+ /// git will allow any value and silently leaves it unset, we will fail if the value is not known.
+ pub fn try_into_eol(
+ &'static self,
+ value: Cow<'_, BStr>,
+ ) -> Result<gix_filter::eol::Mode, config::key::GenericErrorWithValue> {
+ Ok(match value.to_str_lossy().as_ref() {
+ "lf" => gix_filter::eol::Mode::Lf,
+ "crlf" => gix_filter::eol::Mode::CrLf,
+ "native" => gix_filter::eol::Mode::default(),
+ _ => return Err(config::key::GenericErrorWithValue::from_value(self, value.into_owned())),
+ })
+ }
+ }
+ }
+
+ mod safecrlf {
+ use std::borrow::Cow;
+
+ use gix_filter::pipeline::CrlfRoundTripCheck;
+
+ use crate::{bstr::BStr, config, config::tree::core::SafeCrlf};
+
+ impl SafeCrlf {
+ /// Convert `value` into the safe-crlf enumeration, if possible.
+ pub fn try_into_safecrlf(
+ &'static self,
+ value: Cow<'_, BStr>,
+ ) -> Result<CrlfRoundTripCheck, config::key::GenericErrorWithValue> {
+ if value.as_ref() == "warn" {
+ return Ok(CrlfRoundTripCheck::Warn);
+ }
+ let value = gix_config::Boolean::try_from(value.as_ref()).map_err(|err| {
+ config::key::GenericErrorWithValue::from_value(self, value.into_owned()).with_source(err)
+ })?;
+ Ok(if value.into() {
+ CrlfRoundTripCheck::Fail
+ } else {
+ CrlfRoundTripCheck::Skip
+ })
+ }
+ }
+ }
+
+ mod autocrlf {
+ use std::borrow::Cow;
+
+ use gix_filter::eol;
+
+ use crate::{bstr::BStr, config, config::tree::core::AutoCrlf};
+
+ impl AutoCrlf {
+ /// Convert `value` into the safe-crlf enumeration, if possible.
+ pub fn try_into_autocrlf(
+ &'static self,
+ value: Cow<'_, BStr>,
+ ) -> Result<eol::AutoCrlf, config::key::GenericErrorWithValue> {
+ if value.as_ref() == "input" {
+ return Ok(eol::AutoCrlf::Input);
+ }
+ let value = gix_config::Boolean::try_from(value.as_ref()).map_err(|err| {
+ config::key::GenericErrorWithValue::from_value(self, value.into_owned()).with_source(err)
+ })?;
+ Ok(if value.into() {
+ eol::AutoCrlf::Enabled
+ } else {
+ eol::AutoCrlf::Disabled
+ })
+ }
+ }
+ }
+}
+#[cfg(feature = "attributes")]
+pub use filter::*;
+
+#[cfg(feature = "revision")]
mod disambiguate {
use std::borrow::Cow;
@@ -143,30 +319,27 @@ mod disambiguate {
}
mod log_all_ref_updates {
- use std::borrow::Cow;
-
- use crate::{bstr::BStr, config, config::tree::core::LogAllRefUpdates};
+ use crate::{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>(
+ /// Returns the mode for ref-updates as parsed from `value`. If `value` is not a boolean, we try
+ /// to interpret the string value instead. For correctness, this two step process is necessary as
+ /// the interpretation of booleans in special in `git-config`, i.e. we can't just treat it as string.
+ pub fn try_into_ref_updates(
&'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 {
+ match value {
+ Some(Ok(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),
+ Some(Err(err)) => match err.input {
+ val if val.eq_ignore_ascii_case(b"always") => Ok(Some(gix_ref::store::WriteReflog::Always)),
+ val => Err(config::key::GenericErrorWithValue::from_value(self, val)),
},
+ None => Ok(None),
}
}
}
@@ -270,7 +443,9 @@ mod validate {
pub struct Disambiguate;
impl keys::Validate for Disambiguate {
+ #[cfg_attr(not(feature = "revision"), allow(unused_variables))]
fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "revision")]
super::Core::DISAMBIGUATE.try_into_object_kind_hint(value.into())?;
Ok(())
}
@@ -280,9 +455,7 @@ mod validate {
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())
- })?;
+ .try_into_ref_updates(Some(gix_config::Boolean::try_from(value).map(|b| b.0)))?;
Ok(())
}
}
@@ -303,4 +476,44 @@ mod validate {
Ok(())
}
}
+
+ pub struct SafeCrlf;
+ impl keys::Validate for SafeCrlf {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::SAFE_CRLF.try_into_safecrlf(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct AutoCrlf;
+ impl keys::Validate for AutoCrlf {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::AUTO_CRLF.try_into_autocrlf(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct Eol;
+ impl keys::Validate for Eol {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::EOL.try_into_eol(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct CheckRoundTripEncoding;
+ impl keys::Validate for CheckRoundTripEncoding {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "attributes")]
+ super::Core::CHECK_ROUND_TRIP_ENCODING.try_into_encodings(Some(value.into()))?;
+ Ok(())
+ }
+ }
}
diff --git a/vendor/gix/src/config/tree/sections/diff.rs b/vendor/gix/src/config/tree/sections/diff.rs
index 103bb7001..7c467b8f5 100644
--- a/vendor/gix/src/config/tree/sections/diff.rs
+++ b/vendor/gix/src/config/tree/sections/diff.rs
@@ -68,10 +68,8 @@ mod algorithm {
}
mod renames {
- use std::borrow::Cow;
-
use crate::{
- bstr::{BStr, ByteSlice},
+ bstr::ByteSlice,
config::{
key::GenericError,
tree::{keys, sections::diff::Renames, Section},
@@ -84,21 +82,20 @@ mod renames {
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>(
+ /// Try to convert the configuration into a valid rename tracking variant. Use `value` and if it's an error, interpret
+ /// the boolean as string
+ pub fn try_into_renames(
&'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() {
+ let value = &err.input;
+ match value.as_bytes() {
b"copy" | b"copies" => Tracking::RenamesAndCopies,
- _ => return Err(GenericError::from_value(self, value.into_owned()).with_source(err)),
+ _ => return Err(GenericError::from_value(self, value.clone()).with_source(err)),
}
}
})
@@ -107,8 +104,6 @@ mod renames {
}
mod validate {
- use std::borrow::Cow;
-
use crate::{
bstr::BStr,
config::tree::{keys, Diff},
@@ -126,7 +121,7 @@ mod validate {
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)))?;
+ Diff::RENAMES.try_into_renames(boolean)?;
Ok(())
}
}
diff --git a/vendor/gix/src/config/tree/sections/fetch.rs b/vendor/gix/src/config/tree/sections/fetch.rs
index 117cabfd2..32db7be5f 100644
--- a/vendor/gix/src/config/tree/sections/fetch.rs
+++ b/vendor/gix/src/config/tree/sections/fetch.rs
@@ -10,6 +10,10 @@ impl Fetch {
&config::Tree::FETCH,
validate::NegotiationAlgorithm,
);
+ /// The `fetch.recurseSubmodules` key.
+ #[cfg(feature = "attributes")]
+ pub const RECURSE_SUBMODULES: RecurseSubmodules =
+ RecurseSubmodules::new_with_validate("recurseSubmodules", &config::Tree::FETCH, validate::RecurseSubmodules);
}
impl Section for Fetch {
@@ -18,50 +22,81 @@ impl Section for Fetch {
}
fn keys(&self) -> &[&dyn Key] {
- &[&Self::NEGOTIATION_ALGORITHM]
+ &[
+ &Self::NEGOTIATION_ALGORITHM,
+ #[cfg(feature = "attributes")]
+ &Self::RECURSE_SUBMODULES,
+ ]
}
}
/// The `fetch.negotiationAlgorithm` key.
pub type NegotiationAlgorithm = keys::Any<validate::NegotiationAlgorithm>;
-mod algorithm {
- use std::borrow::Cow;
-
- use gix_object::bstr::ByteSlice;
+/// The `fetch.recurseSubmodules` key.
+#[cfg(feature = "attributes")]
+pub type RecurseSubmodules = keys::Any<validate::RecurseSubmodules>;
- use crate::{
- bstr::BStr,
- config::{key::GenericErrorWithValue, tree::sections::fetch::NegotiationAlgorithm},
- remote::fetch::negotiate,
- };
-
- impl NegotiationAlgorithm {
+mod algorithm {
+ #[cfg(feature = "credentials")]
+ impl crate::config::tree::sections::fetch::NegotiationAlgorithm {
/// Derive the negotiation algorithm identified by `name`, case-sensitively.
pub fn try_into_negotiation_algorithm(
&'static self,
- name: Cow<'_, BStr>,
- ) -> Result<negotiate::Algorithm, GenericErrorWithValue> {
+ name: std::borrow::Cow<'_, crate::bstr::BStr>,
+ ) -> Result<crate::remote::fetch::negotiate::Algorithm, crate::config::key::GenericErrorWithValue> {
+ use crate::bstr::ByteSlice;
+ use crate::remote::fetch::negotiate::Algorithm;
+
Ok(match name.as_ref().as_bytes() {
- b"noop" => negotiate::Algorithm::Noop,
- b"consecutive" | b"default" => negotiate::Algorithm::Consecutive,
- b"skipping" => negotiate::Algorithm::Skipping,
- _ => return Err(GenericErrorWithValue::from_value(self, name.into_owned())),
+ b"noop" => Algorithm::Noop,
+ b"consecutive" | b"default" => Algorithm::Consecutive,
+ b"skipping" => Algorithm::Skipping,
+ _ => {
+ return Err(crate::config::key::GenericErrorWithValue::from_value(
+ self,
+ name.into_owned(),
+ ))
+ }
})
}
}
+
+ #[cfg(feature = "attributes")]
+ impl crate::config::tree::sections::fetch::RecurseSubmodules {
+ /// Obtain the way submodules should be updated.
+ pub fn try_into_recurse_submodules(
+ &'static self,
+ value: Result<bool, gix_config::value::Error>,
+ ) -> Result<gix_submodule::config::FetchRecurse, crate::config::key::GenericErrorWithValue> {
+ gix_submodule::config::FetchRecurse::new(value)
+ .map_err(|err| crate::config::key::GenericErrorWithValue::from_value(self, err))
+ }
+ }
}
mod validate {
- use crate::{
- bstr::BStr,
- config::tree::{keys, Fetch},
- };
+ use crate::{bstr::BStr, config::tree::keys};
pub struct NegotiationAlgorithm;
impl keys::Validate for NegotiationAlgorithm {
+ #[cfg_attr(not(feature = "credentials"), allow(unused_variables))]
+ fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
+ #[cfg(feature = "credentials")]
+ crate::config::tree::Fetch::NEGOTIATION_ALGORITHM.try_into_negotiation_algorithm(value.into())?;
+ Ok(())
+ }
+ }
+
+ pub struct RecurseSubmodules;
+ impl keys::Validate for RecurseSubmodules {
+ #[cfg_attr(not(feature = "attributes"), allow(unused_variables))]
fn validate(&self, value: &BStr) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
- Fetch::NEGOTIATION_ALGORITHM.try_into_negotiation_algorithm(value.into())?;
+ #[cfg(feature = "attributes")]
+ {
+ let boolean = gix_config::Boolean::try_from(value).map(|b| b.0);
+ crate::config::tree::Fetch::RECURSE_SUBMODULES.try_into_recurse_submodules(boolean)?;
+ }
Ok(())
}
}
diff --git a/vendor/gix/src/config/tree/sections/gitoxide.rs b/vendor/gix/src/config/tree/sections/gitoxide.rs
index f07d494fb..966d5af7c 100644
--- a/vendor/gix/src/config/tree/sections/gitoxide.rs
+++ b/vendor/gix/src/config/tree/sections/gitoxide.rs
@@ -24,6 +24,8 @@ impl Gitoxide {
pub const SSH: Ssh = Ssh;
/// The `gitoxide.user` section.
pub const USER: User = User;
+ /// The `gitoxide.pathspec` section.
+ pub const PATHSPEC: Pathspec = Pathspec;
/// The `gitoxide.userAgent` Key.
pub const USER_AGENT: keys::Any = keys::Any::new("userAgent", &config::Tree::GITOXIDE).with_note(
@@ -52,6 +54,7 @@ impl Section for Gitoxide {
&Self::OBJECTS,
&Self::SSH,
&Self::USER,
+ &Self::PATHSPEC,
]
}
}
@@ -86,6 +89,12 @@ mod subsections {
.with_deviation(
"relative file paths will always be made relative to the git-common-dir, whereas `git` keeps them as is.",
);
+
+ /// The `gitoxide.core.filterProcessDelay` key (default `true`).
+ ///
+ /// It controls whether or not long running filter driver processes can use the 'delay' capability.
+ pub const FILTER_PROCESS_DELAY: keys::Boolean =
+ keys::Boolean::new_boolean("filterProcessDelay", &Gitoxide::CORE);
}
impl Section for Core {
@@ -99,6 +108,7 @@ mod subsections {
&Self::USE_NSEC,
&Self::USE_STDEV,
&Self::SHALLOW_FILE,
+ &Self::FILTER_PROCESS_DELAY,
]
}
@@ -306,6 +316,56 @@ mod subsections {
}
}
+ /// The `pathspec` sub-section.
+ #[derive(Copy, Clone, Default)]
+ pub struct Pathspec;
+
+ impl Pathspec {
+ /// The `gitoxide.pathspec.glob` key.
+ pub const GLOB: keys::Boolean = keys::Boolean::new_boolean("glob", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_GLOB_PATHSPECS")
+ .with_note("pathspec wildcards don't match the slash character, then needing '**' to get past them");
+ /// The `gitoxide.pathspec.noglob` key.
+ pub const NOGLOB: keys::Boolean = keys::Boolean::new_boolean("noglob", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_NOGLOB_PATHSPECS")
+ .with_note("Enable literal matching for glob patterns, effectively disabling globbing");
+ /// The `gitoxide.pathspec.literal` key.
+ pub const LITERAL: keys::Boolean = keys::Boolean::new_boolean("literal", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_LITERAL_PATHSPECS")
+ .with_note("Make the entire spec used verbatim, the only way to get ':()name' verbatim for instance");
+ /// The `gitoxide.pathspec.icase` key.
+ pub const ICASE: keys::Boolean = keys::Boolean::new_boolean("icase", &Gitoxide::PATHSPEC)
+ .with_environment_override("GIT_ICASE_PATHSPECS")
+ .with_note("Compare string in a case-insensitive manner");
+ /// The `gitoxide.pathspec.inheritIgnoreCase` key, defaulting to `true` if unspecified.
+ /// If set, pathspecs will automatically be match case-insensitively if the underlying filesystem is configured that way.
+ pub const INHERIT_IGNORE_CASE: keys::Boolean =
+ keys::Boolean::new_boolean("inheritIgnoreCase", &Gitoxide::PATHSPEC)
+ .with_note("Inherit `core.ignoreCase` for defaults in pathspecs");
+ /// The default value for `gitoxide.pathspec.inheritIgnoreCase`.
+ pub const INHERIT_IGNORE_CASE_DEFAULT: bool = true;
+ }
+
+ impl Section for Pathspec {
+ fn name(&self) -> &str {
+ "pathspec"
+ }
+
+ fn keys(&self) -> &[&dyn Key] {
+ &[
+ &Self::GLOB,
+ &Self::NOGLOB,
+ &Self::LITERAL,
+ &Self::ICASE,
+ &Self::INHERIT_IGNORE_CASE,
+ ]
+ }
+
+ fn parent(&self) -> Option<&dyn Section> {
+ Some(&Tree::GITOXIDE)
+ }
+ }
+
/// The `objects` sub-section.
#[derive(Copy, Clone, Default)]
pub struct Objects;
@@ -391,7 +451,7 @@ mod subsections {
}
}
}
-pub use subsections::{Allow, Author, Commit, Committer, Core, Http, Https, Objects, Ssh, User};
+pub use subsections::{Allow, Author, Commit, Committer, Core, Http, Https, Objects, Pathspec, Ssh, User};
pub mod validate {
use std::error::Error;
diff --git a/vendor/gix/src/config/tree/sections/index.rs b/vendor/gix/src/config/tree/sections/index.rs
index 08f7ec1bd..026f35b6d 100644
--- a/vendor/gix/src/config/tree/sections/index.rs
+++ b/vendor/gix/src/config/tree/sections/index.rs
@@ -7,6 +7,9 @@ impl Index {
/// The `index.threads` key.
pub const THREADS: IndexThreads =
IndexThreads::new_with_validate("threads", &config::Tree::INDEX, validate::IndexThreads);
+ /// The `index.skipHash` key.
+ pub const SKIP_HASH: keys::Boolean = keys::Boolean::new_boolean("skipHash", &config::Tree::INDEX)
+ .with_deviation("also used to skip the hash when reading, even if a hash exists in the index file");
}
/// The `index.threads` key.
@@ -47,7 +50,7 @@ impl Section for Index {
}
fn keys(&self) -> &[&dyn Key] {
- &[&Self::THREADS]
+ &[&Self::THREADS, &Self::SKIP_HASH]
}
}
diff --git a/vendor/gix/src/config/tree/sections/mod.rs b/vendor/gix/src/config/tree/sections/mod.rs
index ebf24a8b7..34929c5d1 100644
--- a/vendor/gix/src/config/tree/sections/mod.rs
+++ b/vendor/gix/src/config/tree/sections/mod.rs
@@ -37,7 +37,9 @@ pub mod credential;
/// The `diff` top-level section.
#[derive(Copy, Clone, Default)]
+#[cfg(feature = "blob-diff")]
pub struct Diff;
+#[cfg(feature = "blob-diff")]
pub mod diff;
/// The `extension` top-level section.
diff --git a/vendor/gix/src/config/tree/sections/protocol.rs b/vendor/gix/src/config/tree/sections/protocol.rs
index a0510f2b8..7ef2cc8cb 100644
--- a/vendor/gix/src/config/tree/sections/protocol.rs
+++ b/vendor/gix/src/config/tree/sections/protocol.rs
@@ -127,7 +127,7 @@ mod validate {
.to_decimal()
.ok_or_else(|| format!("integer {value} cannot be represented as integer"))?;
match value {
- 0 | 1 | 2 => Ok(()),
+ 0..=2 => Ok(()),
_ => Err(format!("protocol version {value} is unknown").into()),
}
}