From c082f0d168a6bcd420acabfaebcec4975c29bfe3 Mon Sep 17 00:00:00 2001 From: jimmyfraiture Date: Wed, 10 Sep 2025 14:03:18 -0700 Subject: [PATCH] Using tokio watch instead --- codex-rs/core/src/codex.rs | 6 ++- codex-rs/core/src/shell.rs | 84 +++++++++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 25 deletions(-) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index df182babb1..8f9f8c0f26 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -2306,7 +2306,7 @@ fn should_translate_shell_command( || shell_policy.use_profile || matches!( shell, - crate::shell::Shell::Posix(shell) if shell.shell_snapshot.is_some() + crate::shell::Shell::Posix(shell) if shell.shell_snapshot.borrow().is_some() ) } @@ -2964,10 +2964,12 @@ mod tests { } fn zsh_shell(shell_snapshot: Option>) -> shell::Shell { + let (_tx, rx) = + tokio::sync::watch::channel(shell_snapshot); shell::Shell::Posix(shell::PosixShell { shell_path: "/bin/zsh".to_string(), rc_path: "/Users/example/.zshrc".to_string(), - shell_snapshot, + shell_snapshot: rx, }) } diff --git a/codex-rs/core/src/shell.rs b/codex-rs/core/src/shell.rs index d1f3b2ccbf..d2acf75c20 100644 --- a/codex-rs/core/src/shell.rs +++ b/codex-rs/core/src/shell.rs @@ -13,6 +13,14 @@ pub struct ShellSnapshot { pub(crate) path: PathBuf, } +// Usage of fully qualified names for the Receiver for clarity. +type ShellSnapshotRx = tokio::sync::watch::Receiver>>; + +pub fn default_shell_snapshot_rx() -> ShellSnapshotRx { + let (_tx, rx) = tokio::sync::watch::channel(None); + rx +} + impl ShellSnapshot { pub fn new(path: PathBuf) -> Self { Self { path } @@ -25,14 +33,27 @@ impl Drop for ShellSnapshot { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct PosixShell { pub(crate) shell_path: String, pub(crate) rc_path: String, - #[serde(skip_serializing, skip_deserializing)] - pub(crate) shell_snapshot: Option>, + #[serde( + skip_serializing, + skip_deserializing, + default = "default_shell_snapshot_rx" + )] + pub(crate) shell_snapshot: ShellSnapshotRx, } +impl PartialEq for PosixShell { + fn eq(&self, other: &Self) -> bool { + self.shell_path == other.shell_path && self.rc_path == other.rc_path + // deliberately ignore `shell_snapshot` as the RX does not implement PartialEq. + } +} +// Rely on the default implementation. +impl Eq for PosixShell {} + #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct PowerShellConfig { exe: String, // Executable name or path, e.g. "pwsh" or "powershell.exe". @@ -55,7 +76,8 @@ impl Shell { let mut source_path = Path::new(&shell.rc_path); - let session_cmd = if let Some(shell_snapshot) = &shell.shell_snapshot + let shell_snapshot = shell.shell_snapshot.borrow().clone(); + let session_cmd = if let Some(shell_snapshot) = shell_snapshot.as_ref() && shell_snapshot.path.exists() { source_path = shell_snapshot.path.as_path(); @@ -132,7 +154,7 @@ impl Shell { pub fn get_snapshot(&self) -> Option> { match self { - Shell::Posix(shell) => shell.shell_snapshot.clone(), + Shell::Posix(shell) => shell.shell_snapshot.borrow().clone(), _ => None, } } @@ -175,24 +197,37 @@ async fn detect_default_user_shell(session_id: Uuid, codex_home: &Path) -> Shell return Shell::Unknown; }; - let snapshot_path = snapshots::ensure_posix_snapshot( - &shell_path, - &rc_path, - Path::new(&home_path), - codex_home, - session_id, - ) - .await; - if snapshot_path.is_none() { - trace!("failed to prepare posix snapshot; using live profile"); + let (tx, rx) = tokio::sync::watch::channel(None); + + { + let shell_path = shell_path.clone(); + let rc_path = rc_path.clone(); + let home_path = home_path.clone(); + let codex_home = codex_home.to_path_buf(); + tokio::spawn(async move { + let snapshot_path = snapshots::ensure_posix_snapshot( + &shell_path, + &rc_path, + Path::new(&home_path), + codex_home.as_path(), + session_id, + ) + .await; + if snapshot_path.is_none() { + trace!("failed to prepare posix snapshot; using live profile"); + } + let shell_snapshot = + snapshot_path.map(|snapshot| Arc::new(ShellSnapshot::new(snapshot))); + if tx.send(shell_snapshot).is_err() { + trace!("failed to send posix snapshot; using live profile"); + } + }); } - let shell_snapshot = - snapshot_path.map(|snapshot| Arc::new(ShellSnapshot::new(snapshot))); return Shell::Posix(PosixShell { shell_path, rc_path, - shell_snapshot, + shell_snapshot: rx, }); } } @@ -386,7 +421,7 @@ pub(crate) fn delete_shell_snapshot(path: &Path) { #[cfg(test)] #[cfg(unix)] -mod tests { +pub(crate) mod tests { use super::*; use std::path::PathBuf; @@ -396,7 +431,7 @@ mod tests { let shell = Shell::Posix(PosixShell { shell_path: "/bin/zsh".to_string(), rc_path: "/does/not/exist/.zshrc".to_string(), - shell_snapshot: None, + shell_snapshot: default_shell_snapshot_rx(), }); let actual_cmd = shell.format_default_shell_invocation(vec!["myecho".to_string()]); assert_eq!( @@ -457,7 +492,7 @@ mod tests { let shell = Shell::Posix(PosixShell { shell_path: shell_path.to_string(), rc_path: bashrc_path.to_str().unwrap().to_string(), - shell_snapshot: None, + shell_snapshot: default_shell_snapshot_rx(), }); let actual_cmd = shell @@ -565,6 +600,9 @@ mod macos_tests { let snapshot_path = temp_dir.path().join("snapshot.zsh"); std::fs::write(&snapshot_path, "export SNAPSHOT_READY=1").unwrap(); + let (_tx, rx) = + tokio::sync::watch::channel(Some(Arc::new(ShellSnapshot::new(snapshot_path.clone())))); + let shell = Shell::Posix(PosixShell { shell_path: "/bin/zsh".to_string(), rc_path: { @@ -572,7 +610,7 @@ mod macos_tests { std::fs::write(&path, "# test zshrc").unwrap(); path.to_string_lossy().to_string() }, - shell_snapshot: Some(Arc::new(ShellSnapshot::new(snapshot_path.clone()))), + shell_snapshot: rx, }); let invocation = shell.format_default_shell_invocation(vec!["echo".to_string()]); @@ -651,7 +689,7 @@ mod macos_tests { let shell = Shell::Posix(PosixShell { shell_path: shell_path.to_string(), rc_path: zshrc_path.to_str().unwrap().to_string(), - shell_snapshot: None, + shell_snapshot: default_shell_snapshot_rx(), }); let actual_cmd = shell