[codex] preserve fsmonitor for worktree Git reads (#26880)

Codex forces `core.fsmonitor=false` on internal Git commands so a
repository cannot select an executable fsmonitor helper. This also
disables Git's built-in daemon for `status`, `diff`, and `ls-files`,
turning those worktree reads into full scans in large repositories.

Read the raw effective `core.fsmonitor` value and preserve it only when
Git interprets it as true and advertises built-in daemon support through
`git version --build-options`. Query uncommon boolean spellings back
through Git using the exact effective value. Unset, false, helper paths,
malformed values, probe failures, and unsupported Git builds continue to
force `core.fsmonitor=false`.

Centralize this policy in `git-utils` while keeping process execution in
the existing local and workspace-command adapters. Probe once per
worktree workflow and reuse the result for its Git commands, including
the TUI `/diff` path. Metadata-only commands and repository discovery
remain disabled without probing. Each probe and requested Git process
keeps its own existing timeout, and the decision is not cached because
layered and conditional Git configuration can change while Codex runs.

---------

Co-authored-by: Chris Bookholt <bookholt@openai.com>
This commit is contained in:
Tamir Duberstein
2026-06-08 21:32:46 -07:00
committed by GitHub
Unverified
parent 08cb633c06
commit dffc4bf75d
6 changed files with 831 additions and 203 deletions
-40
View File
@@ -340,46 +340,6 @@ async fn test_get_has_changes_with_untracked_change_returns_true() {
assert_eq!(get_has_changes(&repo_path).await, Some(true));
}
#[cfg(unix)]
#[tokio::test]
async fn test_get_has_changes_ignores_repo_fsmonitor_config() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let repo_path = create_test_git_repo(&temp_dir).await;
let helper_path = repo_path.join("fsmonitor-helper.sh");
let marker_path = repo_path.join("fsmonitor-ran");
fs::write(
&helper_path,
format!(
"#!/bin/sh\nprintf ran > \"{}\"\n",
marker_path.to_string_lossy()
),
)
.expect("write fsmonitor helper");
let mut permissions = fs::metadata(&helper_path)
.expect("read fsmonitor helper metadata")
.permissions();
permissions.set_mode(0o755);
fs::set_permissions(&helper_path, permissions).expect("mark fsmonitor helper executable");
Command::new("git")
.args([
"config",
"core.fsmonitor",
helper_path.to_string_lossy().as_ref(),
])
.current_dir(&repo_path)
.output()
.await
.expect("configure fsmonitor helper");
assert_eq!(get_has_changes(&repo_path).await, Some(true));
assert!(
!marker_path.exists(),
"metadata collection should not invoke repository fsmonitor helpers"
);
}
#[cfg(unix)]
#[tokio::test]
async fn test_get_has_changes_ignores_configured_hooks_path() {