Skip to main content

command_stream/commands/
cd.rs

1//! Virtual `cd` command implementation
2
3use crate::commands::CommandContext;
4use crate::utils::{trace, CommandResult};
5use std::env;
6use std::path::PathBuf;
7
8/// Execute the cd command
9///
10/// Changes the current working directory.
11pub async fn cd(ctx: CommandContext) -> CommandResult {
12    let target = if ctx.args.is_empty() {
13        // No argument - go to home directory
14        env::var("HOME")
15            .or_else(|_| env::var("USERPROFILE"))
16            .unwrap_or_else(|_| "/".to_string())
17    } else {
18        ctx.args[0].clone()
19    };
20
21    trace(
22        "VirtualCommand",
23        &format!("cd: changing directory to {:?}", target),
24    );
25
26    let path = PathBuf::from(&target);
27
28    match env::set_current_dir(&path) {
29        Ok(()) => {
30            let new_dir = env::current_dir()
31                .map(|p| p.display().to_string())
32                .unwrap_or_default();
33            trace(
34                "VirtualCommand",
35                &format!("cd: success, new dir: {}", new_dir),
36            );
37            // cd command should not output anything on success
38            CommandResult::success_empty()
39        }
40        Err(e) => {
41            trace("VirtualCommand", &format!("cd: failed: {}", e));
42            CommandResult::error(format!("cd: {}\n", e))
43        }
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use tempfile::tempdir;
51
52    #[tokio::test]
53    async fn test_cd_to_temp() {
54        let temp = tempdir().unwrap();
55        let temp_path = temp.path().to_string_lossy().to_string();
56        let original_dir = env::current_dir().unwrap();
57
58        let ctx = CommandContext::new(vec![temp_path.clone()]);
59        let result = cd(ctx).await;
60        assert!(result.is_success());
61        assert_eq!(result.stdout, "");
62
63        // Restore original directory
64        env::set_current_dir(original_dir).unwrap();
65    }
66
67    #[tokio::test]
68    async fn test_cd_to_nonexistent() {
69        let ctx = CommandContext::new(vec!["/nonexistent/path/12345".to_string()]);
70        let result = cd(ctx).await;
71        assert!(!result.is_success());
72    }
73}