diff options
Diffstat (limited to 'src/platform/paths.rs')
| -rw-r--r-- | src/platform/paths.rs | 270 |
1 files changed, 247 insertions, 23 deletions
diff --git a/src/platform/paths.rs b/src/platform/paths.rs index b430f09..07313fd 100644 --- a/src/platform/paths.rs +++ b/src/platform/paths.rs | |||
| @@ -1,44 +1,268 @@ | |||
| 1 | use std::{fs::create_dir_all, path::PathBuf}; | 1 | use std::{fs::create_dir_all, path::PathBuf}; |
| 2 | 2 | ||
| 3 | use crate::{config::Config, errors::McError}; | 3 | use crate::{config::Config, constants::directory, errors::McError}; |
| 4 | 4 | ||
| 5 | /// ~/.local/share/dml/minecraft | 5 | /// Returns the path to the root Minecraft directory inside the launcher data folder. |
| 6 | pub fn minecraft_root(cfg: &Config) -> PathBuf { | 6 | /// |
| 7 | /// This directory acts as the root for all Minecraft-related files within the launcher data. | ||
| 8 | /// By default, it joins the `minecraft` directory under the data folder (defined by the launcher). | ||
| 9 | /// | ||
| 10 | /// The returned path does not include any specific assets, versions, or libraries directories. | ||
| 11 | /// You can use this as the base path to construct other Minecraft-related paths. | ||
| 12 | /// | ||
| 13 | /// # Parameters | ||
| 14 | /// - `cfg`: The configuration object (`Config`) containing launcher and Minecraft data folder paths. | ||
| 15 | /// | ||
| 16 | /// # Returns | ||
| 17 | /// - A `PathBuf` pointing to the root Minecraft directory. | ||
| 18 | pub fn root_directory(cfg: &Config) -> PathBuf { | ||
| 19 | // Remove DEFAULT_LAUNCHER_DIR to avoid duplicate "dml/dml" | ||
| 7 | cfg.data_dir.join("minecraft") | 20 | cfg.data_dir.join("minecraft") |
| 8 | } | 21 | } |
| 9 | 22 | ||
| 10 | pub fn assets_dir(cfg: &Config) -> PathBuf { | 23 | /// Returns the path to the Minecraft assets directory. |
| 11 | minecraft_root(cfg).join("assets") | 24 | /// |
| 25 | /// This is where Minecraft assets such as textures, sounds, and other resources are stored. | ||
| 26 | /// The assets directory is located inside the root Minecraft directory and can be used | ||
| 27 | /// for accessing game assets. | ||
| 28 | /// | ||
| 29 | /// # Parameters | ||
| 30 | /// - `cfg`: The configuration object (`Config`) that contains paths for the launcher and Minecraft data. | ||
| 31 | /// | ||
| 32 | /// # Returns | ||
| 33 | /// - A `PathBuf` pointing to the assets directory inside the root Minecraft directory. | ||
| 34 | pub fn assets_directory(cfg: &Config) -> PathBuf { | ||
| 35 | root_directory(cfg).join(directory::ASSETS) | ||
| 12 | } | 36 | } |
| 13 | 37 | ||
| 14 | pub fn game_dir(cfg: &Config) -> PathBuf { minecraft_root(cfg) } | 38 | /// Returns the path to the game directory (same as root directory for now). |
| 15 | pub fn ensure_dirs(cfg: &Config) -> Result<(), McError> { | 39 | /// |
| 16 | let root = minecraft_root(cfg); | 40 | /// The game directory currently points to the same location as the root directory. |
| 17 | create_dir_all(&root)?; | 41 | /// In future iterations, this could be adjusted if game-specific files need to be handled separately. |
| 18 | create_dir_all(root.join("versions"))?; | 42 | /// |
| 19 | create_dir_all(root.join("libraries"))?; | 43 | /// # Parameters |
| 20 | create_dir_all(assets_dir(cfg))?; | 44 | /// - `cfg`: The configuration object (`Config`) that holds the paths to the launcher and Minecraft data. |
| 21 | create_dir_all(assets_dir(cfg).join("indexes"))?; | 45 | /// |
| 22 | create_dir_all(assets_dir(cfg).join("objects"))?; | 46 | /// # Returns |
| 23 | create_dir_all(root.join("saves"))?; | 47 | /// - A `PathBuf` pointing to the game directory, which is the same as the root Minecraft directory for now. |
| 48 | pub fn game_directory(cfg: &Config) -> PathBuf { | ||
| 49 | root_directory(cfg) | ||
| 50 | } | ||
| 51 | |||
| 52 | /// Ensures that all necessary directories for Minecraft are created. | ||
| 53 | /// | ||
| 54 | /// This function checks if essential directories for Minecraft's file structure exist and creates them | ||
| 55 | /// if they do not. This includes directories for versions, libraries, assets, and saves. | ||
| 56 | /// | ||
| 57 | /// # Parameters | ||
| 58 | /// - `cfg`: The configuration object (`Config`) that contains paths for the Minecraft data and the required directories. | ||
| 59 | /// | ||
| 60 | /// # Returns | ||
| 61 | /// - `Ok(())` if all directories are created successfully. | ||
| 62 | /// - `Err(McError)` if an error occurs while creating any directory (such as permission issues). | ||
| 63 | /// | ||
| 64 | /// # Example | ||
| 65 | /// ```rust | ||
| 66 | /// let cfg = Config { /* configuration values */ }; | ||
| 67 | /// ensure_directories(&cfg)?; | ||
| 68 | /// ``` | ||
| 69 | /// | ||
| 70 | /// # Notes | ||
| 71 | /// The function creates several directories under the root Minecraft directory, including: | ||
| 72 | /// - Root directory | ||
| 73 | /// - Versions | ||
| 74 | /// - Libraries | ||
| 75 | /// - Assets (with subdirectories for `indexes` and `objects`) | ||
| 76 | /// - Saves | ||
| 77 | /// Each of these directories is essential for managing Minecraft game data and resources. | ||
| 78 | pub fn ensure_directories(cfg: &Config) -> Result<(), McError> { | ||
| 79 | let root: PathBuf = root_directory(cfg); | ||
| 80 | |||
| 81 | for dir in [ | ||
| 82 | root.clone(), | ||
| 83 | root.join(directory::VERSIONS), | ||
| 84 | root.join(directory::LIBRARIES), | ||
| 85 | assets_directory(cfg), | ||
| 86 | assets_directory(cfg).join(directory::INDEXES), | ||
| 87 | assets_directory(cfg).join(directory::OBJECTS), | ||
| 88 | root.join(directory::SAVES), | ||
| 89 | ] { | ||
| 90 | create_dir_all(dir)?; | ||
| 91 | } | ||
| 24 | 92 | ||
| 25 | Ok(()) | 93 | Ok(()) |
| 26 | } | 94 | } |
| 27 | 95 | ||
| 96 | /// Returns the path to a specific version directory inside the root Minecraft directory. | ||
| 97 | /// | ||
| 98 | /// This directory is where the game version-specific files (such as the `.jar` file) are stored. | ||
| 99 | /// The path is constructed by joining the `versions` directory with the provided version name. | ||
| 100 | /// | ||
| 101 | /// # Parameters | ||
| 102 | /// - `cfg`: The configuration object (`Config`) containing paths for the Minecraft data. | ||
| 103 | /// - `version`: The version of Minecraft (e.g., "1.18.2") to generate the path for. | ||
| 104 | /// | ||
| 105 | /// # Returns | ||
| 106 | /// - A `PathBuf` pointing to the directory for the specified version inside the root Minecraft directory. | ||
| 28 | pub fn version_dir(cfg: &Config, version: &str) -> PathBuf { | 107 | pub fn version_dir(cfg: &Config, version: &str) -> PathBuf { |
| 29 | minecraft_root(cfg).join("versions").join(version) | 108 | root_directory(cfg) |
| 109 | .join(directory::VERSIONS) | ||
| 110 | .join(version) | ||
| 30 | } | 111 | } |
| 31 | 112 | ||
| 32 | pub fn client_jar(cfg: &Config, version: &str) -> Result<PathBuf, McError> { | 113 | /// Returns the path to the client `.jar` file for a specific Minecraft version. |
| 33 | Ok(version_dir(cfg, version).join(format!("{version}.jar"))) | 114 | /// |
| 115 | /// This file is typically used to run the Minecraft client for a particular version. | ||
| 116 | /// The path is constructed by joining the version directory with the name of the `.jar` file. | ||
| 117 | /// | ||
| 118 | /// # Parameters | ||
| 119 | /// - `cfg`: The configuration object (`Config`) containing paths for the Minecraft data. | ||
| 120 | /// - `version`: The version of Minecraft (e.g., "1.18.2") to generate the path for. | ||
| 121 | /// | ||
| 122 | /// # Returns | ||
| 123 | /// - A `PathBuf` pointing to the `.jar` file for the specified version in the version directory. | ||
| 124 | pub fn client_jar(cfg: &Config, version: &str) -> PathBuf { | ||
| 125 | version_dir(cfg, version).join(format!("{version}.jar")) | ||
| 34 | } | 126 | } |
| 35 | 127 | ||
| 36 | pub fn library_file(cfg: &Config, rel_path: &str) -> Result<PathBuf, McError> { | 128 | /// Returns the path to a specific library file inside the library directory. |
| 37 | Ok(minecraft_root(cfg) | 129 | /// |
| 38 | .join("libraries") | 130 | /// This function is used to access library files required for running Minecraft. The `rel_path` |
| 39 | .join(rel_path)) | 131 | /// argument specifies the relative path inside the `libraries` directory. It is useful for handling |
| 132 | /// dependencies or loading required libraries based on the game version. | ||
| 133 | /// | ||
| 134 | /// # Parameters | ||
| 135 | /// - `cfg`: The configuration object (`Config`) that contains paths for the Minecraft data. | ||
| 136 | /// - `rel_path`: The relative path of the library file inside the `libraries` directory. | ||
| 137 | /// | ||
| 138 | /// # Returns | ||
| 139 | /// - A `PathBuf` pointing to the specified library file inside the `libraries` directory. | ||
| 140 | pub fn library_file(cfg: &Config, rel_path: &str) -> PathBuf { | ||
| 141 | root_directory(cfg) | ||
| 142 | .join(directory::LIBRARIES) | ||
| 143 | .join(rel_path) | ||
| 40 | } | 144 | } |
| 41 | 145 | ||
| 146 | /// Returns the path to the natives directory for a specific Minecraft version. | ||
| 147 | /// | ||
| 148 | /// The natives directory contains platform-specific native libraries (e.g., `.dll`, `.so`, `.dylib`) | ||
| 149 | /// that Minecraft uses to run the game. This function returns the path to the directory for the | ||
| 150 | /// specified version. | ||
| 151 | /// | ||
| 152 | /// # Parameters | ||
| 153 | /// - `cfg`: The configuration object (`Config`) containing paths for the Minecraft data. | ||
| 154 | /// - `version`: The version of Minecraft (e.g., "1.18.2") to generate the path for. | ||
| 155 | /// | ||
| 156 | /// # Returns | ||
| 157 | /// - A `PathBuf` pointing to the natives directory for the specified version. | ||
| 42 | pub fn natives_dir(cfg: &Config, version: &str) -> PathBuf { | 158 | pub fn natives_dir(cfg: &Config, version: &str) -> PathBuf { |
| 43 | version_dir(cfg, version).join("natives") | 159 | version_dir(cfg, version).join(directory::NATIVES) |
| 160 | } | ||
| 161 | |||
| 162 | // /// Path to a version’s saves directory. | ||
| 163 | // pub fn saves_dir(cfg: &Config) -> PathBuf { | ||
| 164 | // minecraft_root(cfg).join(dirs::SAVES) | ||
| 165 | // } | ||
| 166 | |||
| 167 | #[cfg(test)] | ||
| 168 | mod tests { | ||
| 169 | use super::*; | ||
| 170 | use std::path::Path; | ||
| 171 | |||
| 172 | fn test_config(tmp: &Path) -> Config { | ||
| 173 | Config { | ||
| 174 | data_dir: tmp.to_path_buf(), | ||
| 175 | ..Default::default() | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | #[test] | ||
| 180 | fn root_directory_is_correct() { | ||
| 181 | let tmp = tempfile::tempdir().unwrap(); | ||
| 182 | let cfg = test_config(tmp.path()); | ||
| 183 | |||
| 184 | let root = root_directory(&cfg); | ||
| 185 | assert_eq!(root, tmp.path().join("minecraft")); | ||
| 186 | } | ||
| 187 | |||
| 188 | #[test] | ||
| 189 | fn assets_directory_is_correct() { | ||
| 190 | let tmp = tempfile::tempdir().unwrap(); | ||
| 191 | let cfg = test_config(tmp.path()); | ||
| 192 | |||
| 193 | let assets = assets_directory(&cfg); | ||
| 194 | assert_eq!(assets, root_directory(&cfg).join(directory::ASSETS)); | ||
| 195 | } | ||
| 196 | |||
| 197 | #[test] | ||
| 198 | fn version_paths_are_correct() { | ||
| 199 | let tmp = tempfile::tempdir().unwrap(); | ||
| 200 | let cfg = test_config(tmp.path()); | ||
| 201 | |||
| 202 | let version = "1.20.1"; | ||
| 203 | assert_eq!( | ||
| 204 | version_dir(&cfg, version), | ||
| 205 | root_directory(&cfg) | ||
| 206 | .join(directory::VERSIONS) | ||
| 207 | .join(version) | ||
| 208 | ); | ||
| 209 | |||
| 210 | assert_eq!( | ||
| 211 | client_jar(&cfg, version), | ||
| 212 | version_dir(&cfg, version).join("1.20.1.jar") | ||
| 213 | ); | ||
| 214 | } | ||
| 215 | |||
| 216 | #[test] | ||
| 217 | fn library_file_path_is_correct() { | ||
| 218 | let tmp = tempfile::tempdir().unwrap(); | ||
| 219 | let cfg = test_config(tmp.path()); | ||
| 220 | |||
| 221 | let rel = "com/example/lib.jar"; | ||
| 222 | assert_eq!( | ||
| 223 | library_file(&cfg, rel), | ||
| 224 | root_directory(&cfg) | ||
| 225 | .join(directory::LIBRARIES) | ||
| 226 | .join(rel) | ||
| 227 | ); | ||
| 228 | } | ||
| 229 | |||
| 230 | #[test] | ||
| 231 | fn natives_dir_path_is_correct() { | ||
| 232 | let tmp = tempfile::tempdir().unwrap(); | ||
| 233 | let cfg = test_config(tmp.path()); | ||
| 234 | |||
| 235 | let version = "1.20.1"; | ||
| 236 | assert_eq!( | ||
| 237 | natives_dir(&cfg, version), | ||
| 238 | version_dir(&cfg, version).join(directory::NATIVES) | ||
| 239 | ); | ||
| 240 | } | ||
| 241 | |||
| 242 | #[test] | ||
| 243 | fn ensure_directories_creates_structure() { | ||
| 244 | let tmp = tempfile::tempdir().unwrap(); | ||
| 245 | let cfg = test_config(tmp.path()); | ||
| 246 | |||
| 247 | ensure_directories(&cfg).unwrap(); | ||
| 248 | |||
| 249 | let root = root_directory(&cfg); | ||
| 250 | |||
| 251 | let expected_dirs = [ | ||
| 252 | root.clone(), | ||
| 253 | root.join(directory::VERSIONS), | ||
| 254 | root.join(directory::LIBRARIES), | ||
| 255 | root.join(directory::ASSETS), | ||
| 256 | root.join(directory::ASSETS) | ||
| 257 | .join(directory::INDEXES), | ||
| 258 | root.join(directory::ASSETS) | ||
| 259 | .join(directory::OBJECTS), | ||
| 260 | root.join(directory::SAVES), | ||
| 261 | ]; | ||
| 262 | |||
| 263 | for dir in expected_dirs { | ||
| 264 | assert!(dir.exists(), "Missing directory: {:?}", dir); | ||
| 265 | assert!(dir.is_dir()); | ||
| 266 | } | ||
| 267 | } | ||
| 44 | } | 268 | } |
