style(tui): format shell dispatcher stack
This commit is contained in:
committed by
Hunter Bown
parent
6e5d8ddf01
commit
45e7b12583
@@ -14,12 +14,14 @@ use std::path::{Path, PathBuf};
|
||||
use std::time::{Duration, Instant};
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[cfg(test)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum EvalShellPlatform {
|
||||
Windows,
|
||||
Unix,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct EvalShellInvocation {
|
||||
program: &'static str,
|
||||
@@ -27,6 +29,7 @@ struct EvalShellInvocation {
|
||||
raw_payload_on_windows: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn eval_shell_invocation_for_platform(
|
||||
command: &str,
|
||||
platform: EvalShellPlatform,
|
||||
|
||||
@@ -63,9 +63,9 @@ mod schema_migration;
|
||||
mod seam_manager;
|
||||
#[allow(dead_code)]
|
||||
mod session_failure_classifier;
|
||||
mod shell_dispatcher;
|
||||
mod session_manager;
|
||||
mod settings;
|
||||
mod shell_dispatcher;
|
||||
mod skill_state;
|
||||
mod skills;
|
||||
mod snapshot;
|
||||
|
||||
@@ -868,4 +868,3 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ static LOG_MUTEX: Mutex<()> = Mutex::new(());
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// The concrete shell that the dispatcher will use.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ShellKind {
|
||||
/// PowerShell 7+ (`pwsh.exe`).
|
||||
@@ -104,6 +105,7 @@ pub struct ShellDispatcher {
|
||||
kind: ShellKind,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl ShellDispatcher {
|
||||
/// Detect the user's shell from the environment.
|
||||
///
|
||||
@@ -159,13 +161,10 @@ impl ShellDispatcher {
|
||||
// `detect()` which calls `log_startup()` which also acquires the mutex.
|
||||
let kind = global_dispatcher().kind();
|
||||
let _lock = LOG_MUTEX.lock();
|
||||
let line = format!(
|
||||
"[{}] exec via {kind:?}: {command}\n", now_iso()
|
||||
);
|
||||
let line = format!("[{}] exec via {kind:?}: {command}\n", now_iso());
|
||||
Self::append_log(path, &line)
|
||||
}
|
||||
|
||||
|
||||
/// The detected shell kind.
|
||||
pub fn kind(&self) -> &ShellKind {
|
||||
&self.kind
|
||||
@@ -233,9 +232,7 @@ impl ShellDispatcher {
|
||||
let _lock = LOG_MUTEX.lock();
|
||||
if let Ok(path) = std::env::var("SHELL_DISPATCHER_LOG") {
|
||||
let kind = self.kind();
|
||||
let line = format!(
|
||||
"[{}] exec via {kind:?}: {shell_command}\n", now_iso()
|
||||
);
|
||||
let line = format!("[{}] exec via {kind:?}: {shell_command}\n", now_iso());
|
||||
let _ = Self::append_log(&path, &line);
|
||||
}
|
||||
}
|
||||
@@ -318,7 +315,9 @@ impl ShellDispatcher {
|
||||
r"C:\Program Files\PowerShell\7",
|
||||
r"C:\Windows\System32\WindowsPowerShell\v1.0",
|
||||
];
|
||||
known_dirs.iter().any(|dir| std::path::Path::new(dir).join(name).is_file())
|
||||
known_dirs
|
||||
.iter()
|
||||
.any(|dir| std::path::Path::new(dir).join(name).is_file())
|
||||
}
|
||||
|
||||
fn binary_on_path(name: &str) -> bool {
|
||||
@@ -336,7 +335,9 @@ impl ShellDispatcher {
|
||||
// -- Helpers ---------------------------------------------------------------
|
||||
|
||||
fn now_iso() -> String {
|
||||
chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.3f").to_string()
|
||||
chrono::Utc::now()
|
||||
.format("%Y-%m-%dT%H:%M:%S%.3f")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
/// Global dispatcher instance, detected once at startup.
|
||||
@@ -384,7 +385,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn powershell_build_command_includes_no_profile_and_command_flags() {
|
||||
let dispatcher = ShellDispatcher { kind: ShellKind::Pwsh };
|
||||
let dispatcher = ShellDispatcher {
|
||||
kind: ShellKind::Pwsh,
|
||||
};
|
||||
let cmd = dispatcher.build_command("echo hello");
|
||||
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
|
||||
assert!(args.contains(&"-NoProfile"));
|
||||
@@ -394,7 +397,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn cmd_build_command_uses_c_flag() {
|
||||
let dispatcher = ShellDispatcher { kind: ShellKind::Cmd };
|
||||
let dispatcher = ShellDispatcher {
|
||||
kind: ShellKind::Cmd,
|
||||
};
|
||||
let cmd = dispatcher.build_command("echo hello");
|
||||
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
|
||||
assert!(args.contains(&"/C"));
|
||||
@@ -403,7 +408,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn sh_build_command_uses_dash_c() {
|
||||
let dispatcher = ShellDispatcher { kind: ShellKind::Sh };
|
||||
let dispatcher = ShellDispatcher {
|
||||
kind: ShellKind::Sh,
|
||||
};
|
||||
let cmd = dispatcher.build_command("echo hello");
|
||||
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
|
||||
assert!(args.contains(&"-c"));
|
||||
@@ -412,7 +419,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn build_direct_preserves_args() {
|
||||
let dispatcher = ShellDispatcher { kind: ShellKind::Cmd };
|
||||
let dispatcher = ShellDispatcher {
|
||||
kind: ShellKind::Cmd,
|
||||
};
|
||||
let args = vec!["-m".to_string(), "commit message".to_string()];
|
||||
let cmd = dispatcher.build_direct("git", &args);
|
||||
let cmd_args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
|
||||
@@ -439,7 +448,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn build_command_quotes_spaces_for_cmd() {
|
||||
let dispatcher = ShellDispatcher { kind: ShellKind::Cmd };
|
||||
let dispatcher = ShellDispatcher {
|
||||
kind: ShellKind::Cmd,
|
||||
};
|
||||
let cmd = dispatcher.build_command("git commit -m \"msg with spaces\"");
|
||||
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
|
||||
assert_eq!(args.len(), 2);
|
||||
@@ -450,7 +461,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn build_command_quotes_spaces_for_pwsh() {
|
||||
let dispatcher = ShellDispatcher { kind: ShellKind::Pwsh };
|
||||
let dispatcher = ShellDispatcher {
|
||||
kind: ShellKind::Pwsh,
|
||||
};
|
||||
let cmd = dispatcher.build_command("git commit -m \"msg with spaces\"");
|
||||
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
|
||||
assert_eq!(args.len(), 3);
|
||||
@@ -461,7 +474,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn build_direct_handles_empty_args() {
|
||||
let dispatcher = ShellDispatcher { kind: ShellKind::Sh };
|
||||
let dispatcher = ShellDispatcher {
|
||||
kind: ShellKind::Sh,
|
||||
};
|
||||
let cmd = dispatcher.build_direct("echo", &[]);
|
||||
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
|
||||
assert!(args.is_empty());
|
||||
@@ -499,4 +514,4 @@ mod tests {
|
||||
assert_eq!(kind.binary(), "/bin/zsh");
|
||||
assert_eq!(kind.command_flag(), "-c");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -850,7 +850,11 @@ impl ShellManager {
|
||||
// success/failure/timeout (issue #1690).
|
||||
let _ = crossterm::terminal::disable_raw_mode();
|
||||
struct SyncRawModeGuard;
|
||||
impl Drop for SyncRawModeGuard { fn drop(&mut self) { let _ = crossterm::terminal::enable_raw_mode(); } }
|
||||
impl Drop for SyncRawModeGuard {
|
||||
fn drop(&mut self) {
|
||||
let _ = crossterm::terminal::enable_raw_mode();
|
||||
}
|
||||
}
|
||||
let _guard = SyncRawModeGuard;
|
||||
|
||||
let mut child = cmd
|
||||
@@ -990,7 +994,11 @@ impl ShellManager {
|
||||
// Disable raw mode before spawn; restore on drop (issue #1690).
|
||||
let _ = crossterm::terminal::disable_raw_mode();
|
||||
struct InteractiveRawModeGuard;
|
||||
impl Drop for InteractiveRawModeGuard { fn drop(&mut self) { let _ = crossterm::terminal::enable_raw_mode(); } }
|
||||
impl Drop for InteractiveRawModeGuard {
|
||||
fn drop(&mut self) {
|
||||
let _ = crossterm::terminal::enable_raw_mode();
|
||||
}
|
||||
}
|
||||
let _guard = InteractiveRawModeGuard;
|
||||
|
||||
child_env::apply_to_command(&mut cmd, child_env::string_map_env(&exec_env.env));
|
||||
@@ -2810,4 +2818,4 @@ impl ToolSpec for NoteTool {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod tests;
|
||||
|
||||
@@ -4,6 +4,8 @@ use std::fs;
|
||||
|
||||
#[path = "../src/eval.rs"]
|
||||
mod eval;
|
||||
#[path = "../src/shell_dispatcher.rs"]
|
||||
mod shell_dispatcher;
|
||||
|
||||
use eval::{EvalHarness, EvalHarnessConfig, ScenarioStepKind};
|
||||
use tempfile::tempdir;
|
||||
|
||||
Reference in New Issue
Block a user