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