From c23a457e72abe608715ac76f076f47dc42af07a5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 20:31:44 +0200 Subject: Merging upstream version 1.74.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/gix/src/config/cache/access.rs | 200 +++++++++++++++++++++++--------- vendor/gix/src/config/cache/incubate.rs | 4 +- vendor/gix/src/config/cache/init.rs | 58 ++++++++- vendor/gix/src/config/cache/util.rs | 36 +++++- 4 files changed, 231 insertions(+), 67 deletions(-) (limited to 'vendor/gix/src/config/cache') 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 { + 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 { + 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, 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> { 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 { + 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 { + 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 { - fn boolean( - me: &Cache, - full_key: &str, - key: &'static config::tree::keys::Boolean, - default: bool, - ) -> Result { - 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 { + 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, - source: gix_worktree::cache::state::ignore::Source, + source: gix_worktree::stack::state::ignore::Source, buf: &mut Vec, - ) -> Result { + ) -> Result { 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), config::attribute_stack::Error> { + ) -> Result<(gix_worktree::stack::state::Attributes, Vec), 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 { + 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 { + 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(()) } @@ -445,6 +468,29 @@ fn apply_environment_overrides( (env(key), key.name) }], ), + ( + "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, 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, 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, Option, 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, config::key::GenericErrorWithValue> { +) -> Result, 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 { + fn with_lenient_default_value(self, is_lenient: bool, default: T) -> Self; +} + impl ApplyLeniency for Result, E> { fn with_leniency(self, is_lenient: bool) -> Self { match self { @@ -134,6 +142,16 @@ impl ApplyLeniency for Result, E> { } } +impl IgnoreEmptyPath for Result>, 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 ApplyLeniencyDefault for Result where T: Default, @@ -146,3 +164,13 @@ where } } } + +impl ApplyLeniencyDefaultValue for Result { + 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), + } + } +} -- cgit v1.2.3