Skip to main content

vx_paths/
config.rs

1//! Configuration for path management
2
3use crate::{PathManager, VxPaths};
4use anyhow::Result;
5use serde::{Deserialize, Serialize};
6use std::path::{Path, PathBuf};
7
8/// Configuration for path management
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct PathConfig {
11    /// Custom base directory for vx installations
12    pub base_dir: Option<PathBuf>,
13    /// Custom tools directory
14    pub tools_dir: Option<PathBuf>,
15    /// Custom cache directory
16    pub cache_dir: Option<PathBuf>,
17    /// Custom config directory
18    pub config_dir: Option<PathBuf>,
19    /// Custom temporary directory
20    pub tmp_dir: Option<PathBuf>,
21}
22
23impl PathConfig {
24    /// Create a new PathConfig with default values
25    pub fn new() -> Self {
26        Self {
27            base_dir: None,
28            tools_dir: None,
29            cache_dir: None,
30            config_dir: None,
31            tmp_dir: None,
32        }
33    }
34
35    /// Create PathConfig with custom base directory
36    pub fn with_base_dir<P: AsRef<Path>>(base_dir: P) -> Self {
37        Self {
38            base_dir: Some(base_dir.as_ref().to_path_buf()),
39            tools_dir: None,
40            cache_dir: None,
41            config_dir: None,
42            tmp_dir: None,
43        }
44    }
45
46    /// Create a PathManager from this configuration
47    pub fn create_path_manager(&self) -> Result<PathManager> {
48        let paths = self.create_vx_paths()?;
49        paths.ensure_dirs()?;
50        Ok(PathManager::from_paths(paths))
51    }
52
53    /// Create VxPaths from this configuration
54    pub fn create_vx_paths(&self) -> Result<VxPaths> {
55        let default_paths = if let Some(base_dir) = &self.base_dir {
56            VxPaths::with_base_dir(base_dir)
57        } else {
58            VxPaths::new()?
59        };
60
61        Ok(VxPaths {
62            base_dir: self.base_dir.clone().unwrap_or(default_paths.base_dir),
63            tools_dir: self.tools_dir.clone().unwrap_or(default_paths.tools_dir),
64            cache_dir: self.cache_dir.clone().unwrap_or(default_paths.cache_dir),
65            config_dir: self.config_dir.clone().unwrap_or(default_paths.config_dir),
66            tmp_dir: self.tmp_dir.clone().unwrap_or(default_paths.tmp_dir),
67        })
68    }
69
70    /// Load configuration from environment variables
71    pub fn from_env() -> Self {
72        Self {
73            base_dir: std::env::var("VX_BASE_DIR").ok().map(PathBuf::from),
74            tools_dir: std::env::var("VX_TOOLS_DIR").ok().map(PathBuf::from),
75            cache_dir: std::env::var("VX_CACHE_DIR").ok().map(PathBuf::from),
76            config_dir: std::env::var("VX_CONFIG_DIR").ok().map(PathBuf::from),
77            tmp_dir: std::env::var("VX_TMP_DIR").ok().map(PathBuf::from),
78        }
79    }
80
81    /// Merge with another PathConfig, preferring values from other
82    pub fn merge(&mut self, other: &PathConfig) {
83        if other.base_dir.is_some() {
84            self.base_dir = other.base_dir.clone();
85        }
86        if other.tools_dir.is_some() {
87            self.tools_dir = other.tools_dir.clone();
88        }
89        if other.cache_dir.is_some() {
90            self.cache_dir = other.cache_dir.clone();
91        }
92        if other.config_dir.is_some() {
93            self.config_dir = other.config_dir.clone();
94        }
95        if other.tmp_dir.is_some() {
96            self.tmp_dir = other.tmp_dir.clone();
97        }
98    }
99}
100impl Default for PathConfig {
101    fn default() -> Self {
102        Self::new()
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109    use tempfile::TempDir;
110
111    #[test]
112    fn test_path_config_creation() {
113        let config = PathConfig::new();
114        assert!(config.base_dir.is_none());
115        assert!(config.tools_dir.is_none());
116
117        let temp_dir = TempDir::new().unwrap();
118        let config = PathConfig::with_base_dir(temp_dir.path());
119        assert_eq!(config.base_dir, Some(temp_dir.path().to_path_buf()));
120    }
121
122    #[test]
123    fn test_path_config_merge() {
124        let mut config1 = PathConfig::new();
125        let config2 = PathConfig::with_base_dir("/custom/path");
126
127        config1.merge(&config2);
128        assert_eq!(config1.base_dir, Some(PathBuf::from("/custom/path")));
129    }
130
131    #[test]
132    fn test_create_path_manager() {
133        let temp_dir = TempDir::new().unwrap();
134        let config = PathConfig::with_base_dir(temp_dir.path());
135        let manager = config.create_path_manager().unwrap();
136
137        assert!(manager.tools_dir().exists());
138        assert!(manager.cache_dir().exists());
139    }
140
141    #[test]
142    fn test_from_env() {
143        std::env::set_var("VX_BASE_DIR", "/test/base");
144        std::env::set_var("VX_TOOLS_DIR", "/test/tools");
145
146        let config = PathConfig::from_env();
147        assert_eq!(config.base_dir, Some(PathBuf::from("/test/base")));
148        assert_eq!(config.tools_dir, Some(PathBuf::from("/test/tools")));
149
150        std::env::remove_var("VX_BASE_DIR");
151        std::env::remove_var("VX_TOOLS_DIR");
152    }
153}