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}