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