Skip to main content

tidepool_gvm/
config.rs

1use anyhow::Result;
2use std::env;
3use std::path::{Path, PathBuf};
4
5/// Configuration manager for GVM
6///
7/// Handles configuration paths with the following priority:
8/// 1. Environment variables
9/// 2. Default configuration
10#[derive(Debug, Clone)]
11#[allow(clippy::struct_field_names)]
12pub struct Config {
13    /// Root directory for GVM installation
14    pub root_path: PathBuf,
15    /// Directory containing installed Go versions
16    pub versions_path: PathBuf,
17    /// Directory for cached downloads
18    pub cache_path: PathBuf,
19}
20
21impl Config {
22    /// Initialize configuration from environment variables and defaults
23    /// Creates a new configuration.
24    ///
25    /// # Errors
26    /// Returns an error if the configuration directories cannot be created.
27    pub fn new() -> Result<Self> {
28        let root_path = Self::resolve_root_path()?;
29        let versions_path = Self::resolve_versions_path(&root_path);
30        let cache_path = Self::resolve_cache_path(&root_path);
31        Ok(Config { root_path, versions_path, cache_path })
32    }
33
34    /// Get the GVM root path
35    ///
36    /// Priority: Environment variable `GVM_ROOT_PATH` -> Default (~/.gvm)
37    fn resolve_root_path() -> Result<PathBuf> {
38        if let Ok(env_path) = env::var("GVM_ROOT_PATH") {
39            return Ok(PathBuf::from(env_path));
40        }
41
42        let home_dir = std::env::var("USERPROFILE")
43            .or_else(|_| std::env::var("HOME"))
44            .map(PathBuf::from)
45            .map_err(|_| anyhow::anyhow!("Unable to get user home directory"))?;
46        Ok(home_dir.join(".gvm"))
47    }
48
49    /// Get the versions directory path
50    ///
51    /// Priority: Environment variable `GVM_VERSIONS_PATH` -> Default (`$GVM_ROOT_PATH/versions`)
52    fn resolve_versions_path(root_path: &Path) -> PathBuf {
53        if let Ok(env_path) = env::var("GVM_VERSIONS_PATH") {
54            return PathBuf::from(env_path);
55        }
56        root_path.join("versions")
57    }
58
59    /// Get the cache directory path
60    ///
61    /// Priority: Environment variable `GVM_CACHE_PATH` -> Default (`$GVM_ROOT_PATH/cache`)
62    fn resolve_cache_path(root_path: &Path) -> PathBuf {
63        if let Ok(env_path) = env::var("GVM_CACHE_PATH") {
64            return PathBuf::from(env_path);
65        }
66        root_path.join("cache")
67    }
68
69    /// Get the versions path
70    #[must_use]
71    pub fn versions(&self) -> &PathBuf {
72        &self.versions_path
73    }
74
75    /// Get the cache path
76    #[must_use]
77    pub fn cache(&self) -> &PathBuf {
78        &self.cache_path
79    }
80
81    /// Ensure all configuration directories exist
82    /// Ensure that required directories exist.
83    ///
84    /// # Errors
85    /// Returns an error if the directories cannot be created.
86    pub fn ensure_directories(&self) -> Result<()> {
87        use std::fs;
88
89        // Create root directory
90        if !self.root_path.exists() {
91            fs::create_dir_all(&self.root_path).map_err(|e| {
92                anyhow::anyhow!(
93                    "Failed to create root directory {}: {}",
94                    self.root_path.display(),
95                    e
96                )
97            })?;
98        }
99
100        // Create versions directory
101        if !self.versions_path.exists() {
102            fs::create_dir_all(&self.versions_path).map_err(|e| {
103                anyhow::anyhow!(
104                    "Failed to create versions directory {}: {}",
105                    self.versions_path.display(),
106                    e
107                )
108            })?;
109        }
110
111        // Create cache directory
112        if !self.cache_path.exists() {
113            fs::create_dir_all(&self.cache_path).map_err(|e| {
114                anyhow::anyhow!(
115                    "Failed to create cache directory {}: {}",
116                    self.cache_path.display(),
117                    e
118                )
119            })?;
120        }
121
122        Ok(())
123    }
124}