From e332154dd4d76f33b5ce318947b34b064469447a Mon Sep 17 00:00:00 2001 From: Dylan Hurd Date: Wed, 6 Aug 2025 06:24:57 -0700 Subject: [PATCH] git repo once --- codex-rs/core/src/codex.rs | 17 +++++++++++++---- codex-rs/core/src/rollout.rs | 14 +++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index c85b1ce2b9..d551e1b51c 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -52,6 +52,7 @@ use crate::exec::SandboxType; use crate::exec::StdoutStream; use crate::exec::process_exec_tool_call; use crate::exec_env::create_env; +use crate::git_info::GitInfo; use crate::git_info::collect_git_info; use crate::mcp_connection_manager::McpConnectionManager; use crate::mcp_tool_call::handle_mcp_tool_call; @@ -213,6 +214,7 @@ pub(crate) struct Session { /// the model as well as sandbox policies are resolved against this path /// instead of `std::env::current_dir()`. pub(crate) cwd: PathBuf, + git_info: Option, base_instructions: Option, user_instructions: Option, pub(crate) approval_policy: AskForApproval, @@ -725,11 +727,12 @@ async fn submission_loop( } return; } + let git_info = collect_git_info(&cwd).await; // Optionally resume an existing rollout. let mut restored_items: Option> = None; let rollout_recorder: Option = if let Some(path) = resume_path.as_ref() { - match RolloutRecorder::resume(path, cwd.clone()).await { + match RolloutRecorder::resume(path, git_info.clone()).await { Ok((rec, saved)) => { session_id = saved.session_id; if !saved.items.is_empty() { @@ -749,8 +752,13 @@ async fn submission_loop( let rollout_recorder = match rollout_recorder { Some(rec) => Some(rec), None => { - match RolloutRecorder::new(&config, session_id, user_instructions.clone()) - .await + match RolloutRecorder::new( + &config, + session_id, + user_instructions.clone(), + git_info.clone(), + ) + .await { Ok(r) => Some(r), Err(e) => { @@ -829,6 +837,7 @@ async fn submission_loop( sandbox_policy, shell_environment_policy: config.shell_environment_policy.clone(), cwd, + git_info, writable_roots, mcp_connection_manager, notify, @@ -1228,7 +1237,7 @@ async fn run_turn( base_instructions_override: sess.base_instructions.clone(), environment_context: Some(EnvironmentContext { cwd: sess.cwd.clone(), - git_info: collect_git_info(&sess.cwd).await, + git_info: sess.git_info.clone(), approval_policy: sess.approval_policy, sandbox_policy: sess.sandbox_policy.clone(), }), diff --git a/codex-rs/core/src/rollout.rs b/codex-rs/core/src/rollout.rs index 0ccd8e891b..07bff23c51 100644 --- a/codex-rs/core/src/rollout.rs +++ b/codex-rs/core/src/rollout.rs @@ -21,7 +21,6 @@ use uuid::Uuid; use crate::config::Config; use crate::git_info::GitInfo; -use crate::git_info::collect_git_info; use crate::models::ResponseItem; const SESSIONS_SUBDIR: &str = "sessions"; @@ -82,6 +81,7 @@ impl RolloutRecorder { config: &Config, uuid: Uuid, instructions: Option, + git_info: Option, ) -> std::io::Result { let LogFileInfo { file, @@ -96,9 +96,6 @@ impl RolloutRecorder { .format(timestamp_format) .map_err(|e| IoError::other(format!("failed to format timestamp: {e}")))?; - // Clone the cwd for the spawned task to collect git info asynchronously - let cwd = config.cwd.clone(); - // A reasonably-sized bounded channel. If the buffer fills up the send // future will yield, which is fine – we only need to ensure we do not // perform *blocking* I/O on the caller's thread. @@ -115,7 +112,7 @@ impl RolloutRecorder { id: session_id, instructions, }), - cwd, + git_info, )); Ok(Self { tx }) @@ -157,7 +154,7 @@ impl RolloutRecorder { pub async fn resume( path: &Path, - cwd: std::path::PathBuf, + git_info: Option, ) -> std::io::Result<(Self, SavedSession)> { info!("Resuming rollout from {path:?}"); let text = tokio::fs::read_to_string(path).await?; @@ -220,7 +217,7 @@ impl RolloutRecorder { tokio::fs::File::from_std(file), rx, None, - cwd, + git_info, )); info!("Resumed rollout successfully from {path:?}"); Ok((Self { tx }, saved)) @@ -291,13 +288,12 @@ async fn rollout_writer( file: tokio::fs::File, mut rx: mpsc::Receiver, mut meta: Option, - cwd: std::path::PathBuf, + git_info: Option, ) -> std::io::Result<()> { let mut writer = JsonlWriter { file }; // If we have a meta, collect git info asynchronously and write meta first if let Some(session_meta) = meta.take() { - let git_info = collect_git_info(&cwd).await; let session_meta_with_git = SessionMetaWithGit { meta: session_meta, git: git_info,