diff --git a/codex-rs/git-utils/src/git_command_tests.rs b/codex-rs/git-utils/src/git_command_tests.rs index 77366c0633..cf6e1b6f46 100644 --- a/codex-rs/git-utils/src/git_command_tests.rs +++ b/codex-rs/git-utils/src/git_command_tests.rs @@ -364,6 +364,14 @@ fn config_source_authority_allows_protected_metadata_and_unrelated_external_path "protected metadata config", ) .expect("protected metadata config"); + let canonical_config = + std::fs::canonicalize(root.join(".git/config")).expect("canonical metadata config"); + authority + .ensure_config_source_is_not_worktree_controlled( + &canonical_config, + "canonical protected metadata config", + ) + .expect("canonical protected metadata config"); authority .ensure_config_source_is_not_worktree_controlled(&external, "external config") .expect("unrelated external config"); diff --git a/codex-rs/git-utils/src/git_config_sources/primary_sources.rs b/codex-rs/git-utils/src/git_config_sources/primary_sources.rs index 2693bb943d..ed4866e510 100644 --- a/codex-rs/git-utils/src/git_config_sources/primary_sources.rs +++ b/codex-rs/git-utils/src/git_config_sources/primary_sources.rs @@ -224,11 +224,11 @@ fn git_home_directories() -> Vec { homes.push(home); } if let Some(profile) = std::env::var_os("USERPROFILE") - && !homes.iter().any(|home| *home == profile) + && !homes.contains(&profile) { homes.push(profile); } - return homes; + homes } #[cfg(not(windows))] Vec::new() diff --git a/codex-rs/git-utils/src/git_config_sources_tests.rs b/codex-rs/git-utils/src/git_config_sources_tests.rs index 8c12a1efbe..49a37e267f 100644 --- a/codex-rs/git-utils/src/git_config_sources_tests.rs +++ b/codex-rs/git-utils/src/git_config_sources_tests.rs @@ -41,6 +41,11 @@ fn init_repo_at(root: &Path) { #[cfg(windows)] fn create_junction(path: &Path, target: &Path) { + // Bazel's GNU Windows runner can surface temporary paths with `/` + // separators. `mklink` treats those separators as option prefixes, so + // pass native separators to the cmd.exe built-in. + let path = path.as_os_str().to_string_lossy().replace('/', "\\"); + let target = target.as_os_str().to_string_lossy().replace('/', "\\"); let output = std::process::Command::new("cmd.exe") .args(["/D", "/C", "mklink", "/J"]) .arg(path) @@ -830,14 +835,17 @@ fn rejects_every_duplicate_and_nested_include_target() { std::fs::write(root.join("driver-config"), "").expect("write nested target"); let external = tempfile::tempdir().expect("external config directory"); let outer = external.path().join("outer.gitconfig"); - std::fs::write( - &outer, - format!( - "[include]\npath = {}\n", - root.join("driver-config").display() - ), - ) - .expect("write outer config"); + let nested = root.join("driver-config"); + run_success( + root, + &[ + "config", + "--file", + outer.to_str().expect("UTF-8 outer path"), + "include.path", + nested.to_str().expect("UTF-8 nested path"), + ], + ); add_include( root, "include.path", @@ -1479,14 +1487,21 @@ fn rejects_apfs_data_firmlink_aliases_for_existing_and_missing_worktree_configs( } #[test] -fn include_path_expansion_preserves_colon_parentheses_as_literal_text() { +fn include_path_expansion_supports_git_prefix() { let repo = init_repo(); let root = repo.path(); let git = GitRunner::for_cwd_io(root).expect("Git runner"); let prefix = expand_git_config_path(&git, root, "%(prefix)/etc/gitconfig").expect("expand Git prefix"); assert!(prefix.is_absolute()); +} +#[cfg(not(windows))] +#[test] +fn include_path_expansion_preserves_colon_parentheses_as_literal_text() { + let repo = init_repo(); + let root = repo.path(); + let git = GitRunner::for_cwd_io(root).expect("Git runner"); let optional = GitConfigEntry { scope: crate::git_config::GitConfigScope::Local, origin: crate::git_config::GitConfigOrigin::File(".git/config".into()), @@ -1549,6 +1564,8 @@ fn windows_path_validator_rejects_namespaces_streams_and_alias_components() { r"\\.\pipe\config", r"C:\repo\config:stream", r"C:relative\config", + r":(optional)..\future.gitconfig", + r":(unknown)..\future.gitconfig", r"C:\repo\NUL.gitconfig", r"C:\repo\COM¹.gitconfig", r"C:\repo\LPT³.gitconfig", diff --git a/codex-rs/git-utils/src/path_authority.rs b/codex-rs/git-utils/src/path_authority.rs index 526dce750b..c27f9e698c 100644 --- a/codex-rs/git-utils/src/path_authority.rs +++ b/codex-rs/git-utils/src/path_authority.rs @@ -88,7 +88,7 @@ pub(crate) fn repository_route_boundaries( let canonical_root = std::fs::canonicalize(root)?; let canonical_marker = std::fs::canonicalize(&marker)?; if canonical_marker == canonical_root.join(".git") { - push_unique_location(&mut metadata_dirs, canonical_marker)?; + push_unique_location(&mut metadata_dirs, marker)?; } } for common in common_dirs {