Skip to main content

command_stream/commands/
mkdir.rs

1//! Virtual `mkdir` command implementation
2
3use crate::commands::CommandContext;
4use crate::utils::{trace_lazy, CommandResult, VirtualUtils};
5use std::fs;
6
7/// Execute the mkdir command
8///
9/// Creates directories.
10pub async fn mkdir(ctx: CommandContext) -> CommandResult {
11    if ctx.args.is_empty() {
12        return VirtualUtils::missing_operand_error("mkdir");
13    }
14
15    // Check for -p flag
16    let mut create_parents = false;
17    let mut dirs = Vec::new();
18
19    for arg in &ctx.args {
20        if arg == "-p" {
21            create_parents = true;
22        } else if arg.starts_with('-') {
23            // Skip other flags
24        } else {
25            dirs.push(arg.clone());
26        }
27    }
28
29    if dirs.is_empty() {
30        return VirtualUtils::missing_operand_error("mkdir");
31    }
32
33    let cwd = ctx.get_cwd();
34
35    for dir in dirs {
36        let resolved_path = VirtualUtils::resolve_path(&dir, Some(&cwd));
37
38        trace_lazy("VirtualCommand", || {
39            format!(
40                "mkdir: creating directory {:?}, parents: {}",
41                resolved_path, create_parents
42            )
43        });
44
45        let result = if create_parents {
46            fs::create_dir_all(&resolved_path)
47        } else {
48            fs::create_dir(&resolved_path)
49        };
50
51        if let Err(e) = result {
52            return CommandResult::error(format!(
53                "mkdir: cannot create directory '{}': {}\n",
54                dir, e
55            ));
56        }
57    }
58
59    CommandResult::success_empty()
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use tempfile::tempdir;
66
67    #[tokio::test]
68    async fn test_mkdir_simple() {
69        let temp = tempdir().unwrap();
70        let new_dir = temp.path().join("new_directory");
71
72        let ctx = CommandContext::new(vec![new_dir.to_string_lossy().to_string()]);
73        let result = mkdir(ctx).await;
74
75        assert!(result.is_success());
76        assert!(new_dir.exists());
77    }
78
79    #[tokio::test]
80    async fn test_mkdir_with_parents() {
81        let temp = tempdir().unwrap();
82        let nested_dir = temp.path().join("a/b/c/d");
83
84        let ctx = CommandContext::new(vec![
85            "-p".to_string(),
86            nested_dir.to_string_lossy().to_string(),
87        ]);
88        let result = mkdir(ctx).await;
89
90        assert!(result.is_success());
91        assert!(nested_dir.exists());
92    }
93
94    #[tokio::test]
95    async fn test_mkdir_missing_operand() {
96        let ctx = CommandContext::new(vec![]);
97        let result = mkdir(ctx).await;
98
99        assert!(!result.is_success());
100        assert!(result.stderr.contains("missing operand"));
101    }
102}