diff --git a/gix/src/open/repository.rs b/gix/src/open/repository.rs index 25a8af99453..1b367497ffa 100644 --- a/gix/src/open/repository.rs +++ b/gix/src/open/repository.rs @@ -1,4 +1,9 @@ #![allow(clippy::result_large_err)] +use gix_config::file::Metadata; +use gix_features::threading::OwnShared; +use gix_object::bstr::ByteSlice; +use gix_path::RelativePath; +use std::path::Path; use std::{ borrow::Cow, collections::{btree_map::Entry, BTreeMap}, @@ -6,10 +11,6 @@ use std::{ path::PathBuf, }; -use gix_features::threading::OwnShared; -use gix_object::bstr::ByteSlice; -use gix_path::RelativePath; - use super::{Error, Options}; use crate::{ bstr::BString, @@ -257,26 +258,32 @@ impl ThreadSafeRepository { // core.worktree might be used to overwrite the worktree directory if !config.is_bare { let mut key_source = None; + fn assure_config_is_from_current_repo( + section: &gix_config::file::Metadata, + git_dir: &Path, + current_dir: &Path, + filter_config_section: &mut fn(&Metadata) -> bool, + ) -> bool { + if !filter_config_section(section) { + return false; + } + // ignore worktree settings that aren't from our repository. This can happen + // with worktrees of submodules for instance. + section + .path + .as_deref() + .and_then(|p| gix_path::normalize(p.into(), current_dir)) + .is_some_and(|config_path| config_path.starts_with(git_dir)) + } let worktree_path = config .resolved - .path_filter(Core::WORKTREE, { - |section| { - if !filter_config_section(section) { - return false; - } - // ignore worktree settings that aren't from our repository. This can happen - // with worktrees of submodules for instance. - let is_config_in_our_repo = section - .path - .as_deref() - .and_then(|p| gix_path::normalize(p.into(), current_dir)) - .is_some_and(|config_path| config_path.starts_with(&git_dir)); - if !is_config_in_our_repo { - return false; - } + .path_filter(Core::WORKTREE, |section| { + let res = + assure_config_is_from_current_repo(section, &git_dir, current_dir, &mut filter_config_section); + if res { key_source = Some(section.source); - true } + res }) .zip(key_source); if let Some((wt, key_source)) = worktree_path { @@ -302,7 +309,9 @@ impl ThreadSafeRepository { } else if !config.lenient_config && config .resolved - .boolean_filter(Core::WORKTREE, &mut filter_config_section) + .boolean_filter(Core::WORKTREE, |section| { + assure_config_is_from_current_repo(section, &git_dir, current_dir, &mut filter_config_section) + }) .is_some() { return Err(Error::from(config::Error::ConfigTypedString( diff --git a/gix/tests/gix-init.rs b/gix/tests/gix-init.rs index bfe92e7f3ce..a0eb77045db 100644 --- a/gix/tests/gix-init.rs +++ b/gix/tests/gix-init.rs @@ -1,22 +1,28 @@ #![allow(clippy::result_large_err)] + +use gix::open::Permissions; +use gix::{Repository, ThreadSafeRepository}; +use gix_sec::Permission; +use serial_test::serial; + +pub fn named_subrepo_opts( + fixture: &str, + name: &str, + opts: gix::open::Options, +) -> std::result::Result { + let repo_path = gix_testtools::scripted_fixture_read_only(fixture).unwrap().join(name); + Ok(ThreadSafeRepository::open_opts(repo_path, opts)?.to_thread_local()) +} + mod with_overrides { use std::borrow::Cow; - use gix::{Repository, ThreadSafeRepository}; + use crate::named_subrepo_opts; use gix_object::bstr::BStr; use gix_sec::Permission; use gix_testtools::Env; use serial_test::serial; - pub fn named_subrepo_opts( - fixture: &str, - name: &str, - opts: gix::open::Options, - ) -> std::result::Result { - let repo_path = gix_testtools::scripted_fixture_read_only(fixture).unwrap().join(name); - Ok(ThreadSafeRepository::open_opts(repo_path, opts)?.to_thread_local()) - } - #[test] #[serial] fn order_from_api_and_cli_and_environment() -> gix_testtools::Result { @@ -264,3 +270,21 @@ mod with_overrides { Cow::Borrowed(s.into()) } } + +#[test] +#[serial] +fn git_worktree_and_strict_config() -> gix_testtools::Result { + let _restore_env_on_drop = gix_testtools::Env::new().set("GIT_WORK_TREE", "."); + let _repo = named_subrepo_opts( + "make_empty_repo.sh", + "", + gix::open::Options::isolated() + .permissions({ + let mut perm = Permissions::isolated(); + perm.env.git_prefix = Permission::Allow; + perm + }) + .strict_config(true), + )?; + Ok(()) +}