forge_tree/generator/
file_generator.rs

1//! File and directory creation utilities
2//! 
3//! This module handles the actual filesystem operations for creating
4//! directories and files, with support for force overwrite mode.
5
6use crate::{Result, ForgeTreeError};
7use std::fs;
8use std::path::Path;
9
10/// Handles creation of files and directories on the filesystem
11/// 
12/// FileGenerator provides safe file operations with configurable
13/// overwrite behavior and proper error handling.
14pub struct FileGenerator {
15    /// Whether to overwrite existing files without error
16    force_overwrite: bool,
17}
18
19impl FileGenerator {
20    /// Create a new FileGenerator with default settings (no force overwrite)
21    pub fn new() -> Self {
22        Self {
23            force_overwrite: false,
24        }
25    }
26
27    /// Configure whether existing files should be overwritten
28    /// 
29    /// When force_overwrite is true, existing files will be replaced.
30    /// When false, attempting to create existing files will return an error.
31    pub fn with_force_overwrite(mut self, force: bool) -> Self {
32        self.force_overwrite = force;
33        self
34    }
35
36    /// Create a directory and all necessary parent directories
37    /// 
38    /// This method:
39    /// - Creates the directory and any missing parent directories
40    /// - Handles the case where the path already exists as a directory
41    /// - Returns an error if the path exists but is not a directory
42    pub fn create_directory<P: AsRef<Path>>(&self, path: P) -> Result<()> {
43        let path = path.as_ref();
44        
45        // Check if path exists and is not a directory (e.g., it's a file)
46        if path.exists() && !path.is_dir() {
47            return Err(ForgeTreeError::InvalidPath(
48                format!("Path exists but is not a directory: {}", path.display())
49            ));
50        }
51
52        // create_dir_all is idempotent - it won't error if directory already exists
53        fs::create_dir_all(path)?;
54        Ok(())
55    }
56
57    /// Create a file with the specified content
58    /// 
59    /// This method:
60    /// - Checks for existing files and respects the force_overwrite setting
61    /// - Creates parent directories if they don't exist
62    /// - Writes the content to the file (overwrites if file exists and force is true)
63    pub fn create_file<P: AsRef<Path>>(&self, path: P, content: &str) -> Result<()> {
64        let path = path.as_ref();
65
66        // Check if file already exists and we're not in force mode
67        if path.exists() && !self.force_overwrite {
68            return Err(ForgeTreeError::FileExists(path.display().to_string()));
69        }
70
71        // Ensure the parent directory exists before creating the file
72        if let Some(parent) = path.parent() {
73            self.create_directory(parent)?;
74        }
75
76        // fs::write automatically creates or overwrites the file
77        fs::write(path, content)?;
78        Ok(())
79    }
80}
81
82impl Default for FileGenerator {
83    fn default() -> Self {
84        Self::new()
85    }
86}