app_path/app_path/
directory.rs

1use crate::{AppPath, AppPathError};
2
3impl AppPath {
4    /// Creates parent directories needed for this file path.
5    ///
6    /// This method creates all parent directories for a file path, making it ready
7    /// for file creation. It does not create the file itself.
8    ///
9    /// **Use this when you know the path represents a file and you want to prepare
10    /// the directory structure for writing the file.**
11    ///
12    /// # Examples
13    ///
14    /// ```rust
15    /// use app_path::AppPath;
16    /// use std::fs;
17    ///
18    /// // Prepare directories for a log file relative to your app
19    /// let log_file = AppPath::with("logs/2024/app.log");
20    /// log_file.create_parents()?; // Creates logs/2024/ directories
21    ///
22    /// // Parent directories exist, but file does not
23    /// let logs_dir = AppPath::with("logs");
24    /// let year_dir = AppPath::with("logs/2024");
25    /// assert!(logs_dir.exists());
26    /// assert!(year_dir.exists());
27    /// assert!(!log_file.exists()); // File not created, only parent dirs
28    ///
29    /// // Now you can write the file
30    /// fs::write(&log_file, "Log entry")?;
31    /// assert!(log_file.exists());
32    ///
33    /// # std::fs::remove_dir_all(&AppPath::with("logs")).ok();
34    /// # Ok::<(), Box<dyn std::error::Error>>(())
35    /// ```
36    ///
37    /// ## Complex Directory Structures
38    ///
39    /// ```rust
40    /// use app_path::AppPath;
41    /// use std::fs;
42    ///
43    /// // Create parents for config file
44    /// let config_file = AppPath::with("config/database/settings.toml");
45    /// config_file.create_parents()?; // Creates config/database/ directories
46    ///
47    /// // Create parents for data file  
48    /// let data_file = AppPath::with("data/users/profiles.db");
49    /// data_file.create_parents()?; // Creates data/users/ directories
50    ///
51    /// // All parent directories exist
52    /// assert!(AppPath::with("config").exists());
53    /// assert!(AppPath::with("config/database").exists());
54    /// assert!(AppPath::with("data").exists());
55    /// assert!(AppPath::with("data/users").exists());
56    ///
57    /// # std::fs::remove_dir_all(&AppPath::with("config")).ok();
58    /// # std::fs::remove_dir_all(&AppPath::with("data")).ok();
59    /// # Ok::<(), app_path::AppPathError>(())
60    /// ```
61    ///
62    /// # Errors
63    ///
64    /// Returns [`AppPathError::IoError`] if directory creation fails:
65    /// - **Insufficient permissions** - Cannot create directories due to filesystem permissions
66    /// - **Disk space exhausted** - Not enough space to create directory entries
67    /// - **Invalid path characters** - Path contains characters invalid for the target filesystem
68    /// - **Network filesystem issues** - Problems with remote/networked filesystems
69    /// - **Filesystem corruption** - Underlying filesystem errors
70    ///
71    /// The operation is **not atomic** - some parent directories may be created even if the
72    /// operation ultimately fails.
73    #[inline]
74    pub fn create_parents(&self) -> Result<(), AppPathError> {
75        if let Some(parent) = self.full_path.parent() {
76            std::fs::create_dir_all(parent)?;
77        }
78        Ok(())
79    }
80
81    /// Creates this path as a directory, including all parent directories.
82    ///
83    /// This method treats the path as a directory and creates it along with
84    /// all necessary parent directories. The created directory will exist
85    /// after this call succeeds.
86    ///
87    /// **Use this when you know the path represents a directory that should be created.**
88    ///
89    /// # Behavior
90    ///
91    /// - **Creates the directory itself**: Unlike `create_parents()`, this creates the full path as a directory
92    /// - **Creates all parents**: Any missing parent directories are created automatically
93    /// - **Idempotent**: Safe to call multiple times - won't fail if directory already exists
94    /// - **Atomic-like**: Either all directories are created or the operation fails
95    ///
96    /// # Examples
97    ///
98    /// ## Basic Directory Creation
99    ///
100    /// ```rust
101    /// use app_path::AppPath;
102    ///
103    /// // Create a cache directory relative to your app
104    /// let cache_dir = AppPath::with("cache");
105    /// cache_dir.create_dir()?; // Creates cache/ directory
106    /// assert!(cache_dir.exists());
107    /// assert!(cache_dir.is_dir());
108    ///
109    /// # std::fs::remove_dir_all(&cache_dir).ok();
110    /// # Ok::<(), Box<dyn std::error::Error>>(())
111    /// ```
112    ///
113    /// ## Nested Directory Structures
114    ///
115    /// ```rust
116    /// use app_path::AppPath;
117    ///
118    /// // Create deeply nested directories
119    /// let deep_dir = AppPath::with("data/backups/daily");
120    /// deep_dir.create_dir()?; // Creates data/backups/daily/ directories
121    /// assert!(deep_dir.exists());
122    /// assert!(deep_dir.is_dir());
123    ///
124    /// // All parent directories are also created
125    /// let backups_dir = AppPath::with("data/backups");
126    /// assert!(backups_dir.exists());
127    /// assert!(backups_dir.is_dir());
128    ///
129    /// # std::fs::remove_dir_all(&AppPath::with("data")).ok();
130    /// # Ok::<(), Box<dyn std::error::Error>>(())
131    /// ```
132    ///
133    /// ## Practical Application Setup
134    ///
135    /// ```rust
136    /// use app_path::AppPath;
137    ///
138    /// // Set up application directory structure
139    /// let config_dir = AppPath::with("config");
140    /// let data_dir = AppPath::with("data");
141    /// let cache_dir = AppPath::with("cache");
142    /// let logs_dir = AppPath::with("logs");
143    ///
144    /// // Create all directories
145    /// config_dir.create_dir()?;
146    /// data_dir.create_dir()?;
147    /// cache_dir.create_dir()?;
148    /// logs_dir.create_dir()?;
149    ///
150    /// // Now create subdirectories
151    /// let daily_logs = logs_dir.join("daily");
152    /// daily_logs.create_dir()?;
153    ///
154    /// // Verify structure
155    /// assert!(config_dir.is_dir());
156    /// assert!(data_dir.is_dir());
157    /// assert!(cache_dir.is_dir());
158    /// assert!(logs_dir.is_dir());
159    /// assert!(daily_logs.is_dir());
160    ///
161    /// # std::fs::remove_dir_all(&config_dir).ok();
162    /// # std::fs::remove_dir_all(&data_dir).ok();
163    /// # std::fs::remove_dir_all(&cache_dir).ok();
164    /// # std::fs::remove_dir_all(&logs_dir).ok();
165    /// # Ok::<(), Box<dyn std::error::Error>>(())
166    /// ```
167    ///
168    /// ## Comparison with `create_parents()`
169    ///
170    /// ```rust
171    /// use app_path::AppPath;
172    ///
173    /// let file_path = AppPath::with("logs/app.log");
174    /// let dir_path = AppPath::with("logs");
175    ///
176    /// // For files: prepare parent directories
177    /// file_path.create_parents()?; // Creates logs/ directory
178    /// assert!(dir_path.exists()); // logs/ directory exists
179    /// assert!(!file_path.exists()); // app.log file does NOT exist
180    ///
181    /// // For directories: create the directory itself  
182    /// dir_path.create_dir()?; // Creates logs/ directory (idempotent)
183    /// assert!(dir_path.exists()); // logs/ directory exists
184    /// assert!(dir_path.is_dir()); // and it's definitely a directory
185    ///
186    /// # std::fs::remove_dir_all(&dir_path).ok();
187    /// # Ok::<(), app_path::AppPathError>(())
188    /// ```
189    ///
190    /// # Errors
191    ///
192    /// Returns [`AppPathError::IoError`] if directory creation fails:
193    /// - **Insufficient permissions** - Cannot create directories due to filesystem permissions
194    /// - **Disk space exhausted** - Not enough space to create directory entries  
195    /// - **Invalid path characters** - Path contains characters invalid for the target filesystem
196    /// - **Network filesystem issues** - Problems with remote/networked filesystems
197    /// - **Path already exists as file** - A file already exists at this path (not a directory)
198    /// - **Filesystem corruption** - Underlying filesystem errors
199    ///
200    /// The operation creates parent directories as needed, but is **not atomic** - some
201    /// parent directories may be created even if the final directory creation fails.
202    #[inline]
203    pub fn create_dir(&self) -> Result<(), AppPathError> {
204        std::fs::create_dir_all(self)?;
205        Ok(())
206    }
207}